From 6f717de0f15057051bdeb318fea5fa039004d1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Mon, 16 Nov 2020 13:38:52 +0100 Subject: [PATCH] work around WinUSB limitation of only one open device handle --- Software/PC_Application/Device/device.cpp | 61 +++++++++++-------- Software/PC_Application/Device/device.h | 2 +- Software/PC_Application/appwindow.cpp | 3 + .../Application/Drivers/USB/usb.c | 4 +- Software/VNA_embedded/VNA_embedded Debug.cfg | 36 +++++++++++ 5 files changed, 79 insertions(+), 27 deletions(-) create mode 100644 Software/VNA_embedded/VNA_embedded Debug.cfg diff --git a/Software/PC_Application/Device/device.cpp b/Software/PC_Application/Device/device.cpp index d61d2ec..86693ea 100644 --- a/Software/PC_Application/Device/device.cpp +++ b/Software/PC_Application/Device/device.cpp @@ -80,6 +80,7 @@ void USBInBuffer::Callback(libusb_transfer *transfer) case LIBUSB_TRANSFER_STALL: qCritical() << "LIBUSB_ERROR" << transfer->status; libusb_free_transfer(transfer); + this->transfer = nullptr; emit TransferError(); return; break; @@ -146,6 +147,9 @@ Device::Device(QString serial) m_handle = nullptr; lastInfoValid = false; 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) { @@ -158,7 +162,7 @@ Device::Device(QString serial) // not the requested device, continue search return true; } - }, m_context); + }, m_context, false); if(!m_handle) { QString message = "No device found"; @@ -170,21 +174,19 @@ Device::Device(QString serial) } // Found the correct device, now connect - /* claim the interfaces */ - for (int if_num = 0; if_num < 1; if_num++) { - int ret = libusb_claim_interface(m_handle, if_num); - 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; - auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); - msg->exec(); - libusb_exit(m_context); - throw std::runtime_error(message.toStdString()); - } + /* claim the interface */ + int ret = libusb_claim_interface(m_handle, 0); + 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; + auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); + msg->exec(); + libusb_exit(m_context); + throw std::runtime_error(message.toStdString()); } qInfo() << "USB connection established" << flush; m_connected = true; @@ -215,6 +217,7 @@ Device::~Device() qCritical() << "Error releasing interface" << libusb_error_name(ret); } } + libusb_release_interface(m_handle, 0); libusb_close(m_handle); m_receiveThread->join(); libusb_exit(m_context); @@ -287,11 +290,14 @@ std::set Device::GetDevices() 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); + }, ctx, true); libusb_exit(ctx); @@ -307,7 +313,7 @@ void Device::USBHandleThread() qDebug() << "Disconnected, receive thread exiting"; } -void Device::SearchDevices(std::function foundCallback, libusb_context *context) +void Device::SearchDevices(std::function foundCallback, libusb_context *context, bool ignoreOpenError) { libusb_device **devList; auto ndevices = libusb_get_device_list(context, &devList); @@ -341,13 +347,19 @@ void Device::SearchDevices(std::function libusb_device_handle *handle = nullptr; ret = libusb_open(device, &handle); if (ret) { + qDebug() << libusb_strerror((enum libusb_error) ret); /* Failed to open */ - QString message = "Found potential device but failed to open usb connection: \""; - message.append(libusb_strerror((libusb_error) ret)); - message.append("\" On Linux this is most likely caused by a missing udev rule. On Windows it could be a missing driver. Try installing the WinUSB driver using Zadig (https://zadig.akeo.ie/)"); - qWarning() << message; - auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); - msg->exec(); + if(!ignoreOpenError) { + QString message = "Found potential device but failed to open usb connection: \""; + message.append(libusb_strerror((libusb_error) ret)); + message.append("\" On Linux this is most likely caused by a missing udev rule. " + "On Windows this most likely means that you are already connected to " + "this device (is another instance of the application already runnning? " + "If that is not the case, you can try installing the WinUSB driver using Zadig (https://zadig.akeo.ie/)"); + qWarning() << message; + auto msg = new QMessageBox(QMessageBox::Icon::Warning, "Error opening device", message); + msg->exec(); + } continue; } @@ -408,6 +420,7 @@ void Device::ReceivedData() { Protocol::PacketInfo packet; uint16_t handled_len; +// qDebug() << "Received data"; do { handled_len = Protocol::DecodeBuffer(dataBuffer->getBuffer(), dataBuffer->getReceived(), &packet); dataBuffer->removeBytes(handled_len); diff --git a/Software/PC_Application/Device/device.h b/Software/PC_Application/Device/device.h index 586c496..c57e0df 100644 --- a/Software/PC_Application/Device/device.h +++ b/Software/PC_Application/Device/device.h @@ -98,7 +98,7 @@ private: void USBHandleThread(); // foundCallback is called for every device that is found. If it returns true the search continues, otherwise it is aborted. // When the search is aborted the last found device is still opened - static void SearchDevices(std::function foundCallback, libusb_context *context); + static void SearchDevices(std::function foundCallback, libusb_context *context, bool ignoreOpenError); libusb_device_handle *m_handle; libusb_context *m_context; diff --git a/Software/PC_Application/appwindow.cpp b/Software/PC_Application/appwindow.cpp index b4f3b6c..115eb9b 100644 --- a/Software/PC_Application/appwindow.cpp +++ b/Software/PC_Application/appwindow.cpp @@ -263,6 +263,9 @@ int AppWindow::UpdateDeviceList() deviceActionGroup->setExclusive(true); ui->menuConnect_to->clear(); auto devices = Device::GetDevices(); + if(device) { + devices.insert(device->serial()); + } if(devices.size()) { for(auto d : devices) { auto connectAction = ui->menuConnect_to->addAction(d); diff --git a/Software/VNA_embedded/Application/Drivers/USB/usb.c b/Software/VNA_embedded/Application/Drivers/USB/usb.c index 0cd1891..1e590dd 100644 --- a/Software/VNA_embedded/Application/Drivers/USB/usb.c +++ b/Software/VNA_embedded/Application/Drivers/USB/usb.c @@ -110,7 +110,7 @@ __ALIGN_BEGIN uint8_t USBD_CfgFSDesc[USB_CONFIG_DESC_SIZ] __ALIGN_END = // See https://github.com/pbatard/libwdi/wiki/WCID-Devices for descriptor data // This requests to load the WinUSB driver for this device -__ALIGN_BEGIN const uint8_t USBD_MicrosoftCompatibleID[40] __ALIGN_END = +__ALIGN_BEGIN const char USBD_MicrosoftCompatibleID[40] __ALIGN_END = { 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, @@ -119,7 +119,7 @@ __ALIGN_BEGIN const uint8_t USBD_MicrosoftCompatibleID[40] __ALIGN_END = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, + 'W','I','N','U','S','B','\0','\0', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/Software/VNA_embedded/VNA_embedded Debug.cfg b/Software/VNA_embedded/VNA_embedded Debug.cfg new file mode 100644 index 0000000..9abf4c7 --- /dev/null +++ b/Software/VNA_embedded/VNA_embedded Debug.cfg @@ -0,0 +1,36 @@ +# This is an VNA_embedded board with a single STM32G431CBUx chip +# +# Generated by System Workbench for STM32 +# Take care that such file, as generated, may be overridden without any early notice. Please have a look to debug launch configuration setup(s) + +source [find interface/stlink.cfg] + +set WORKAREASIZE 0x5800 + +transport select "hla_swd" + +set CHIPNAME STM32G431CBUx +set BOARDNAME VNA_embedded + +# CHIPNAMES state +set CHIPNAME_CPU0_ACTIVATED 1 + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate connect_assert_srst +set CONNECT_UNDER_RESET 1 + +# BCTM CPU variables + + + +source [find target/stm32g4x.cfg]