usb: gadget: always update HS/SS descriptors and create a copy of them
[deliverable/linux.git] / drivers / usb / gadget / f_ecm.c
index 95bc94f8e57066a743428571707540d71775e751..2d3c5a46de8e71d08094f83a8f774397c8c10c7f 100644 (file)
@@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
  * encapsulated commands (vendor-specific, using control-OUT).
  */
 
-#define LOG2_STATUS_INTERVAL_MSEC      5       /* 1 << 5 == 32 msec */
+#define ECM_STATUS_INTERVAL_MS         32
 #define ECM_STATUS_BYTECOUNT           16      /* 8 byte header + data */
 
 
@@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(ECM_STATUS_BYTECOUNT),
-       .bInterval =            1 << LOG2_STATUS_INTERVAL_MSEC,
+       .bInterval =            ECM_STATUS_INTERVAL_MS,
 };
 
 static struct usb_endpoint_descriptor fs_ecm_in_desc = {
@@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(ECM_STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
 };
 
 static struct usb_endpoint_descriptor hs_ecm_in_desc = {
@@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_INT,
        .wMaxPacketSize =       cpu_to_le16(ECM_STATUS_BYTECOUNT),
-       .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
+       .bInterval =            USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
 };
 
 static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
@@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
 
 static struct usb_descriptor_header *ecm_ss_function[] = {
        /* CDC ECM control descriptors */
+       (struct usb_descriptor_header *) &ecm_iad_descriptor,
        (struct usb_descriptor_header *) &ecm_control_intf,
        (struct usb_descriptor_header *) &ecm_header_desc,
        (struct usb_descriptor_header *) &ecm_union_desc,
@@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        ecm->notify_req->context = ecm;
        ecm->notify_req->complete = ecm_notify_complete;
 
-       /* copy descriptors, and track endpoint copies */
-       f->descriptors = usb_copy_descriptors(ecm_fs_function);
-       if (!f->descriptors)
-               goto fail;
-
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
         * both speeds
         */
-       if (gadget_is_dualspeed(c->cdev->gadget)) {
-               hs_ecm_in_desc.bEndpointAddress =
-                               fs_ecm_in_desc.bEndpointAddress;
-               hs_ecm_out_desc.bEndpointAddress =
-                               fs_ecm_out_desc.bEndpointAddress;
-               hs_ecm_notify_desc.bEndpointAddress =
-                               fs_ecm_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
-               if (!f->hs_descriptors)
-                       goto fail;
-       }
-
-       if (gadget_is_superspeed(c->cdev->gadget)) {
-               ss_ecm_in_desc.bEndpointAddress =
-                               fs_ecm_in_desc.bEndpointAddress;
-               ss_ecm_out_desc.bEndpointAddress =
-                               fs_ecm_out_desc.bEndpointAddress;
-               ss_ecm_notify_desc.bEndpointAddress =
-                               fs_ecm_notify_desc.bEndpointAddress;
-
-               /* copy descriptors, and track endpoint copies */
-               f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
-               if (!f->ss_descriptors)
-                       goto fail;
-       }
+       hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+       hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+       hs_ecm_notify_desc.bEndpointAddress =
+               fs_ecm_notify_desc.bEndpointAddress;
+
+       ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+       ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+       ss_ecm_notify_desc.bEndpointAddress =
+               fs_ecm_notify_desc.bEndpointAddress;
+
+       status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
+                       ecm_ss_function);
+       if (status)
+               goto fail;
 
        /* NOTE:  all that is done without knowing or caring about
         * the network link ... which is unavailable to this code
@@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (f->descriptors)
-               usb_free_descriptors(f->descriptors);
-       if (f->hs_descriptors)
-               usb_free_descriptors(f->hs_descriptors);
-
        if (ecm->notify_req) {
                kfree(ecm->notify_req->buf);
                usb_ep_free_request(ecm->notify, ecm->notify_req);
@@ -808,9 +786,9 @@ fail:
        /* we might as well release our claims on endpoints */
        if (ecm->notify)
                ecm->notify->driver_data = NULL;
-       if (ecm->port.out_ep->desc)
+       if (ecm->port.out_ep)
                ecm->port.out_ep->driver_data = NULL;
-       if (ecm->port.in_ep->desc)
+       if (ecm->port.in_ep)
                ecm->port.in_ep->driver_data = NULL;
 
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -825,11 +803,7 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
 
        DBG(c->cdev, "ecm unbind\n");
 
-       if (gadget_is_superspeed(c->cdev->gadget))
-               usb_free_descriptors(f->ss_descriptors);
-       if (gadget_is_dualspeed(c->cdev->gadget))
-               usb_free_descriptors(f->hs_descriptors);
-       usb_free_descriptors(f->descriptors);
+       usb_free_all_descriptors(f);
 
        kfree(ecm->notify_req->buf);
        usb_ep_free_request(ecm->notify, ecm->notify_req);
This page took 0.026649 seconds and 5 git commands to generate.