CHROMIUM: usb: gadget: f_mtp: Add SuperSpeed support
authorMark Kuo <mkuo@nvidia.com>
Thu, 20 Aug 2015 05:01:46 +0000 (13:01 +0800)
committerBadhri Jagan Sridharan <Badhri@google.com>
Tue, 22 Mar 2016 18:12:06 +0000 (11:12 -0700)
Add SuperSpeed endpoint and companion descriptors.

BUG=chrome-os-partner:43682
TEST=Smaug enumerates as a SuperSpeed device.

Change-Id: I2bf3125d180fcb07222a5740fa67f3526cf3e95c
Signed-off-by: Hui Fu <hfu@nvidia.com>
Signed-off-by: Henry Lin <henryl@nvidia.com>
Signed-off-by: Mark Kuo <mkuo@nvidia.com>
Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/294950

drivers/usb/gadget/function/f_mtp.c

index 8f80a7e91314d705b6265a8c7080289707695cf3..148f8fcecc8071467f9527ec83a89b806e058c1f 100644 (file)
@@ -135,6 +135,34 @@ static struct usb_interface_descriptor ptp_interface_desc = {
        .bInterfaceProtocol     = 1,
 };
 
+static struct usb_endpoint_descriptor mtp_ss_in_desc = {
+       .bLength                = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType        = USB_DT_ENDPOINT,
+       .bEndpointAddress       = USB_DIR_IN,
+       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor mtp_ss_in_comp_desc = {
+       .bLength                = sizeof(mtp_ss_in_comp_desc),
+       .bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
+       /* .bMaxBurst           = DYNAMIC, */
+};
+
+static struct usb_endpoint_descriptor mtp_ss_out_desc = {
+       .bLength                = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType        = USB_DT_ENDPOINT,
+       .bEndpointAddress       = USB_DIR_OUT,
+       .bmAttributes           = USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize         = __constant_cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor mtp_ss_out_comp_desc = {
+       .bLength                = sizeof(mtp_ss_out_comp_desc),
+       .bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
+       /* .bMaxBurst           = DYNAMIC, */
+};
+
 static struct usb_endpoint_descriptor mtp_highspeed_in_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
@@ -174,6 +202,12 @@ static struct usb_endpoint_descriptor mtp_intr_desc = {
        .bInterval              = 6,
 };
 
+static struct usb_ss_ep_comp_descriptor mtp_intr_ss_comp_desc = {
+       .bLength                = sizeof(mtp_intr_ss_comp_desc),
+       .bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
+       .wBytesPerInterval      = cpu_to_le16(2),
+};
+
 static struct usb_descriptor_header *fs_mtp_descs[] = {
        (struct usb_descriptor_header *) &mtp_interface_desc,
        (struct usb_descriptor_header *) &mtp_fullspeed_in_desc,
@@ -190,6 +224,17 @@ static struct usb_descriptor_header *hs_mtp_descs[] = {
        NULL,
 };
 
+static struct usb_descriptor_header *ss_mtp_descs[] = {
+       (struct usb_descriptor_header *) &mtp_interface_desc,
+       (struct usb_descriptor_header *) &mtp_ss_in_desc,
+       (struct usb_descriptor_header *) &mtp_ss_in_comp_desc,
+       (struct usb_descriptor_header *) &mtp_ss_out_desc,
+       (struct usb_descriptor_header *) &mtp_ss_out_comp_desc,
+       (struct usb_descriptor_header *) &mtp_intr_desc,
+       (struct usb_descriptor_header *) &mtp_intr_ss_comp_desc,
+       NULL,
+};
+
 static struct usb_descriptor_header *fs_ptp_descs[] = {
        (struct usb_descriptor_header *) &ptp_interface_desc,
        (struct usb_descriptor_header *) &mtp_fullspeed_in_desc,
@@ -206,6 +251,17 @@ static struct usb_descriptor_header *hs_ptp_descs[] = {
        NULL,
 };
 
+static struct usb_descriptor_header *ss_ptp_descs[] = {
+       (struct usb_descriptor_header *) &ptp_interface_desc,
+       (struct usb_descriptor_header *) &mtp_ss_in_desc,
+       (struct usb_descriptor_header *) &mtp_ss_in_comp_desc,
+       (struct usb_descriptor_header *) &mtp_ss_out_desc,
+       (struct usb_descriptor_header *) &mtp_ss_out_comp_desc,
+       (struct usb_descriptor_header *) &mtp_intr_desc,
+       (struct usb_descriptor_header *) &mtp_intr_ss_comp_desc,
+       NULL,
+};
+
 static struct usb_string mtp_string_defs[] = {
        /* Naming interface "MTP" so libmtp will recognize us */
        [INTERFACE_STRING_INDEX].s      = "MTP",
@@ -1131,10 +1187,24 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
                mtp_highspeed_out_desc.bEndpointAddress =
                        mtp_fullspeed_out_desc.bEndpointAddress;
        }
+       /* support super speed hardware */
+       if (gadget_is_superspeed(c->cdev->gadget)) {
+               unsigned max_burst;
+
+               /* Calculate bMaxBurst, we know packet size is 1024 */
+               max_burst = min_t(unsigned, MTP_BULK_BUFFER_SIZE / 1024, 15);
+               mtp_ss_in_desc.bEndpointAddress =
+                       mtp_fullspeed_in_desc.bEndpointAddress;
+               mtp_ss_in_comp_desc.bMaxBurst = max_burst;
+               mtp_ss_out_desc.bEndpointAddress =
+                       mtp_fullspeed_out_desc.bEndpointAddress;
+               mtp_ss_out_comp_desc.bMaxBurst = max_burst;
+       }
 
        DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
-                       gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
-                       f->name, dev->ep_in->name, dev->ep_out->name);
+               gadget_is_superspeed(c->cdev->gadget) ? "super" :
+               (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full"),
+               f->name, dev->ep_in->name, dev->ep_out->name);
        return 0;
 }
 
@@ -1410,9 +1480,11 @@ struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi,
        if (mtp_config) {
                dev->function.fs_descriptors = fs_mtp_descs;
                dev->function.hs_descriptors = hs_mtp_descs;
+               dev->function.ss_descriptors = ss_mtp_descs;
        } else {
                dev->function.fs_descriptors = fs_ptp_descs;
                dev->function.hs_descriptors = hs_ptp_descs;
+               dev->function.ss_descriptors = ss_ptp_descs;
        }
        dev->function.bind = mtp_function_bind;
        dev->function.unbind = mtp_function_unbind;