From ace5960e705dab91c384aaf209c7c3f4515e5d31 Mon Sep 17 00:00:00 2001 From: "andrey.bychkov" Date: Mon, 10 Aug 2026 16:26:30 +0300 Subject: [PATCH] fix(piusb): fix 4 bugs in USB read/write/enumeration/close 1. Missing break in readDevice() Bulk case: Bulk read result was overwritten by interrupt read, silently corrupting all bulk reads. 2. Wrong variable in writeDevice(): switch checked ep_read instead of ep_write; Interrupt case used ep_read.address for writes. 3. Interface mismatch in closeDevice(): always released interface 0 (intefrace_) instead of the actually claimed interface (interface_claimed), leaking non-zero interface claims. 4. Wrong index in interface enumeration: used outer loop variable c (configuration index) instead of i (interface index), reading wrong interface descriptors or causing OOB access. --- libs/usb/piusb.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libs/usb/piusb.cpp b/libs/usb/piusb.cpp index 95687efa..c45070ee 100644 --- a/libs/usb/piusb.cpp +++ b/libs/usb/piusb.cpp @@ -239,7 +239,7 @@ bool PIUSB::openDevice() { for (int i = 0; i < dc.bNumInterfaces; ++i) { conf.interfaces << Interface(); Interface & infc(conf.interfaces.back()); - struct usb_interface_descriptor * di(dc.interface[c].altsetting); + struct usb_interface_descriptor * di(dc.interface[i].altsetting); infc.index = i; infc.value_to_select = di->bAlternateSetting; infc.class_code = di->bInterfaceClass; @@ -287,7 +287,7 @@ bool PIUSB::openDevice() { } // else piCoutObj << "ok"; // usb_reset(hdev); - // usb_set_configuration(hdev, 1); + // usb_set_configuration(hdev, 1); // usb_set_altinterface(hdev, 0); # ifndef WINDOWS @@ -320,7 +320,7 @@ bool PIUSB::openDevice() { bool PIUSB::closeDevice() { #ifdef PIP_USB if (hdev == 0) return true; - usb_release_interface(hdev, intefrace_); + if (interface_claimed >= 0) usb_release_interface(hdev, interface_claimed); usb_close(hdev); hdev = 0; interface_claimed = -1; @@ -340,6 +340,7 @@ ssize_t PIUSB::readDevice(void * read_to, ssize_t max_size) { case Endpoint::Bulk: /*piCoutObj << "bulk read" << max_size;*/ ret = usb_bulk_read(hdev, ep_read.address, (char *)read_to, max_size, timeout_r); + break; case Endpoint::Interrupt: ret = usb_interrupt_read(hdev, ep_read.address, (char *)read_to, max_size, timeout_r); default: break; } @@ -354,11 +355,11 @@ ssize_t PIUSB::readDevice(void * read_to, ssize_t max_size) { ssize_t PIUSB::writeDevice(const void * data, ssize_t max_size) { #ifdef PIP_USB if (isClosed() || ep_write.isNull()) return -1; - switch (ep_read.transfer_type) { + switch (ep_write.transfer_type) { case Endpoint::Bulk: /*piCoutObj << "bulk write" << max_size;*/ return usb_bulk_write(hdev, ep_write.address, (char *)const_cast(data), max_size, timeout_w); - case Endpoint::Interrupt: return usb_interrupt_write(hdev, ep_read.address, (char *)data, max_size, timeout_w); + case Endpoint::Interrupt: return usb_interrupt_write(hdev, ep_write.address, (char *)data, max_size, timeout_w); default: break; } return -1; @@ -442,7 +443,7 @@ PICout operator<<(PICout s, const PIUSB::Endpoint & v) { PIString PIUSB::constructFullPathDevice() const { PIString ret; ret = PIString::fromNumber(vendorID(), 16).toLowerCase() + ":" + PIString::fromNumber(productID(), 16).toLowerCase() + ":" + - deviceNumber() + ":" + endpointRead().address + ":" + endpointWrite().address; + deviceNumber() + ":" + endpointRead().address + ":" + endpointWrite().address; return ret; }