This patch is required to implement the set_procotol and get_procotol commands 
for HID gadgets to interact with the BIOS using the BOOT protocol according to 
the HID specification. These two commands are also required to implement remote 
wake up for HID gadgets once the BIOS takes control of the device. 

This issue was first raised by Golmer Palmer in May 25 2015 but was never 
followed 
up on. This version of the patch is also heavily based on the patch provided by 
Alan Stern with some added support for remote wakeup.

Abdul Mohamed

---
 drivers/usb/gadget/function/f_hid.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/usb/gadget/function/f_hid.c 
b/drivers/usb/gadget/function/f_hid.c
index 5eea448..ea38e36 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_is_report;
        unsigned short                  report_desc_length;
        char                            *report_desc;
        unsigned short                  report_length;
@@ -338,10 +339,13 @@ static ssize_t f_hidg_write(struct file *file, const char 
__user *buffer,
                            size_t count, loff_t *offp)
 {
        struct f_hidg *hidg  = file->private_data;
+       struct usb_composite_dev        *cdev = hidg->func.config->cdev; 
        struct usb_request *req;
        unsigned long flags;
        ssize_t status = -ENOMEM;
 
+       usb_gadget_wakeup(cdev->gadget);
+
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;
 
@@ -528,6 +532,9 @@ static int hidg_setup(struct usb_function *f,
                  | HID_REQ_GET_PROTOCOL):
                VDBG(cdev, "get_protocol\n");
                goto stall;
+               length = min_t(unsigned, length, 1); 
+               ((u8 *) req->buf)[0]    = hidg->protocol_is_report;
+               goto respond; 
                break;
 
        case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
@@ -539,6 +546,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 > 1)
+                       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_is_report = value; 
+                               goto respond;
+               }
                goto stall;
                break;
 
@@ -768,6 +786,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_is_report = 1; 
        hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
        hidg_ss_in_comp_desc.wBytesPerInterval =
                                cpu_to_le16(hidg->report_length);
-- 
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