]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/usb/gadget/f_acm.c
Merge branch 'for-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
[mirror_ubuntu-bionic-kernel.git] / drivers / usb / gadget / f_acm.c
index 3f8849339adefe65bc5c2bc068cea34bc809407a..d672250a61fa60253e4507c16e7ec199038dae81 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) 2008 by David Brownell
  * Copyright (C) 2008 by Nokia Corporation
  * Copyright (C) 2009 by Samsung Electronics
- * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
+ * Author: Michal Nazarewicz (mina86@mina86.com)
  *
  * This software is distributed under the terms of the GNU General
  * Public License ("GPL") as published by the Free Software Foundation,
@@ -237,6 +237,42 @@ static struct usb_descriptor_header *acm_hs_function[] = {
        NULL,
 };
 
+static struct usb_endpoint_descriptor acm_ss_in_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor acm_ss_out_desc = {
+       .bLength =              USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = {
+       .bLength =              sizeof acm_ss_bulk_comp_desc,
+       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *acm_ss_function[] = {
+       (struct usb_descriptor_header *) &acm_iad_descriptor,
+       (struct usb_descriptor_header *) &acm_control_interface_desc,
+       (struct usb_descriptor_header *) &acm_header_desc,
+       (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
+       (struct usb_descriptor_header *) &acm_descriptor,
+       (struct usb_descriptor_header *) &acm_union_desc,
+       (struct usb_descriptor_header *) &acm_hs_notify_desc,
+       (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+       (struct usb_descriptor_header *) &acm_data_interface_desc,
+       (struct usb_descriptor_header *) &acm_ss_in_desc,
+       (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+       (struct usb_descriptor_header *) &acm_ss_out_desc,
+       (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc,
+       NULL,
+};
+
 /* string descriptors: */
 
 #define ACM_CTRL_IDX   0
@@ -643,9 +679,21 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
                /* copy descriptors */
                f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
        }
+       if (gadget_is_superspeed(c->cdev->gadget)) {
+               acm_ss_in_desc.bEndpointAddress =
+                       acm_fs_in_desc.bEndpointAddress;
+               acm_ss_out_desc.bEndpointAddress =
+                       acm_fs_out_desc.bEndpointAddress;
+
+               /* copy descriptors, and track endpoint copies */
+               f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
+               if (!f->ss_descriptors)
+                       goto fail;
+       }
 
        DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
                        acm->port_num,
+                       gadget_is_superspeed(c->cdev->gadget) ? "super" :
                        gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
                        acm->port.in->name, acm->port.out->name,
                        acm->notify->name);
@@ -675,6 +723,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
 
        if (gadget_is_dualspeed(c->cdev->gadget))
                usb_free_descriptors(f->hs_descriptors);
+       if (gadget_is_superspeed(c->cdev->gadget))
+               usb_free_descriptors(f->ss_descriptors);
        usb_free_descriptors(f->descriptors);
        gs_free_req(acm->notify, acm->notify_req);
        kfree(acm);