summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/composite.c26
-rw-r--r--include/linux/usb/composite.h10
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;