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
This commit is contained in:
Josef Söntgen 2024-11-01 17:08:24 +01:00 committed by Christian Helmuth
parent 97e638a2ac
commit 96d9f5d317
2 changed files with 16 additions and 3 deletions

View File

@ -58,7 +58,7 @@ struct Usb_device
Usb_device &_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(); 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<Usb_device::Interface>::Element(device._interfaces, *this), Registry<Usb_device::Interface>::Element(device._interfaces, *this),
_device(device) _device(device)
{ {
@ -461,11 +462,21 @@ static int genode_set_interface_altsetting(struct libusb_device_handle* dev_hand
altsetting < 0 || altsetting > 0xff) altsetting < 0 || altsetting > 0xff)
return LIBUSB_ERROR_INVALID_PARAM; 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, Usb_device::Urb urb(nullptr, 0, device()._device, P::Request::SET_INTERFACE,
Rt::value(P::Recipient::IFACE, P::Type::STANDARD, Rt::value(P::Recipient::IFACE, P::Type::STANDARD,
P::Direction::OUT), P::Direction::OUT),
(uint8_t)altsetting, (uint8_t)interface_number, 0); (uint8_t)altsetting, (uint8_t)interface_number, 0);
device()._wait_for_urb(urb); device()._wait_for_urb(urb);
/* claim interface */
new (device()._alloc)
Usb_device::Interface(device(), (uint8_t) interface_number,
(uint8_t) altsetting);
return LIBUSB_SUCCESS; return LIBUSB_SUCCESS;
} }

View File

@ -671,6 +671,8 @@ inline Usb::Interface::Interface(Device &device, Index idx, size_t buffer_size)
device._for_each_iface([&] (Xml_node node) { device._for_each_iface([&] (Xml_node node) {
if (node.attribute_value<uint16_t>("number", INVALID) != idx.number) if (node.attribute_value<uint16_t>("number", INVALID) != idx.number)
return; return;
if (node.attribute_value<uint16_t>("alt_setting", INVALID) != idx.alt_setting)
return;
node.for_each_sub_node("endpoint", [&] (Xml_node node) { node.for_each_sub_node("endpoint", [&] (Xml_node node) {
Endpoint ep { node.attribute_value<uint8_t>("address", 0), Endpoint ep { node.attribute_value<uint8_t>("address", 0),
node.attribute_value<uint8_t>("attributes", 0) }; node.attribute_value<uint8_t>("attributes", 0) };