]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
usb: gadget: f_hid: {GET,SET} PROTOCOL Support
authorAbdulhadi Mohamed <abdulahhadi2@gmail.com>
Wed, 19 Jul 2017 15:31:10 +0000 (16:31 +0100)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Tue, 15 Aug 2017 09:46:03 +0000 (12:46 +0300)
The current f_hid driver doesn't handle GET_PROCOTOL and
SET_PROCOTOL requests, which are required to operate HID
gadgets in BOOT mode. This patch implements this feature for
devices that have the same implementation for REPORT and BOOT mode
so that these devices are recognized by older BIOSes.

Signed-off-by: Abdulhadi Mohamed <abdulahhadi2@gmail.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/gadget/function/f_hid.c
include/linux/hid.h

index 5eea44823ca06d06955eb2bc51782cac6cd345ec..d8e359ef6eb1d525e96c027868ce55ac6aa0f1e0 100644 (file)
@@ -44,6 +44,7 @@ struct f_hidg {
        /* configuration */
        unsigned char                   bInterfaceSubClass;
        unsigned char                   bInterfaceProtocol;
+       unsigned char                   protocol;
        unsigned short                  report_desc_length;
        char                            *report_desc;
        unsigned short                  report_length;
@@ -527,7 +528,9 @@ static int hidg_setup(struct usb_function *f,
        case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
                  | HID_REQ_GET_PROTOCOL):
                VDBG(cdev, "get_protocol\n");
-               goto stall;
+               length = min_t(unsigned int, length, 1);
+               ((u8 *) req->buf)[0] = hidg->protocol;
+               goto respond;
                break;
 
        case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -539,6 +542,17 @@ static int hidg_setup(struct usb_function *f,
        case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
                  | HID_REQ_SET_PROTOCOL):
                VDBG(cdev, "set_protocol\n");
+               if (value > HID_REPORT_PROTOCOL)
+                       goto stall;
+               length = 0;
+               /*
+                * We assume that programs implementing the Boot protocol
+                * are also compatible with the Report Protocol
+                */
+               if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
+                       hidg->protocol = value;
+                       goto respond;
+               }
                goto stall;
                break;
 
@@ -768,6 +782,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
        /* set descriptor dynamic values */
        hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
        hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
+       hidg->protocol = HID_REPORT_PROTOCOL;
        hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
        hidg_ss_in_comp_desc.wBytesPerInterval =
                                cpu_to_le16(hidg->report_length);
index 5006f9b5d83701a77529988644cd9b018485bf7b..6519cdc4c7d371ae965716e33b072a0f44f64a0c 100644 (file)
@@ -362,6 +362,12 @@ struct hid_item {
 #define HID_GROUP_WACOM                                0x0101
 #define HID_GROUP_LOGITECH_DJ_DEVICE           0x0102
 
+/*
+ * HID protocol status
+ */
+#define HID_REPORT_PROTOCOL    1
+#define HID_BOOT_PROTOCOL      0
+
 /*
  * This is the global environment of the parser. This information is
  * persistent for main-items. The global environment can be saved and