usb: gadget: OS String support
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>
Thu, 8 May 2014 12:06:22 +0000 (14:06 +0200)
committerFelipe Balbi <balbi@ti.com>
Wed, 14 May 2014 14:38:03 +0000 (09:38 -0500)
There is a custom (non-USB IF) extension to the USB standard:

http://msdn.microsoft.com/library/windows/hardware/gg463182

They grant permission to use the specification - there is
"Microsoft OS Descriptor Specification License Agreement"
under the link mentioned above, and its Section 2 "Grant
of License", letter (b) reads:

"Patent license. Microsoft hereby grants to You a nonexclusive,
royalty-free, nontransferable, worldwide license under Microsoft’s
patents embodied solely within the Specification and that are owned
or licensable by Microsoft to make, use, import, offer to sell,
sell and distribute directly or indirectly to Your Licensees Your
Implementation. You may sublicense this patent license to Your
Licensees under the same terms and conditions."

The said extension is maintained by Microsoft for Microsoft.

Yet it is fairly common for various devices to use it, and a
popular proprietary operating system expects devices to provide
"OS descriptors", so Linux-based USB gadgets whishing to be able
to talk to a variety of operating systems should be able to provide
the "OS descriptors".

This patch adds optional support for gadgets whishing to expose
the so called "OS String" under index 0xEE of language 0.
The contents of the string is generated based on the qw_sign
array and b_vendor_code.

Interested gadgets need to set the cdev->use_os_string flag,
fill cdev->qw_sign with appropriate values and fill cdev->b_vendor_code
with a value of their choice.

This patch does not however implement responding to any vendor-specific
USB requests.

Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/composite.c
include/linux/usb/composite.h

index 8060de6562cdba5dd09ed61ce1de853bcd6610ac..2f87b1697bf53f790656123c7bec4f2d8c83e0c8 100644 (file)
 #include <linux/usb/composite.h>
 #include <asm/unaligned.h>
 
+/**
+ * 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;
+
 /*
  * The code in this file is utility code, used to build a gadget driver
  * from one or more "function" drivers, one or more "configuration"
@@ -961,6 +977,19 @@ 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;
+               compiletime_assert(
+                       sizeof(b->qwSignature) == sizeof(cdev->qw_sign),
+                       "qwSignature size must be equal to qw_sign");
+               memcpy(&b->qwSignature, cdev->qw_sign, sizeof(b->qwSignature));
+               b->bMS_VendorCode = cdev->b_vendor_code;
+               b->bPad = 0;
+               return sizeof(*b);
+       }
+
        list_for_each_entry(uc, &cdev->gstrings, list) {
                struct usb_gadget_strings **sp;
 
index d3ca3b53837c42c85ff2dd7ebcc11764014fe23d..7d29ee9363e8cb43e760a5dedc60490fc1c9ab83 100644 (file)
@@ -335,11 +335,17 @@ static inline struct usb_composite_driver *to_cdriver(
        return container_of(gdrv, struct usb_composite_driver, gadget_driver);
 }
 
+#define OS_STRING_QW_SIGN_LEN          14
+#define OS_STRING_IDX                  0xEE
+
 /**
  * struct usb_composite_device - represents one composite usb gadget
  * @gadget: read-only, abstracts the gadget's usb peripheral controller
  * @req: used for control responses; buffer is pre-allocated
  * @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.
@@ -372,6 +378,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;