From 96d9f5d317c25ead15dd9ec509758e3d277fd362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 1 Nov 2024 17:08:24 +0100 Subject: [PATCH] usb: consider alternate setting in endpoint select When constructing an Usb::Interface and implicitly corresponding Usb::Endpoint instances only select endpoints relevant for the given alternate setting. The libusb has to be changed to delegate the correct alternate setting to the constructor too. Fix genodelabs/genode#5394 --- repos/libports/src/lib/libusb/genode_usb_raw.cc | 17 ++++++++++++++--- repos/os/include/usb_session/device.h | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/repos/libports/src/lib/libusb/genode_usb_raw.cc b/repos/libports/src/lib/libusb/genode_usb_raw.cc index 57845480dd..42672b7621 100644 --- a/repos/libports/src/lib/libusb/genode_usb_raw.cc +++ b/repos/libports/src/lib/libusb/genode_usb_raw.cc @@ -58,7 +58,7 @@ struct Usb_device Usb_device &_device; - Interface(Usb_device &device, uint8_t idx); + Interface(Usb_device &device, uint8_t idx, uint8_t alt = 0); void handle_events(); }; @@ -108,9 +108,10 @@ struct Usb_device }; -Usb_device::Interface::Interface(Usb_device &device, uint8_t idx) +Usb_device::Interface::Interface(Usb_device &device, uint8_t idx, uint8_t alt) : - Usb::Interface(device._device, Usb::Interface::Index{idx, 0}, (1UL << 20)), + Usb::Interface(device._device, Usb::Interface::Index{idx, alt}, + (1UL << 20)), Registry::Element(device._interfaces, *this), _device(device) { @@ -461,11 +462,21 @@ static int genode_set_interface_altsetting(struct libusb_device_handle* dev_hand altsetting < 0 || altsetting > 0xff) return LIBUSB_ERROR_INVALID_PARAM; + /* remove already claimed interface with old setting */ + device()._interfaces.for_each([&] (Usb_device::Interface &iface) { + if (iface.index().number == interface_number) + destroy(device()._alloc, &iface); }); + Usb_device::Urb urb(nullptr, 0, device()._device, P::Request::SET_INTERFACE, Rt::value(P::Recipient::IFACE, P::Type::STANDARD, P::Direction::OUT), (uint8_t)altsetting, (uint8_t)interface_number, 0); device()._wait_for_urb(urb); + + /* claim interface */ + new (device()._alloc) + Usb_device::Interface(device(), (uint8_t) interface_number, + (uint8_t) altsetting); return LIBUSB_SUCCESS; } diff --git a/repos/os/include/usb_session/device.h b/repos/os/include/usb_session/device.h index 412bfcf149..765d819425 100644 --- a/repos/os/include/usb_session/device.h +++ b/repos/os/include/usb_session/device.h @@ -671,6 +671,8 @@ inline Usb::Interface::Interface(Device &device, Index idx, size_t buffer_size) device._for_each_iface([&] (Xml_node node) { if (node.attribute_value("number", INVALID) != idx.number) return; + if (node.attribute_value("alt_setting", INVALID) != idx.alt_setting) + return; node.for_each_sub_node("endpoint", [&] (Xml_node node) { Endpoint ep { node.attribute_value("address", 0), node.attribute_value("attributes", 0) };