#include "usbdevice.h" #include "CustomWidgets/informationbox.h" #include #include #include #include #include using namespace std; using USBID = struct { int VID; int PID; }; static constexpr USBID IDs[] = { {0x0483, 0x4122}, }; USBDevice::USBDevice(QString serial) { m_handle = nullptr; libusb_init(&m_context); #if LIBUSB_API_VERSION >= 0x01000106 libusb_set_option(m_context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); #endif SearchDevices([=](libusb_device_handle *handle, QString found_serial) -> bool { if(serial.isEmpty() || serial == found_serial) { // accept connection to this device m_serial = found_serial; m_handle = handle; // abort device search return false; } else { // not the requested device, continue search return true; } }, m_context, false); if(!m_handle) { QString message = "No device found"; if(!serial.isEmpty()) { // only show error message if specific device was requested InformationBox::ShowError("Error opening device", message); } libusb_exit(m_context); throw std::runtime_error(message.toStdString()); return; } // Found the correct device, now connect /* claim the interface */ int ret = libusb_claim_interface(m_handle, 2); if (ret < 0) { libusb_close(m_handle); /* Failed to open */ QString message = "Failed to claim interface: \""; message.append(libusb_strerror((libusb_error) ret)); message.append("\" Maybe you are already connected to this device?"); qWarning() << message; InformationBox::ShowError("Error opening device", message); libusb_exit(m_context); throw std::runtime_error(message.toStdString()); } qInfo() << "USB connection established" << flush; } USBDevice::~USBDevice() { libusb_release_interface(m_handle, 2); libusb_close(m_handle); libusb_exit(m_context); } bool USBDevice::Cmd(QString cmd) { QString rcv; bool success = send(cmd) && receive(&rcv); if(success && rcv == "") { // empty response expected by commad return true; } else { // failed to send/receive emit communicationFailure(); return false; } } QString USBDevice::Query(QString query) { if(send(query)) { QString rcv; if(receive(&rcv)) { return rcv; } else { emit communicationFailure(); } } else { emit communicationFailure(); } return QString(); } std::set USBDevice::GetDevices() { std::set serials; libusb_context *ctx; libusb_init(&ctx); #if LIBUSB_API_VERSION >= 0x01000106 libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); #endif SearchDevices([&serials](libusb_device_handle *, QString serial) -> bool { serials.insert(serial); return true; }, ctx, true); libusb_exit(ctx); return serials; } void USBDevice::SearchDevices(std::function foundCallback, libusb_context *context, bool ignoreOpenError) { libusb_device **devList; auto ndevices = libusb_get_device_list(context, &devList); for (ssize_t idx = 0; idx < ndevices; idx++) { int ret; libusb_device *device = devList[idx]; libusb_device_descriptor desc = {}; ret = libusb_get_device_descriptor(device, &desc); if (ret) { /* some error occured */ qCritical() << "Failed to get device descriptor: " << libusb_strerror((libusb_error) ret); continue; } bool correctID = false; int numIDs = sizeof(IDs)/sizeof(IDs[0]); for(int i=0;i 0) { /* managed to read the product string */ QString product(c_product); if (product == "LibreCAL") { // this is a match if(!foundCallback(handle, QString(c_serial))) { // abort search break; } } } else { qWarning() << "Failed to get product descriptor: " << libusb_strerror((libusb_error) ret); } libusb_close(handle); } libusb_free_device_list(devList, 1); } bool USBDevice::send(const QString &s) { // qDebug() << "Send:"<