drivers/hid/usbhid/usbkbd.c | 22 ++++++++++++++++++++++ drivers/hid/usbhid/usbmouse.c | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+)
usbkbd and usbmouse are HID Boot Protocol drivers. They do not
parse report descriptors before decoding interrupt reports; instead,
they interpret input data as the fixed boot keyboard and boot mouse
formats.
The HID specification defines SET_PROTOCOL as the class request
to select report or boot protocol. Boot subclass devices may power
up or return from reset in report protocol, and hosts are expected
to select the protocol they intend to use.
Do not depend on firmware or a previous driver to leave the
interface in boot protocol. Send SET_PROTOCOL(BOOT) during probe
before the interrupt URB can be opened.
Keep failures non-fatal. Some devices may reject the request while
still sending boot-compatible reports. For those devices, the
existing driver behavior is preferable.
Signed-off-by: Xu Rao <raoxu@uniontech.com>
---
drivers/hid/usbhid/usbkbd.c | 22 ++++++++++++++++++++++
drivers/hid/usbhid/usbmouse.c | 22 ++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 6b33e6ad0846..f3b83f0396c8 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -233,6 +233,26 @@ static void usb_kbd_close(struct input_dev *dev)
usb_kill_urb(kbd->irq);
}
+static void usb_kbd_set_boot_protocol(struct usb_device *dev,
+ struct usb_interface *iface)
+{
+ struct usb_host_interface *interface = iface->cur_altsetting;
+ int error;
+
+ /*
+ * usbkbd does not parse report descriptors. Make the device produce
+ * the fixed boot report format that the driver decodes.
+ */
+ error = usb_control_msg_send(dev, 0, HID_REQ_SET_PROTOCOL,
+ USB_DIR_OUT | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, HID_BOOT_PROTOCOL,
+ interface->desc.bInterfaceNumber, NULL, 0,
+ USB_CTRL_SET_TIMEOUT, GFP_KERNEL);
+ if (error < 0)
+ dev_dbg(&iface->dev, "failed to set boot protocol: %d\n",
+ error);
+}
+
static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
{
if (!(kbd->irq = usb_alloc_urb(0, GFP_KERNEL)))
@@ -289,6 +309,8 @@ static int usb_kbd_probe(struct usb_interface *iface,
if (usb_kbd_alloc_mem(dev, kbd))
goto fail2;
+ usb_kbd_set_boot_protocol(dev, iface);
+
kbd->usbdev = dev;
kbd->dev = input_dev;
spin_lock_init(&kbd->leds_lock);
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 7cc4f9558e5f..c1b9d95f957e 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -103,6 +103,26 @@ static void usb_mouse_close(struct input_dev *dev)
usb_kill_urb(mouse->irq);
}
+static void usb_mouse_set_boot_protocol(struct usb_device *dev,
+ struct usb_interface *intf)
+{
+ struct usb_host_interface *interface = intf->cur_altsetting;
+ int error;
+
+ /*
+ * usbmouse does not parse report descriptors. Make the device produce
+ * the fixed boot report format that the driver decodes.
+ */
+ error = usb_control_msg_send(dev, 0, HID_REQ_SET_PROTOCOL,
+ USB_DIR_OUT | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, HID_BOOT_PROTOCOL,
+ interface->desc.bInterfaceNumber, NULL, 0,
+ USB_CTRL_SET_TIMEOUT, GFP_KERNEL);
+ if (error < 0)
+ dev_dbg(&intf->dev, "failed to set boot protocol: %d\n",
+ error);
+}
+
static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *dev = interface_to_usbdev(intf);
@@ -138,6 +158,8 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
if (!mouse->irq)
goto fail2;
+ usb_mouse_set_boot_protocol(dev, intf);
+
mouse->usbdev = dev;
mouse->dev = input_dev;
--
2.50.1
On Tue, Jun 02, 2026 at 09:48:35AM +0800, Xu Rao wrote: > usbkbd and usbmouse are HID Boot Protocol drivers. They do not > parse report descriptors before decoding interrupt reports; instead, > they interpret input data as the fixed boot keyboard and boot mouse > formats. > > The HID specification defines SET_PROTOCOL as the class request > to select report or boot protocol. Boot subclass devices may power > up or return from reset in report protocol, and hosts are expected > to select the protocol they intend to use. > > Do not depend on firmware or a previous driver to leave the > interface in boot protocol. Send SET_PROTOCOL(BOOT) during probe > before the interrupt URB can be opened. > > Keep failures non-fatal. Some devices may reject the request while > still sending boot-compatible reports. For those devices, the > existing driver behavior is preferable. Do you really use these drivers for devices? If so, why? And shouldn't the failure be fatal? If not, why even attempt to send it? How was this tested? On what devices? thanks, greg k-h
Hi Greg, > > Do not depend on firmware or a previous driver to leave the > > interface in boot protocol. Send SET_PROTOCOL(BOOT) during probe > > before the interrupt URB can be opened. > > > > Keep failures non-fatal. Some devices may reject the request while > > still sending boot-compatible reports. For those devices, the > > existing driver behavior is preferable. > > Do you really use these drivers for devices? If so, why? > > And shouldn't the failure be fatal? If not, why even attempt to send > it? After checking the actual device path again, you are right: the devices I had in mind use the normal usbhid/hid-generic path, not usbkbd or usbmouse. This patch came from reading the simple HID Boot Protocol drivers and noticing that they decode fixed boot reports without explicitly selecting boot protocol first. So this was a code-inspection cleanup rather than a fix for a device that I can show is bound to these drivers. Given that I do not have a real user of usbkbd/usbmouse to justify the change and test coverage properly, please ignore/drop this patch. Sorry for the noise, and thanks for pointing this out. thanks, Xu Rao
© 2016 - 2026 Red Hat, Inc.