usb: fix wrong init of keyboard/mouse's if first interface is not boot protocol

There is always some endpoint descriptors after each interface descriptor, We
should only decrement num_iface if interface type is USB_DT_INTERFACE, see
https://www.beyondlogic.org/usbnutshell/usb5.shtml#ConfigurationDescriptors

Signed-off-by: Qi Zhou <atmgnd@outlook.com>
This commit is contained in:
Qi Zhou 2022-11-14 20:55:44 +08:00 committed by Kevin O'Connor
parent 3208b098f5
commit 645a64b491
2 changed files with 15 additions and 10 deletions

View File

@ -22,13 +22,13 @@ struct usb_pipe *mouse_pipe VARFSEG;
// Send USB HID protocol message. // Send USB HID protocol message.
static int static int
set_protocol(struct usb_pipe *pipe, u16 val) set_protocol(struct usb_pipe *pipe, u16 val, u16 inferface)
{ {
struct usb_ctrlrequest req; struct usb_ctrlrequest req;
req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
req.bRequest = HID_REQ_SET_PROTOCOL; req.bRequest = HID_REQ_SET_PROTOCOL;
req.wValue = val; req.wValue = val;
req.wIndex = 0; req.wIndex = inferface;
req.wLength = 0; req.wLength = 0;
return usb_send_default_control(pipe, &req, NULL); return usb_send_default_control(pipe, &req, NULL);
} }
@ -76,9 +76,12 @@ usb_kbd_setup(struct usbdevice_s *usbdev
} }
// Enable "boot" protocol. // Enable "boot" protocol.
int ret = set_protocol(usbdev->defpipe, 0); int ret = set_protocol(usbdev->defpipe, 0, usbdev->iface->bInterfaceNumber);
if (ret) if (ret) {
dprintf(3, "Failed to set boot protocol\n");
return -1; return -1;
}
// Periodically send reports to enable key repeat. // Periodically send reports to enable key repeat.
ret = set_idle(usbdev->defpipe, KEYREPEATMS); ret = set_idle(usbdev->defpipe, KEYREPEATMS);
if (ret) if (ret)
@ -118,7 +121,7 @@ usb_mouse_setup(struct usbdevice_s *usbdev
} }
// Enable "boot" protocol. // Enable "boot" protocol.
int ret = set_protocol(usbdev->defpipe, 0); int ret = set_protocol(usbdev->defpipe, 0, usbdev->iface->bInterfaceNumber);
if (ret) if (ret)
return -1; return -1;

View File

@ -372,17 +372,19 @@ configure_usb_device(struct usbdevice_s *usbdev)
void *config_end = (void*)config + config->wTotalLength; void *config_end = (void*)config + config->wTotalLength;
struct usb_interface_descriptor *iface = (void*)(&config[1]); struct usb_interface_descriptor *iface = (void*)(&config[1]);
for (;;) { for (;;) {
if (!num_iface-- || (void*)iface + iface->bLength > config_end) if (!num_iface || (void*)iface + iface->bLength > config_end)
// Not a supported device. // Not a supported device.
goto fail; goto fail;
if (iface->bDescriptorType == USB_DT_INTERFACE if (iface->bDescriptorType == USB_DT_INTERFACE) {
&& (iface->bInterfaceClass == USB_CLASS_HUB num_iface--;
if (iface->bInterfaceClass == USB_CLASS_HUB
|| (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE || (iface->bInterfaceClass == USB_CLASS_MASS_STORAGE
&& (iface->bInterfaceProtocol == US_PR_BULK && (iface->bInterfaceProtocol == US_PR_BULK
|| iface->bInterfaceProtocol == US_PR_UAS)) || iface->bInterfaceProtocol == US_PR_UAS))
|| (iface->bInterfaceClass == USB_CLASS_HID || (iface->bInterfaceClass == USB_CLASS_HID
&& iface->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT))) && iface->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT))
break; break;
}
iface = (void*)iface + iface->bLength; iface = (void*)iface + iface->bLength;
} }