@@ -25,6 +25,22 @@ static inline void le16_add_cpu_packed(__le16_packed *var, u16 val)
var->val = cpu_to_le16(le16_to_cpu(var->val) + val);
}
+/**
+ * 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
@@ -577,6 +593,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
@@ -284,6 +284,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
@@ -291,6 +293,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.
@@ -324,6 +329,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;