summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbdulhadi Mohamed <abdulahhadi2@gmail.com>2017-07-19 16:31:10 +0100
committerGerrit - the friendly Code Review server <code-review@localhost>2019-01-10 21:03:30 -0800
commitfda16fc18334dd2efa39262cefbee2e3a4cd1897 (patch)
treee1e732fb77f610d79f1be210436b58c0dd820748
parentb3b13a88db52f9500853acd9290d319bba9f0917 (diff)
usb: gadget: f_hid: {GET,SET} PROTOCOL Support
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. Change-Id: I2279d9083bf9093f5a96c16df5d7ae48d11fd503 Signed-off-by: Abdulhadi Mohamed <abdulahhadi2@gmail.com> Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> Git-commit: b3c4ec71ec413c2e5bfb028bdf1737af07f1fde0 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git Signed-off-by: Ajay Agarwal <ajaya@codeaurora.org>
-rw-r--r--drivers/usb/gadget/function/f_hid.c17
-rw-r--r--include/linux/hid.h6
2 files changed, 22 insertions, 1 deletions
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index bdb19f30aac7..3ce3d5504b67 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 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);
diff --git a/include/linux/hid.h b/include/linux/hid.h
index fd86687f8119..d16de62231d3 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -345,6 +345,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.