diff options
author | Felipe Balbi <balbi@ti.com> | 2011-08-03 14:33:27 +0300 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-10-13 20:39:59 +0300 |
commit | 4bb99b7c82bac1488a0228d2363db1f68d90f6f3 (patch) | |
tree | 62741be3938a236aba3539402f7030d2eeb417bd /drivers/usb/gadget/storage_common.c | |
parent | 089b837a39552ee49a4ea4c188e8c3517473f10c (diff) | |
download | linux-4bb99b7c82bac1488a0228d2363db1f68d90f6f3.tar.bz2 |
usb: gadget: storage: add superspeed support
this patch adds superspeed descriptors for the
storage gadgets.
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/storage_common.c')
-rw-r--r-- | drivers/usb/gadget/storage_common.c | 120 |
1 files changed, 118 insertions, 2 deletions
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 523626274c0f..c7f291a331df 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -515,12 +515,128 @@ static struct usb_descriptor_header *fsg_hs_function[] = { NULL, }; +static struct usb_endpoint_descriptor +fsg_ss_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ +}; + +static struct usb_endpoint_descriptor +fsg_ss_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_ss_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .wBytesPerInterval = cpu_to_le16(2), +}; + +#ifndef FSG_NO_OTG +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = { + .bLength = USB_DT_USB_EXT_CAP_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_CAP_TYPE_EXT, + + .bmAttributes = cpu_to_le32(USB_LPM_SUPPORT), +}; + +static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { + .bLength = USB_DT_USB_SS_CAP_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_SS_CAP_TYPE, + + /* .bmAttributes = LTM is not supported yet */ + + .wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION + | USB_FULL_SPEED_OPERATION + | USB_HIGH_SPEED_OPERATION + | USB_5GBPS_OPERATION), + .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, + .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, + .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT, +}; + +static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + + .wTotalLength = USB_DT_BOS_SIZE + + USB_DT_USB_EXT_CAP_SIZE + + USB_DT_USB_SS_CAP_SIZE, + + .bNumDeviceCaps = 2, +}; + +static struct usb_descriptor_header *fsg_ss_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_ss_intr_in_desc, + (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc, +#endif + NULL, +}; + /* Maxpacket and other transfer characteristics vary by speed. */ static __maybe_unused struct usb_endpoint_descriptor * fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, - struct usb_endpoint_descriptor *hs) + struct usb_endpoint_descriptor *hs, + struct usb_endpoint_descriptor *ss) { - if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) + return ss; + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) return hs; return fs; } |