The current HID function driver doesn't support GET_PROCOTOL and
SET_PROCOTOL commands, which are required to operate the HID gadget in
BOOT mode. This change implements this feature for devices that have
the same implementation for REPORT and BOOT mode

Signed-off-by: Abdulhadi Mohamed <abdulahha...@gmail.com>
---
 drivers/usb/gadget/function/f_hid.c | 17 ++++++++++++++++-
 include/linux/hid.h                 |  6 ++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/f_hid.c 
b/drivers/usb/gadget/function/f_hid.c
index 5eea448..c60b882 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -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, 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);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index b2ec827..29d06c8 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -347,6 +347,12 @@ struct hid_item {
 #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
  * restored with PUSH/POP statements.
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to