From 6024cd7c215f255ba3c5dea039a73d57e781a464 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 00:14:41 +0100 Subject: [PATCH 01/12] whb04b: Try to improve error handling --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 55 ++++++++++++------- src/hal/user_comps/xhc-whb04b-6/usb.h | 7 ++- .../user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 37 +++++++------ 3 files changed, 62 insertions(+), 37 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index b3ddc899702..5d2d8beb554 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -462,7 +462,9 @@ bool Usb::setupAsyncTransfer() //! timeout[ms] 750); int r = libusb_submit_transfer(inTransfer); - assert(0 == r); + if(r != 0){ + std::cerr << "libusb_submit_transfer failed with " << r << endl; + } return (0 == r); } // ---------------------------------------------------------------------- @@ -538,7 +540,10 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) if (mIsRunning) { - setupAsyncTransfer(); + if(!setupAsyncTransfer()) + { + requestTermination(); + } } break; @@ -547,7 +552,10 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) case (LIBUSB_TRANSFER_TIMED_OUT): if (mIsRunning) { - setupAsyncTransfer(); + if(!setupAsyncTransfer()) + { + requestTermination(); + } } break; @@ -610,7 +618,7 @@ void Usb::enableVerboseInit(bool enable) } } // ---------------------------------------------------------------------- -bool Usb::init() +Usb::InitStatus Usb::init() { if (getDoReconnect()) { @@ -626,11 +634,11 @@ bool Usb::init() } *verboseInitOut << "init usb context ..."; - int r = libusb_init(&context); + int r = libusb_init(&context); //This function is deprecated. However, Debian 12 doesn't have it, so we leave it in for now. if (r != 0) { std::cerr << endl << "failed to initialize usb context" << endl; - return false; + return InitStatus::RETRY; } *verboseInitOut << " ok" << endl; @@ -664,13 +672,13 @@ bool Usb::init() if (devicesCount < 0) { std::cerr << endl << "failed to get device list" << endl; - return false; + return InitStatus::RETRY; } deviceHandle = libusb_open_device_with_vid_pid(context, usbVendorId, usbProductId); libusb_free_device_list(devicesReference, 1); *verboseInitOut << "." << std::flush; - if (!isDeviceOpen()) + if (deviceHandle == nullptr) { *verboseInitOut << "." << std::flush; if (isWaitWithTimeout) @@ -678,39 +686,48 @@ bool Usb::init() *verboseInitOut << "." << std::flush; if ((mWaitSecs--) <= 0) { - std::cerr << endl << "timeout exceeded, exiting" << endl; - return false; + std::cerr << endl << "Configured timeout exceeded, exiting" << endl; + return InitStatus::EXIT; } } sleep(1); } - } while (!isDeviceOpen() && mIsRunning); + } while (deviceHandle == nullptr && mIsRunning); *verboseInitOut << " ok" << endl << "init " << mName << " device found" << endl; - if (isDeviceOpen()) + if (deviceHandle != nullptr) { *verboseInitOut << "init detaching active kernel driver ..."; - if (libusb_kernel_driver_active(deviceHandle, 0) == 1) + r = libusb_kernel_driver_active(deviceHandle, 0); + if (r == 1) { - int r = libusb_detach_kernel_driver(deviceHandle, 0); - assert(0 == r); + r = libusb_detach_kernel_driver(deviceHandle, 0); + if(r < 0){ + std::cerr << "libusb_detach_kernel_driver failed with " << r << endl; + return InitStatus::RETRY; + } *verboseInitOut << " ok" << endl; } - else + else if(r == 0) { *verboseInitOut << " already detached" << endl; } + else + { + std::cerr << "libusb_kernel_driver_active failed with " << r << endl; + return InitStatus::RETRY; + } *verboseInitOut << "init claiming interface ..."; - int r = libusb_claim_interface(deviceHandle, 0); + r = libusb_claim_interface(deviceHandle, 0); if (r != 0) { std::cerr << endl << "failed to claim interface" << endl; - return false; + return InitStatus::RETRY; } *verboseInitOut << " ok" << endl; } - return true; + return InitStatus::OK; } // ---------------------------------------------------------------------- void Usb::setWaitWithTimeout(uint8_t waitSecs) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.h b/src/hal/user_comps/xhc-whb04b-6/usb.h index 9902d0105eb..bbf1855a0c1 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.h +++ b/src/hal/user_comps/xhc-whb04b-6/usb.h @@ -274,6 +274,11 @@ class SleepDetect class Usb : public UsbRawInputListener { public: + enum class InitStatus{ + EXIT, //Program should exit + RETRY, //Program should retry + OK //All fine + }; static const ConstantUsbPackages ConstantPackages; //! \param name device string used for printing messages //! \param onDataReceivedCallback called when received data is ready @@ -302,7 +307,7 @@ class Usb : public UsbRawInputListener void enableVerboseTx(bool enable); void enableVerboseRx(bool enable); void enableVerboseInit(bool enable); - bool init(); + InitStatus init(); void setWaitWithTimeout(uint8_t waitSecs); UsbOutPackageData& getOutputPackageData(); diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index 367a4726997..fe36fbf678a 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -433,31 +433,34 @@ int XhcWhb04b6Component::run() mHal.setIsPendantConnected(false); initWhb(); - if (!mUsb.init()) + Usb::InitStatus status = mUsb.init(); + if (status == Usb::InitStatus::EXIT) { return EXIT_FAILURE; } - - mHal.setIsPendantConnected(true); - - if (!isHalReady && !mHal.isSimulationModeEnabled()) + else if(status == Usb::InitStatus::OK) { - hal_ready(mHal.getHalComponentId()); - isHalReady = true; - } + mHal.setIsPendantConnected(true); - if (mUsb.isDeviceOpen()) - { - *mInitCout << "init enabling reception ..."; - if (!enableReceiveAsyncTransfer()) + if (!isHalReady && !mHal.isSimulationModeEnabled()) + { + hal_ready(mHal.getHalComponentId()); + isHalReady = true; + } + + if (mUsb.isDeviceOpen()) { - std::cerr << endl << "failed to enable reception" << endl; - return EXIT_FAILURE; + *mInitCout << "init enabling reception ..."; + if (!enableReceiveAsyncTransfer()) + { + std::cerr << endl << "failed to enable reception" << endl; + return EXIT_FAILURE; + } + *mInitCout << " ok" << endl; } - *mInitCout << " ok" << endl; + process(); + teardownUsb(); } - process(); - teardownUsb(); } teardownHal(); From 010897fded9b8ca1c0add53b46bcd06e11f886b4 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 09:53:53 +0100 Subject: [PATCH 02/12] whb04b: Cleanup XhcWhb04b6Component should not even include libusb --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 52 ++++++++++--------- src/hal/user_comps/xhc-whb04b-6/usb.h | 8 ++- .../user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 42 ++------------- src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h | 3 -- 4 files changed, 33 insertions(+), 72 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 5d2d8beb554..028f715ba6b 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -140,31 +140,6 @@ bool Usb::isDeviceOpen() const return deviceHandle != nullptr; } // ---------------------------------------------------------------------- -libusb_context** Usb::getContextReference() -{ - return &context; -} -// ---------------------------------------------------------------------- -libusb_context* Usb::getContext() -{ - return context; -} -// ---------------------------------------------------------------------- -void Usb::setContext(libusb_context* context) -{ - this->context = context; -} -// ---------------------------------------------------------------------- -libusb_device_handle* Usb::getDeviceHandle() -{ - return deviceHandle; -} -// ---------------------------------------------------------------------- -void Usb::setDeviceHandle(libusb_device_handle* deviceHandle) -{ - this->deviceHandle = deviceHandle; -} -// ---------------------------------------------------------------------- bool Usb::isWaitForPendantBeforeHalEnabled() const { return isWaitWithTimeout; @@ -729,6 +704,33 @@ Usb::InitStatus Usb::init() } return InitStatus::OK; } +void Usb::handleTimeouts() +{ + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 200 * 1000; + + int r = libusb_handle_events_timeout_completed(context, &timeout, nullptr); + assert((r == LIBUSB_SUCCESS) || (r == LIBUSB_ERROR_NO_DEVICE) || (r == LIBUSB_ERROR_BUSY) || + (r == LIBUSB_ERROR_TIMEOUT) || (r == LIBUSB_ERROR_INTERRUPTED)); +} +void Usb::close() +{ + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + int r = libusb_handle_events_timeout_completed(context, &tv, nullptr); + assert(0 == r); + r = libusb_release_interface(deviceHandle, 0); + assert((0 == r) || (r == LIBUSB_ERROR_NO_DEVICE)); + libusb_close(deviceHandle); + deviceHandle = nullptr; +} +void Usb::teardown() +{ + libusb_exit(context); + context = nullptr; +} // ---------------------------------------------------------------------- void Usb::setWaitWithTimeout(uint8_t waitSecs) { diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.h b/src/hal/user_comps/xhc-whb04b-6/usb.h index bbf1855a0c1..c02719960b9 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.h +++ b/src/hal/user_comps/xhc-whb04b-6/usb.h @@ -288,11 +288,6 @@ class Usb : public UsbRawInputListener uint16_t getUsbProductId() const; void setUsbProductId(uint16_t usbProductId); bool isDeviceOpen() const; - libusb_context** getContextReference(); - libusb_context* getContext(); - void setContext(libusb_context* context); - libusb_device_handle* getDeviceHandle(); - void setDeviceHandle(libusb_device_handle* deviceHandle); bool isWaitForPendantBeforeHalEnabled() const; bool getDoReconnect() const; void setDoReconnect(bool doReconnect); @@ -308,6 +303,9 @@ class Usb : public UsbRawInputListener void enableVerboseRx(bool enable); void enableVerboseInit(bool enable); InitStatus init(); + void handleTimeouts(); + void close(); + void teardown(); void setWaitWithTimeout(uint8_t waitSecs); UsbOutPackageData& getOutputPackageData(); diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index fe36fbf678a..9042a0f59cf 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include @@ -459,7 +458,7 @@ int XhcWhb04b6Component::run() *mInitCout << " ok" << endl; } process(); - teardownUsb(); + mUsb.teardown(); } } teardownHal(); @@ -483,34 +482,13 @@ void XhcWhb04b6Component::setSimulationMode(bool enableSimulationMode) mUsb.setSimulationMode(mIsSimulationMode); } // ---------------------------------------------------------------------- -void XhcWhb04b6Component::setUsbContext(libusb_context* context) -{ - mUsb.setContext(context); -} -// ---------------------------------------------------------------------- -libusb_device_handle* XhcWhb04b6Component::getUsbDeviceHandle() -{ - return mUsb.getDeviceHandle(); -} -// ---------------------------------------------------------------------- -libusb_context* XhcWhb04b6Component::getUsbContext() -{ - return mUsb.getContext(); -} -// ---------------------------------------------------------------------- void XhcWhb04b6Component::process() { if (mUsb.isDeviceOpen()) { while (isRunning() && !mUsb.getDoReconnect()) { - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 200 * 1000; - - int r = libusb_handle_events_timeout_completed(getUsbContext(), &timeout, nullptr); - assert((r == LIBUSB_SUCCESS) || (r == LIBUSB_ERROR_NO_DEVICE) || (r == LIBUSB_ERROR_BUSY) || - (r == LIBUSB_ERROR_TIMEOUT) || (r == LIBUSB_ERROR_INTERRUPTED)); + mUsb.handleTimeouts(); if (mHal.isSimulationModeEnabled()) { linuxcncSimulate(); @@ -521,24 +499,10 @@ void XhcWhb04b6Component::process() mHal.setIsPendantConnected(false); *mInitCout << "connection lost, cleaning up" << endl; - struct timeval tv; - tv.tv_sec = 1; - tv.tv_usec = 0; - int r = libusb_handle_events_timeout_completed(getUsbContext(), &tv, nullptr); - assert(0 == r); - r = libusb_release_interface(getUsbDeviceHandle(), 0); - assert((0 == r) || (r == LIBUSB_ERROR_NO_DEVICE)); - libusb_close(getUsbDeviceHandle()); - mUsb.setDeviceHandle(nullptr); + mUsb.close(); } } // ---------------------------------------------------------------------- -void XhcWhb04b6Component::teardownUsb() -{ - libusb_exit(getUsbContext()); - mUsb.setContext(nullptr); -} -// ---------------------------------------------------------------------- void XhcWhb04b6Component::enableVerbosePendant(bool enable) { mPendant.enableVerbose(enable); diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h index 3399685a6b6..07e01a090e4 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h @@ -42,9 +42,6 @@ class XhcWhb04b6Component : virtual ~XhcWhb04b6Component(); void process(); void teardownUsb(); - void setUsbContext(libusb_context* context); - libusb_device_handle* getUsbDeviceHandle(); - libusb_context* getUsbContext(); //! \return the name as specified to \ref XhcWhb04b6Component const char* getName() const; //! \return the name as specified to \ref Hal From 27c69527fd994f81b8ac32169ad32e0ccb189730 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 10:02:48 +0100 Subject: [PATCH 03/12] whb04b: Remove unneccesary code --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 19 ++----------------- src/hal/user_comps/xhc-whb04b-6/usb.h | 3 --- .../user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 7 +------ src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h | 1 - 4 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 028f715ba6b..e2dad2085e7 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -125,16 +125,6 @@ ConstantUsbPackages::ConstantUsbPackages() : { } // ---------------------------------------------------------------------- -uint16_t Usb::getUsbVendorId() const -{ - return usbVendorId; -} -// ---------------------------------------------------------------------- -uint16_t Usb::getUsbProductId() const -{ - return usbProductId; -} -// ---------------------------------------------------------------------- bool Usb::isDeviceOpen() const { return deviceHandle != nullptr; @@ -150,11 +140,6 @@ bool Usb::getDoReconnect() const return mDoReconnect; } // ---------------------------------------------------------------------- -void Usb::setDoReconnect(bool doReconnect) -{ - this->mDoReconnect = doReconnect; -} -// ---------------------------------------------------------------------- void Usb::setUsbProductId(uint16_t usbProductId) { this->usbProductId = usbProductId; @@ -215,7 +200,7 @@ void Usb::sendDisplayData() if (r < 0) { std::cerr << "transmission failed, try to reconnect ..." << endl; - setDoReconnect(true); + mDoReconnect = true; return; } } @@ -604,7 +589,7 @@ Usb::InitStatus Usb::init() *verboseInitOut << "." << std::flush; sleep(1); } - setDoReconnect(false); + mDoReconnect=false; *verboseInitOut << " done" << endl; } diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.h b/src/hal/user_comps/xhc-whb04b-6/usb.h index c02719960b9..d78fe43bcef 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.h +++ b/src/hal/user_comps/xhc-whb04b-6/usb.h @@ -284,13 +284,10 @@ class Usb : public UsbRawInputListener //! \param onDataReceivedCallback called when received data is ready Usb(const char* name, OnUsbInputPackageListener& onDataReceivedCallback, Hal &hal); ~Usb(); - uint16_t getUsbVendorId() const; - uint16_t getUsbProductId() const; void setUsbProductId(uint16_t usbProductId); bool isDeviceOpen() const; bool isWaitForPendantBeforeHalEnabled() const; bool getDoReconnect() const; - void setDoReconnect(bool doReconnect); void onUsbDataReceived(struct libusb_transfer* transfer) override; void setSimulationMode(bool isSimulationMode); void setIsRunning(bool enableRunning); diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index 9042a0f59cf..c6443e6608a 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -450,7 +450,7 @@ int XhcWhb04b6Component::run() if (mUsb.isDeviceOpen()) { *mInitCout << "init enabling reception ..."; - if (!enableReceiveAsyncTransfer()) + if (!mUsb.setupAsyncTransfer()) { std::cerr << endl << "failed to enable reception" << endl; return EXIT_FAILURE; @@ -470,11 +470,6 @@ void XhcWhb04b6Component::linuxcncSimulate() { } // ---------------------------------------------------------------------- -bool XhcWhb04b6Component::enableReceiveAsyncTransfer() -{ - return mUsb.setupAsyncTransfer(); -} -// ---------------------------------------------------------------------- void XhcWhb04b6Component::setSimulationMode(bool enableSimulationMode) { mIsSimulationMode = enableSimulationMode; diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h index 07e01a090e4..44789645ec3 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.h @@ -51,7 +51,6 @@ class XhcWhb04b6Component : void initWhb(); void initHal(); void teardownHal(); - bool enableReceiveAsyncTransfer(); void updateDisplay(); void linuxcncSimulate(); void requestTermination(int signal = -42); From e450a2365bc1c5e1ce919569faeed22ef267f834 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 10:21:08 +0100 Subject: [PATCH 04/12] whb04b: Proper close and reconnect --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 14 ++++++++++++++ src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index e2dad2085e7..e14b3d2e110 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -598,6 +598,7 @@ Usb::InitStatus Usb::init() if (r != 0) { std::cerr << endl << "failed to initialize usb context" << endl; + mDoReconnect=true; return InitStatus::RETRY; } *verboseInitOut << " ok" << endl; @@ -632,6 +633,7 @@ Usb::InitStatus Usb::init() if (devicesCount < 0) { std::cerr << endl << "failed to get device list" << endl; + mDoReconnect=true; return InitStatus::RETRY; } @@ -665,6 +667,9 @@ Usb::InitStatus Usb::init() r = libusb_detach_kernel_driver(deviceHandle, 0); if(r < 0){ std::cerr << "libusb_detach_kernel_driver failed with " << r << endl; + libusb_close(deviceHandle); + deviceHandle = nullptr; + mDoReconnect=true; return InitStatus::RETRY; } *verboseInitOut << " ok" << endl; @@ -676,6 +681,9 @@ Usb::InitStatus Usb::init() else { std::cerr << "libusb_kernel_driver_active failed with " << r << endl; + libusb_close(deviceHandle); + deviceHandle = nullptr; + mDoReconnect=true; return InitStatus::RETRY; } *verboseInitOut << "init claiming interface ..."; @@ -683,12 +691,16 @@ Usb::InitStatus Usb::init() if (r != 0) { std::cerr << endl << "failed to claim interface" << endl; + libusb_close(deviceHandle); + deviceHandle = nullptr; + mDoReconnect=true; return InitStatus::RETRY; } *verboseInitOut << " ok" << endl; } return InitStatus::OK; } +// ---------------------------------------------------------------------- void Usb::handleTimeouts() { struct timeval timeout; @@ -699,6 +711,7 @@ void Usb::handleTimeouts() assert((r == LIBUSB_SUCCESS) || (r == LIBUSB_ERROR_NO_DEVICE) || (r == LIBUSB_ERROR_BUSY) || (r == LIBUSB_ERROR_TIMEOUT) || (r == LIBUSB_ERROR_INTERRUPTED)); } +// ---------------------------------------------------------------------- void Usb::close() { struct timeval tv; @@ -711,6 +724,7 @@ void Usb::close() libusb_close(deviceHandle); deviceHandle = nullptr; } +// ---------------------------------------------------------------------- void Usb::teardown() { libusb_exit(context); diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index c6443e6608a..7c4a70ab0bf 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -460,6 +460,10 @@ int XhcWhb04b6Component::run() process(); mUsb.teardown(); } + else + { + mUsb.teardown(); + } } teardownHal(); From 48f3009d86da14d359ec0dd8d4bd36ee133c0c06 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 10:42:22 +0100 Subject: [PATCH 05/12] whb04b: Cleanup --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 49 +++++++++++++++---- src/hal/user_comps/xhc-whb04b-6/usb.h | 1 + .../user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 6 ++- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index e14b3d2e110..9275b807b09 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -164,6 +164,12 @@ Usb::Usb(const char* name, OnUsbInputPackageListener& onDataReceivedCallback, Ha // ---------------------------------------------------------------------- void Usb::sendDisplayData() { + if(deviceHandle == nullptr) + { + std::cerr << endl << "Bug: sendDisplayData: deviceHandle is null!" << endl; + return; + } + outputPackageBuffer.asBlocks.init(&outputPackageData); if (mIsSimulationMode) @@ -414,6 +420,12 @@ void Usb::requestTermination() bool Usb::setupAsyncTransfer() { assert(inTransfer != nullptr); + if(deviceHandle == nullptr) + { + std::cerr << endl << "Bug: setupAsyncTransfer: deviceHandle is null!" << endl; + return false; + } + libusb_fill_bulk_transfer(inTransfer, deviceHandle, (0x1 | LIBUSB_ENDPOINT_IN), inputPackageBuffer.asBuffer, sizeof(inputPackageBuffer.asBuffer), mRawDataCallback, @@ -424,8 +436,12 @@ bool Usb::setupAsyncTransfer() int r = libusb_submit_transfer(inTransfer); if(r != 0){ std::cerr << "libusb_submit_transfer failed with " << r << endl; + return false; + } + else + { + return true; } - return (0 == r); } // ---------------------------------------------------------------------- void Usb::onUsbDataReceived(struct libusb_transfer* transfer) @@ -580,6 +596,14 @@ void Usb::enableVerboseInit(bool enable) // ---------------------------------------------------------------------- Usb::InitStatus Usb::init() { + if(context != nullptr) + { + std::cerr << endl << "Bug: Not cleaned up context properly before calling init again!" << endl; + } + if(deviceHandle != nullptr) + { + std::cerr << endl << "Bug: Not cleaned up deviceHandle properly before calling init again!" << endl; + } if (getDoReconnect()) { int pauseSecs = 3; @@ -633,6 +657,7 @@ Usb::InitStatus Usb::init() if (devicesCount < 0) { std::cerr << endl << "failed to get device list" << endl; + teardown(); mDoReconnect=true; return InitStatus::RETRY; } @@ -649,6 +674,7 @@ Usb::InitStatus Usb::init() if ((mWaitSecs--) <= 0) { std::cerr << endl << "Configured timeout exceeded, exiting" << endl; + teardown(); return InitStatus::EXIT; } } @@ -667,8 +693,8 @@ Usb::InitStatus Usb::init() r = libusb_detach_kernel_driver(deviceHandle, 0); if(r < 0){ std::cerr << "libusb_detach_kernel_driver failed with " << r << endl; - libusb_close(deviceHandle); - deviceHandle = nullptr; + closeHandle(); + teardown(); mDoReconnect=true; return InitStatus::RETRY; } @@ -681,8 +707,8 @@ Usb::InitStatus Usb::init() else { std::cerr << "libusb_kernel_driver_active failed with " << r << endl; - libusb_close(deviceHandle); - deviceHandle = nullptr; + closeHandle(); + teardown(); mDoReconnect=true; return InitStatus::RETRY; } @@ -691,8 +717,8 @@ Usb::InitStatus Usb::init() if (r != 0) { std::cerr << endl << "failed to claim interface" << endl; - libusb_close(deviceHandle); - deviceHandle = nullptr; + closeHandle(); + teardown(); mDoReconnect=true; return InitStatus::RETRY; } @@ -712,6 +738,12 @@ void Usb::handleTimeouts() (r == LIBUSB_ERROR_TIMEOUT) || (r == LIBUSB_ERROR_INTERRUPTED)); } // ---------------------------------------------------------------------- +void Usb::closeHandle() +{ + libusb_close(deviceHandle); + deviceHandle = nullptr; +} +// ---------------------------------------------------------------------- void Usb::close() { struct timeval tv; @@ -721,8 +753,7 @@ void Usb::close() assert(0 == r); r = libusb_release_interface(deviceHandle, 0); assert((0 == r) || (r == LIBUSB_ERROR_NO_DEVICE)); - libusb_close(deviceHandle); - deviceHandle = nullptr; + closeHandle(); } // ---------------------------------------------------------------------- void Usb::teardown() diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.h b/src/hal/user_comps/xhc-whb04b-6/usb.h index d78fe43bcef..e7ec787517a 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.h +++ b/src/hal/user_comps/xhc-whb04b-6/usb.h @@ -308,6 +308,7 @@ class Usb : public UsbRawInputListener UsbOutPackageData& getOutputPackageData(); private: + void closeHandle(); const uint16_t usbVendorId{0x10ce}; uint16_t usbProductId{0xeb93}; libusb_context * context{nullptr}; diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index 7c4a70ab0bf..fe4ef1d4673 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -460,9 +460,13 @@ int XhcWhb04b6Component::run() process(); mUsb.teardown(); } + else if(status == Usb::InitStatus::RETRY) + { + //Just retry + } else { - mUsb.teardown(); + std::cerr << endl << "Bug: Unhandled return value!" << endl; } } teardownHal(); From ee628c8cdd12e4cdc52e24a38e5e1291cc70f841 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 11:06:46 +0100 Subject: [PATCH 06/12] whb04b: Get rid of bad asserts and use static_assert --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 9275b807b09..4adcf561431 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -54,13 +54,13 @@ const ConstantUsbPackages Usb::ConstantPackages; UsbOutPackageBlock::UsbOutPackageBlock() : asBlock() { - assert(sizeof(UsbOutPackageBlockBuffer) == sizeof(UsbOutPackageBlockFields)); + static_assert(sizeof(UsbOutPackageBlockBuffer) == sizeof(UsbOutPackageBlockFields)); } // ---------------------------------------------------------------------- UsbInPackageBuffer::UsbInPackageBuffer() : asBuffer{0} { - assert(sizeof(asFields) == sizeof(asBuffer)); + static_assert(sizeof(asFields) == sizeof(asBuffer)); } // ---------------------------------------------------------------------- UsbEmptyPackage::UsbEmptyPackage() : @@ -371,9 +371,9 @@ UsbOutPackageBuffer::UsbOutPackageBuffer() : << " sizeof array " << sizeof(asBlockArray) << endl << " sizeof package " << sizeof(UsbOutPackageData) << endl; } - assert(sizeof(UsbOutPackageBlocks) == sizeof(asBlockArray)); - size_t blocksCount = sizeof(UsbOutPackageBlocks) / sizeof(UsbOutPackageBlockFields); - assert((sizeof(UsbOutPackageData) + blocksCount) == sizeof(UsbOutPackageBlocks)); + static_assert(sizeof(UsbOutPackageBlocks) == sizeof(asBlockArray)); + constexpr size_t blocksCount = sizeof(UsbOutPackageBlocks) / sizeof(UsbOutPackageBlockFields); + static_assert((sizeof(UsbOutPackageData) + blocksCount) == sizeof(UsbOutPackageBlocks)); } // ---------------------------------------------------------------------- UsbInPackage::UsbInPackage() : @@ -734,8 +734,10 @@ void Usb::handleTimeouts() timeout.tv_usec = 200 * 1000; int r = libusb_handle_events_timeout_completed(context, &timeout, nullptr); - assert((r == LIBUSB_SUCCESS) || (r == LIBUSB_ERROR_NO_DEVICE) || (r == LIBUSB_ERROR_BUSY) || - (r == LIBUSB_ERROR_TIMEOUT) || (r == LIBUSB_ERROR_INTERRUPTED)); + if(r != 0) + { + std::cerr << endl << "Error: handleTimeouts() libusb_handle_events_timeout_completed returned " << r << endl; + } } // ---------------------------------------------------------------------- void Usb::closeHandle() @@ -750,9 +752,15 @@ void Usb::close() tv.tv_sec = 1; tv.tv_usec = 0; int r = libusb_handle_events_timeout_completed(context, &tv, nullptr); - assert(0 == r); + if(r != 0) + { + std::cerr << endl << "Error: close() libusb_handle_events_timeout_completed returned " << r << endl; + } r = libusb_release_interface(deviceHandle, 0); - assert((0 == r) || (r == LIBUSB_ERROR_NO_DEVICE)); + if(r != 0 && r != LIBUSB_ERROR_NO_DEVICE) + { + std::cerr << endl << "Error: close() libusb_release_interface returned " << r << endl; + } closeHandle(); } // ---------------------------------------------------------------------- From 82527502f088a19c85d76c3a6d7ed02b230465d6 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 12:31:11 +0100 Subject: [PATCH 07/12] whb04b: Error handling --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 31 ++++++++-------- src/hal/user_comps/xhc-whb04b-6/usb.h | 4 +-- .../user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 36 ++++++++++--------- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 4adcf561431..6b1c6ff8fd3 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -135,11 +135,6 @@ bool Usb::isWaitForPendantBeforeHalEnabled() const return isWaitWithTimeout; } // ---------------------------------------------------------------------- -bool Usb::getDoReconnect() const -{ - return mDoReconnect; -} -// ---------------------------------------------------------------------- void Usb::setUsbProductId(uint16_t usbProductId) { this->usbProductId = usbProductId; @@ -436,6 +431,7 @@ bool Usb::setupAsyncTransfer() int r = libusb_submit_transfer(inTransfer); if(r != 0){ std::cerr << "libusb_submit_transfer failed with " << r << endl; + mDoReconnect = true; return false; } else @@ -518,7 +514,7 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) { if(!setupAsyncTransfer()) { - requestTermination(); + transferFailed = true; } } @@ -530,7 +526,7 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) { if(!setupAsyncTransfer()) { - requestTermination(); + transferFailed = true; } } break; @@ -543,12 +539,12 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) case (LIBUSB_TRANSFER_OVERFLOW): case (LIBUSB_TRANSFER_ERROR): std::cerr << "transfer error: " << transfer->status << endl; - requestTermination(); + transferFailed = true; break; default: std::cerr << "unknown transfer status: " << transfer->status << endl; - requestTermination(); + transferFailed = true; break; } //libusb_free_transfer(transfer); @@ -604,7 +600,7 @@ Usb::InitStatus Usb::init() { std::cerr << endl << "Bug: Not cleaned up deviceHandle properly before calling init again!" << endl; } - if (getDoReconnect()) + if (mDoReconnect) { int pauseSecs = 3; *verboseInitOut << "init pausing " << pauseSecs << "s, waiting for device to be gone ..."; @@ -681,11 +677,11 @@ Usb::InitStatus Usb::init() sleep(1); } } while (deviceHandle == nullptr && mIsRunning); - *verboseInitOut << " ok" << endl - << "init " << mName << " device found" << endl; if (deviceHandle != nullptr) { + *verboseInitOut << " ok" << endl + << "init " << mName << " device found" << endl; *verboseInitOut << "init detaching active kernel driver ..."; r = libusb_kernel_driver_active(deviceHandle, 0); if (r == 1) @@ -727,7 +723,7 @@ Usb::InitStatus Usb::init() return InitStatus::OK; } // ---------------------------------------------------------------------- -void Usb::handleTimeouts() +void Usb::process() { struct timeval timeout; timeout.tv_sec = 0; @@ -736,7 +732,14 @@ void Usb::handleTimeouts() int r = libusb_handle_events_timeout_completed(context, &timeout, nullptr); if(r != 0) { - std::cerr << endl << "Error: handleTimeouts() libusb_handle_events_timeout_completed returned " << r << endl; + std::cerr << endl << "Error: process() libusb_handle_events_timeout_completed returned " << r << endl; + } + + if(transferFailed) + { + close(); + transferFailed = false; + mDoReconnect = true; } } // ---------------------------------------------------------------------- diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.h b/src/hal/user_comps/xhc-whb04b-6/usb.h index e7ec787517a..2bef2ce001b 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.h +++ b/src/hal/user_comps/xhc-whb04b-6/usb.h @@ -287,7 +287,6 @@ class Usb : public UsbRawInputListener void setUsbProductId(uint16_t usbProductId); bool isDeviceOpen() const; bool isWaitForPendantBeforeHalEnabled() const; - bool getDoReconnect() const; void onUsbDataReceived(struct libusb_transfer* transfer) override; void setSimulationMode(bool isSimulationMode); void setIsRunning(bool enableRunning); @@ -300,7 +299,7 @@ class Usb : public UsbRawInputListener void enableVerboseRx(bool enable); void enableVerboseInit(bool enable); InitStatus init(); - void handleTimeouts(); + void process(); void close(); void teardown(); void setWaitWithTimeout(uint8_t waitSecs); @@ -318,6 +317,7 @@ class Usb : public UsbRawInputListener bool mIsSimulationMode{false}; SleepDetect sleepState; bool mIsRunning{false}; + bool transferFailed{false}; UsbInPackageBuffer inputPackageBuffer; UsbOutPackageBuffer outputPackageBuffer; UsbOutPackageData outputPackageData; diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index fe4ef1d4673..00e5243dd9a 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -450,15 +450,18 @@ int XhcWhb04b6Component::run() if (mUsb.isDeviceOpen()) { *mInitCout << "init enabling reception ..."; - if (!mUsb.setupAsyncTransfer()) + if (mUsb.setupAsyncTransfer()) { - std::cerr << endl << "failed to enable reception" << endl; - return EXIT_FAILURE; + *mInitCout << " ok" << endl; + process(); //process loops until disconnect/stopped + mUsb.teardown(); + } + else + { + mUsb.close(); + mUsb.teardown(); } - *mInitCout << " ok" << endl; } - process(); - mUsb.teardown(); } else if(status == Usb::InitStatus::RETRY) { @@ -487,23 +490,22 @@ void XhcWhb04b6Component::setSimulationMode(bool enableSimulationMode) // ---------------------------------------------------------------------- void XhcWhb04b6Component::process() { - if (mUsb.isDeviceOpen()) + while (isRunning() && mUsb.isDeviceOpen()) { - while (isRunning() && !mUsb.getDoReconnect()) + if (mHal.isSimulationModeEnabled()) { - mUsb.handleTimeouts(); - if (mHal.isSimulationModeEnabled()) - { - linuxcncSimulate(); - } - updateDisplay(); + linuxcncSimulate(); } updateDisplay(); - - mHal.setIsPendantConnected(false); - *mInitCout << "connection lost, cleaning up" << endl; + mUsb.process(); + } + if(mUsb.isDeviceOpen()) + { mUsb.close(); } + + mHal.setIsPendantConnected(false); + *mInitCout << "connection lost, cleaning up" << endl; } // ---------------------------------------------------------------------- void XhcWhb04b6Component::enableVerbosePendant(bool enable) From acae9ec2e5ede4ee630bd3e720eb48baa244f27f Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 12:40:24 +0100 Subject: [PATCH 08/12] whb04b: Comments / Cleanup --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 6b1c6ff8fd3..ded2d7f48dd 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -444,6 +444,9 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) { assert(mHal.isInitialized()); + //DO NOT call close from here, it is a callback from libusb + //and will deadlock!! + int expectedPackageSize = static_cast(sizeof(UsbInPackage)); std::ios init(NULL); init.copyfmt(*verboseTxOut); @@ -547,11 +550,15 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) transferFailed = true; break; } - //libusb_free_transfer(transfer); } // ---------------------------------------------------------------------- Usb::~Usb() { + if(deviceHandle != nullptr){ + close(); + } + libusb_free_transfer(inTransfer); + libusb_free_transfer(outTransfer); } // ---------------------------------------------------------------------- void Usb::enableVerboseTx(bool enable) From 23c28e190b86435ad14ede0ba7d87cc8878b0be0 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 12:50:20 +0100 Subject: [PATCH 09/12] whb04b: Cleanup --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index ded2d7f48dd..8888834a791 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -429,7 +429,8 @@ bool Usb::setupAsyncTransfer() //! timeout[ms] 750); int r = libusb_submit_transfer(inTransfer); - if(r != 0){ + if(r != 0) + { std::cerr << "libusb_submit_transfer failed with " << r << endl; mDoReconnect = true; return false; @@ -554,7 +555,8 @@ void Usb::onUsbDataReceived(struct libusb_transfer* transfer) // ---------------------------------------------------------------------- Usb::~Usb() { - if(deviceHandle != nullptr){ + if(deviceHandle != nullptr) + { close(); } libusb_free_transfer(inTransfer); @@ -694,7 +696,8 @@ Usb::InitStatus Usb::init() if (r == 1) { r = libusb_detach_kernel_driver(deviceHandle, 0); - if(r < 0){ + if(r < 0) + { std::cerr << "libusb_detach_kernel_driver failed with " << r << endl; closeHandle(); teardown(); From ee1c3ca87e34be395bddaf9ba9a267d491e31638 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 13:22:39 +0100 Subject: [PATCH 10/12] whb04b: Remove teardown and checks --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 49 ++++++++++++++----- src/hal/user_comps/xhc-whb04b-6/usb.h | 2 +- .../user_comps/xhc-whb04b-6/xhc-whb04b6.cc | 2 - 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 8888834a791..13766ae1dbe 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -662,7 +662,7 @@ Usb::InitStatus Usb::init() if (devicesCount < 0) { std::cerr << endl << "failed to get device list" << endl; - teardown(); + closeLibusb(); mDoReconnect=true; return InitStatus::RETRY; } @@ -679,7 +679,7 @@ Usb::InitStatus Usb::init() if ((mWaitSecs--) <= 0) { std::cerr << endl << "Configured timeout exceeded, exiting" << endl; - teardown(); + closeLibusb(); return InitStatus::EXIT; } } @@ -700,7 +700,7 @@ Usb::InitStatus Usb::init() { std::cerr << "libusb_detach_kernel_driver failed with " << r << endl; closeHandle(); - teardown(); + closeLibusb(); mDoReconnect=true; return InitStatus::RETRY; } @@ -714,7 +714,7 @@ Usb::InitStatus Usb::init() { std::cerr << "libusb_kernel_driver_active failed with " << r << endl; closeHandle(); - teardown(); + closeLibusb(); mDoReconnect=true; return InitStatus::RETRY; } @@ -724,7 +724,7 @@ Usb::InitStatus Usb::init() { std::cerr << endl << "failed to claim interface" << endl; closeHandle(); - teardown(); + closeLibusb(); mDoReconnect=true; return InitStatus::RETRY; } @@ -735,6 +735,12 @@ Usb::InitStatus Usb::init() // ---------------------------------------------------------------------- void Usb::process() { + if(context == nullptr) + { + std::cerr << endl << "Bug: process context is closed!" << endl; + return; + } + struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 200 * 1000; @@ -755,12 +761,38 @@ void Usb::process() // ---------------------------------------------------------------------- void Usb::closeHandle() { + if(deviceHandle == nullptr) + { + std::cerr << endl << "Bug: closeHandle allready closed!" << endl; + return; + } libusb_close(deviceHandle); deviceHandle = nullptr; } // ---------------------------------------------------------------------- +void Usb::closeLibusb() +{ + if(context == nullptr) + { + std::cerr << endl << "Bug: closeLibusb allready closed!" << endl; + return; + } + libusb_exit(context); + context = nullptr; +} +// ---------------------------------------------------------------------- void Usb::close() { + if(context == nullptr) + { + std::cerr << endl << "Bug: close context allready closed!" << endl; + return; + } + if(deviceHandle == nullptr) + { + std::cerr << endl << "Bug: close deviceHandle allready closed!" << endl; + return; + } struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; @@ -775,12 +807,7 @@ void Usb::close() std::cerr << endl << "Error: close() libusb_release_interface returned " << r << endl; } closeHandle(); -} -// ---------------------------------------------------------------------- -void Usb::teardown() -{ - libusb_exit(context); - context = nullptr; + closeLibusb(); } // ---------------------------------------------------------------------- void Usb::setWaitWithTimeout(uint8_t waitSecs) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.h b/src/hal/user_comps/xhc-whb04b-6/usb.h index 2bef2ce001b..23773babbf0 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.h +++ b/src/hal/user_comps/xhc-whb04b-6/usb.h @@ -301,13 +301,13 @@ class Usb : public UsbRawInputListener InitStatus init(); void process(); void close(); - void teardown(); void setWaitWithTimeout(uint8_t waitSecs); UsbOutPackageData& getOutputPackageData(); private: void closeHandle(); + void closeLibusb(); const uint16_t usbVendorId{0x10ce}; uint16_t usbProductId{0xeb93}; libusb_context * context{nullptr}; diff --git a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc index 00e5243dd9a..a8369dd6a94 100644 --- a/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc +++ b/src/hal/user_comps/xhc-whb04b-6/xhc-whb04b6.cc @@ -454,12 +454,10 @@ int XhcWhb04b6Component::run() { *mInitCout << " ok" << endl; process(); //process loops until disconnect/stopped - mUsb.teardown(); } else { mUsb.close(); - mUsb.teardown(); } } } From cf291ac7a10744411198d37ecd9921c799360443 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 13:40:39 +0100 Subject: [PATCH 11/12] whb04b: Interrupted is not an error --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index 13766ae1dbe..fc004ea9390 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -746,7 +746,8 @@ void Usb::process() timeout.tv_usec = 200 * 1000; int r = libusb_handle_events_timeout_completed(context, &timeout, nullptr); - if(r != 0) + //LIBUSB_ERROR_INTERRUPTED can happen on shutdown signal and is fine + if(r != 0 && r != LIBUSB_ERROR_INTERRUPTED) { std::cerr << endl << "Error: process() libusb_handle_events_timeout_completed returned " << r << endl; } From 1fcae397a8ae2cbeef7ea1d420ba326d561cb368 Mon Sep 17 00:00:00 2001 From: Hannes Diethelm Date: Sat, 7 Mar 2026 20:18:09 +0100 Subject: [PATCH 12/12] whb04b: Change to interrupt As sugested by Finngineering --- src/hal/user_comps/xhc-whb04b-6/usb.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/user_comps/xhc-whb04b-6/usb.cc b/src/hal/user_comps/xhc-whb04b-6/usb.cc index fc004ea9390..6d863b84ceb 100644 --- a/src/hal/user_comps/xhc-whb04b-6/usb.cc +++ b/src/hal/user_comps/xhc-whb04b-6/usb.cc @@ -421,7 +421,7 @@ bool Usb::setupAsyncTransfer() return false; } - libusb_fill_bulk_transfer(inTransfer, deviceHandle, + libusb_fill_interrupt_transfer(inTransfer, deviceHandle, (0x1 | LIBUSB_ENDPOINT_IN), inputPackageBuffer.asBuffer, sizeof(inputPackageBuffer.asBuffer), mRawDataCallback, //! pass this object as callback data