diff options
-rw-r--r-- | drivers/usb/gadget/composite.c | 26 | ||||
-rw-r--r-- | include/linux/usb/composite.h | 10 |
2 files changed, 36 insertions, 0 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index d0ee7847b9..d334f48786 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -16,6 +16,22 @@ static struct usb_composite_driver *composite; /** + * struct usb_os_string - represents OS String to be reported by a gadget + * @bLength: total length of the entire descritor, always 0x12 + * @bDescriptorType: USB_DT_STRING + * @qwSignature: the OS String proper + * @bMS_VendorCode: code used by the host for subsequent requests + * @bPad: not used, must be zero + */ +struct usb_os_string { + __u8 bLength; + __u8 bDescriptorType; + __u8 qwSignature[OS_STRING_QW_SIGN_LEN]; + __u8 bMS_VendorCode; + __u8 bPad; +} __packed; + +/** * usb_add_function() - add a function to a configuration * @config: the configuration * @function: the function being added @@ -566,6 +582,16 @@ static int get_string(struct usb_composite_dev *cdev, return s->bLength; } + if (cdev->use_os_string && language == 0 && id == OS_STRING_IDX) { + struct usb_os_string *b = buf; + b->bLength = sizeof(*b); + b->bDescriptorType = USB_DT_STRING; + memcpy(&b->qwSignature, cdev->qw_sign, sizeof(b->qwSignature)); + b->bMS_VendorCode = cdev->b_vendor_code; + b->bPad = 0; + return sizeof(*b); + } + /* * Otherwise, look up and return a specified string. String IDs * are device-scoped, so we look up each string table we're told diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 86e1ceac3c..14359b2b6e 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -285,6 +285,8 @@ struct usb_composite_driver { extern int usb_composite_register(struct usb_composite_driver *); extern void usb_composite_unregister(struct usb_composite_driver *); +#define OS_STRING_QW_SIGN_LEN 14 +#define OS_STRING_IDX 0xEE /** * struct usb_composite_device - represents one composite usb gadget @@ -292,6 +294,9 @@ extern void usb_composite_unregister(struct usb_composite_driver *); * @req: used for control responses; buffer is pre-allocated * @bufsiz: size of buffer pre-allocated in @req * @config: the currently active configuration + * @qw_sign: qwSignature part of the OS string + * @b_vendor_code: bMS_VendorCode part of the OS string + * @use_os_string: false by default, interested gadgets set it * * One of these devices is allocated and initialized before the * associated device driver's bind() is called. @@ -325,6 +330,11 @@ struct usb_composite_dev { struct usb_configuration *config; + /* OS String is a custom (yet popular) extension to the USB standard. */ + u8 qw_sign[OS_STRING_QW_SIGN_LEN]; + u8 b_vendor_code; + unsigned int use_os_string:1; + /* private: */ /* internals */ unsigned int suspended:1; |