Skip to content

Commit

Permalink
usb: gadget: add SS descriptors to Ethernet gadget
Browse files Browse the repository at this point in the history
Add SuperSpeed descriptors to the Network USB
function drivers.

This has been lightly tested using a Linux host.
I was able to ssh from device to host and host to
device, no obvious problems seen.

Signed-off-by: Paul Zimmerman <paulz@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Paul Zimmerman authored and Felipe Balbi committed Jul 8, 2011
1 parent 96fe53e commit 04617db
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 11 deletions.
2 changes: 1 addition & 1 deletion drivers/usb/gadget/ether.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ static struct usb_composite_driver eth_driver = {
.name = "g_ether",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.max_speed = USB_SPEED_SUPER,
.unbind = __exit_p(eth_unbind),
};

Expand Down
100 changes: 98 additions & 2 deletions drivers/usb/gadget/f_ecm.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,12 @@ static inline struct f_ecm *func_to_ecm(struct usb_function *f)
/* peak (theoretical) bulk transfer rate in bits-per-second */
static inline unsigned ecm_bitrate(struct usb_gadget *g)
{
if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
return 13 * 1024 * 8 * 1000 * 8;
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
return 13 * 512 * 8 * 1000 * 8;
else
return 19 * 64 * 1 * 1000 * 8;
return 19 * 64 * 1 * 1000 * 8;
}

/*-------------------------------------------------------------------------*/
Expand Down Expand Up @@ -210,8 +212,10 @@ static struct usb_descriptor_header *ecm_fs_function[] = {
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ecm_desc,

/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &fs_ecm_notify_desc,

/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
Expand All @@ -231,6 +235,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};

static struct usb_endpoint_descriptor hs_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
Expand All @@ -255,8 +260,10 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ecm_desc,

/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &hs_ecm_notify_desc,

/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
Expand All @@ -265,6 +272,76 @@ static struct usb_descriptor_header *ecm_hs_function[] = {
NULL,
};

/* super speed support: */

static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
.bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
};

static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
.bLength = sizeof ss_ecm_intr_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,

/* the following 3 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
.wBytesPerInterval = cpu_to_le16(ECM_STATUS_BYTECOUNT),
};

static struct usb_endpoint_descriptor ss_ecm_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};

static struct usb_endpoint_descriptor ss_ecm_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};

static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
.bLength = sizeof ss_ecm_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,

/* the following 2 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
};

static struct usb_descriptor_header *ecm_ss_function[] = {
/* CDC ECM control descriptors */
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
(struct usb_descriptor_header *) &ecm_desc,

/* NOTE: status endpoint might need to be removed */
(struct usb_descriptor_header *) &ss_ecm_notify_desc,
(struct usb_descriptor_header *) &ss_ecm_intr_comp_desc,

/* data interface, altsettings 0 and 1 */
(struct usb_descriptor_header *) &ecm_data_nop_intf,
(struct usb_descriptor_header *) &ecm_data_intf,
(struct usb_descriptor_header *) &ss_ecm_in_desc,
(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
(struct usb_descriptor_header *) &ss_ecm_out_desc,
(struct usb_descriptor_header *) &ss_ecm_bulk_comp_desc,
NULL,
};

/* string descriptors: */

static struct usb_string ecm_string_defs[] = {
Expand Down Expand Up @@ -679,6 +756,20 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
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;
}

/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
* until we're activated via set_alt().
Expand All @@ -688,6 +779,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->port.close = ecm_close;

DBG(cdev, "CDC Ethernet: %s speed IN/%s OUT/%s NOTIFY/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
ecm->port.in_ep->name, ecm->port.out_ep->name,
ecm->notify->name);
Expand All @@ -696,6 +788,8 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
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);
Expand All @@ -722,6 +816,8 @@ 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);
Expand Down
56 changes: 56 additions & 0 deletions drivers/usb/gadget/f_eem.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,45 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = {
NULL,
};

/* super speed support: */

static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};

static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,

.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};

static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = {
.bLength = sizeof eem_ss_bulk_comp_desc,
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,

/* the following 2 values can be tweaked if necessary */
/* .bMaxBurst = 0, */
/* .bmAttributes = 0, */
};

static struct usb_descriptor_header *eem_ss_function[] __initdata = {
/* CDC EEM control descriptors */
(struct usb_descriptor_header *) &eem_intf,
(struct usb_descriptor_header *) &eem_ss_in_desc,
(struct usb_descriptor_header *) &eem_ss_bulk_comp_desc,
(struct usb_descriptor_header *) &eem_ss_out_desc,
(struct usb_descriptor_header *) &eem_ss_bulk_comp_desc,
NULL,
};

/* string descriptors: */

static struct usb_string eem_string_defs[] = {
Expand Down Expand Up @@ -265,14 +304,29 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
goto fail;
}

if (gadget_is_superspeed(c->cdev->gadget)) {
eem_ss_in_desc.bEndpointAddress =
eem_fs_in_desc.bEndpointAddress;
eem_ss_out_desc.bEndpointAddress =
eem_fs_out_desc.bEndpointAddress;

/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eem_ss_function);
if (!f->ss_descriptors)
goto fail;
}

DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
eem->port.in_ep->name, eem->port.out_ep->name);
return 0;

fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);

/* we might as well release our claims on endpoints */
if (eem->port.out_ep->desc)
Expand All @@ -292,6 +346,8 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)

DBG(c->cdev, "eem 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);
Expand Down
Loading

0 comments on commit 04617db

Please sign in to comment.