|
@@ -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);
|