diff options
author | Felipe Balbi <balbi@ti.com> | 2011-08-03 07:33:27 -0400 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-10-13 13:39:59 -0400 |
commit | 4bb99b7c82bac1488a0228d2363db1f68d90f6f3 (patch) | |
tree | 62741be3938a236aba3539402f7030d2eeb417bd /drivers/usb | |
parent | 089b837a39552ee49a4ea4c188e8c3517473f10c (diff) |
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')
-rw-r--r-- | drivers/usb/gadget/f_mass_storage.c | 22 | ||||
-rw-r--r-- | drivers/usb/gadget/file_storage.c | 59 | ||||
-rw-r--r-- | drivers/usb/gadget/mass_storage.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/storage_common.c | 120 |
4 files changed, 190 insertions, 13 deletions
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 927ee88278bd..52583a235330 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -3023,6 +3023,28 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) | |||
3023 | } | 3023 | } |
3024 | } | 3024 | } |
3025 | 3025 | ||
3026 | if (gadget_is_superspeed(gadget)) { | ||
3027 | unsigned max_burst; | ||
3028 | |||
3029 | /* Calculate bMaxBurst, we know packet size is 1024 */ | ||
3030 | max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15); | ||
3031 | |||
3032 | fsg_ss_bulk_in_desc.bEndpointAddress = | ||
3033 | fsg_fs_bulk_in_desc.bEndpointAddress; | ||
3034 | fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; | ||
3035 | |||
3036 | fsg_ss_bulk_out_desc.bEndpointAddress = | ||
3037 | fsg_fs_bulk_out_desc.bEndpointAddress; | ||
3038 | fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; | ||
3039 | |||
3040 | f->ss_descriptors = usb_copy_descriptors(fsg_ss_function); | ||
3041 | if (unlikely(!f->ss_descriptors)) { | ||
3042 | usb_free_descriptors(f->hs_descriptors); | ||
3043 | usb_free_descriptors(f->descriptors); | ||
3044 | return -ENOMEM; | ||
3045 | } | ||
3046 | } | ||
3047 | |||
3026 | return 0; | 3048 | return 0; |
3027 | 3049 | ||
3028 | autoconf_fail: | 3050 | autoconf_fail: |
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a230009db734..5779549d7dc6 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -586,7 +586,19 @@ dev_qualifier = { | |||
586 | .bNumConfigurations = 1, | 586 | .bNumConfigurations = 1, |
587 | }; | 587 | }; |
588 | 588 | ||
589 | static int populate_bos(struct fsg_dev *fsg, u8 *buf) | ||
590 | { | ||
591 | memcpy(buf, &fsg_bos_desc, USB_DT_BOS_SIZE); | ||
592 | buf += USB_DT_BOS_SIZE; | ||
593 | |||
594 | memcpy(buf, &fsg_ext_cap_desc, USB_DT_USB_EXT_CAP_SIZE); | ||
595 | buf += USB_DT_USB_EXT_CAP_SIZE; | ||
589 | 596 | ||
597 | memcpy(buf, &fsg_ss_cap_desc, USB_DT_USB_SS_CAP_SIZE); | ||
598 | |||
599 | return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE | ||
600 | + USB_DT_USB_EXT_CAP_SIZE; | ||
601 | } | ||
590 | 602 | ||
591 | /* | 603 | /* |
592 | * Config descriptors must agree with the code that sets configurations | 604 | * Config descriptors must agree with the code that sets configurations |
@@ -935,7 +947,8 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
935 | break; | 947 | break; |
936 | case USB_DT_DEVICE_QUALIFIER: | 948 | case USB_DT_DEVICE_QUALIFIER: |
937 | VDBG(fsg, "get device qualifier\n"); | 949 | VDBG(fsg, "get device qualifier\n"); |
938 | if (!gadget_is_dualspeed(fsg->gadget)) | 950 | if (!gadget_is_dualspeed(fsg->gadget) || |
951 | fsg->gadget->speed == USB_SPEED_SUPER) | ||
939 | break; | 952 | break; |
940 | /* | 953 | /* |
941 | * Assume ep0 uses the same maxpacket value for both | 954 | * Assume ep0 uses the same maxpacket value for both |
@@ -948,7 +961,8 @@ static int standard_setup_req(struct fsg_dev *fsg, | |||
948 | 961 | ||
949 | case USB_DT_OTHER_SPEED_CONFIG: | 962 | case USB_DT_OTHER_SPEED_CONFIG: |
950 | VDBG(fsg, "get other-speed config descriptor\n"); | 963 | VDBG(fsg, "get other-speed config descriptor\n"); |
951 | if (!gadget_is_dualspeed(fsg->gadget)) | 964 | if (!gadget_is_dualspeed(fsg->gadget) || |
965 | fsg->gadget->speed == USB_SPEED_SUPER) | ||
952 | break; | 966 | break; |
953 | goto get_config; | 967 | goto get_config; |
954 | case USB_DT_CONFIG: | 968 | case USB_DT_CONFIG: |
@@ -967,7 +981,15 @@ get_config: | |||
967 | value = usb_gadget_get_string(&fsg_stringtab, | 981 | value = usb_gadget_get_string(&fsg_stringtab, |
968 | w_value & 0xff, req->buf); | 982 | w_value & 0xff, req->buf); |
969 | break; | 983 | break; |
984 | |||
985 | case USB_DT_BOS: | ||
986 | VDBG(fsg, "get bos descriptor\n"); | ||
987 | |||
988 | if (gadget_is_superspeed(fsg->gadget)) | ||
989 | value = populate_bos(fsg, req->buf); | ||
990 | break; | ||
970 | } | 991 | } |
992 | |||
971 | break; | 993 | break; |
972 | 994 | ||
973 | /* One config, two speeds */ | 995 | /* One config, two speeds */ |
@@ -2777,13 +2799,15 @@ reset: | |||
2777 | 2799 | ||
2778 | /* Enable the endpoints */ | 2800 | /* Enable the endpoints */ |
2779 | d = fsg_ep_desc(fsg->gadget, | 2801 | d = fsg_ep_desc(fsg->gadget, |
2780 | &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); | 2802 | &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc, |
2803 | &fsg_ss_bulk_in_desc); | ||
2781 | if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) | 2804 | if ((rc = enable_endpoint(fsg, fsg->bulk_in, d)) != 0) |
2782 | goto reset; | 2805 | goto reset; |
2783 | fsg->bulk_in_enabled = 1; | 2806 | fsg->bulk_in_enabled = 1; |
2784 | 2807 | ||
2785 | d = fsg_ep_desc(fsg->gadget, | 2808 | d = fsg_ep_desc(fsg->gadget, |
2786 | &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); | 2809 | &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc, |
2810 | &fsg_ss_bulk_out_desc); | ||
2787 | if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) | 2811 | if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) |
2788 | goto reset; | 2812 | goto reset; |
2789 | fsg->bulk_out_enabled = 1; | 2813 | fsg->bulk_out_enabled = 1; |
@@ -2792,7 +2816,8 @@ reset: | |||
2792 | 2816 | ||
2793 | if (transport_is_cbi()) { | 2817 | if (transport_is_cbi()) { |
2794 | d = fsg_ep_desc(fsg->gadget, | 2818 | d = fsg_ep_desc(fsg->gadget, |
2795 | &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc); | 2819 | &fsg_fs_intr_in_desc, &fsg_hs_intr_in_desc, |
2820 | &fsg_ss_intr_in_desc); | ||
2796 | if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) | 2821 | if ((rc = enable_endpoint(fsg, fsg->intr_in, d)) != 0) |
2797 | goto reset; | 2822 | goto reset; |
2798 | fsg->intr_in_enabled = 1; | 2823 | fsg->intr_in_enabled = 1; |
@@ -3424,6 +3449,24 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3424 | fsg_fs_intr_in_desc.bEndpointAddress; | 3449 | fsg_fs_intr_in_desc.bEndpointAddress; |
3425 | } | 3450 | } |
3426 | 3451 | ||
3452 | if (gadget_is_superspeed(gadget)) { | ||
3453 | unsigned max_burst; | ||
3454 | |||
3455 | fsg_ss_function[i + FSG_SS_FUNCTION_PRE_EP_ENTRIES] = NULL; | ||
3456 | |||
3457 | /* Calculate bMaxBurst, we know packet size is 1024 */ | ||
3458 | max_burst = min_t(unsigned, mod_data.buflen / 1024, 15); | ||
3459 | |||
3460 | /* Assume endpoint addresses are the same for both speeds */ | ||
3461 | fsg_ss_bulk_in_desc.bEndpointAddress = | ||
3462 | fsg_fs_bulk_in_desc.bEndpointAddress; | ||
3463 | fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; | ||
3464 | |||
3465 | fsg_ss_bulk_out_desc.bEndpointAddress = | ||
3466 | fsg_fs_bulk_out_desc.bEndpointAddress; | ||
3467 | fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; | ||
3468 | } | ||
3469 | |||
3427 | if (gadget_is_otg(gadget)) | 3470 | if (gadget_is_otg(gadget)) |
3428 | fsg_otg_desc.bmAttributes |= USB_OTG_HNP; | 3471 | fsg_otg_desc.bmAttributes |= USB_OTG_HNP; |
3429 | 3472 | ||
@@ -3540,11 +3583,7 @@ static void fsg_resume(struct usb_gadget *gadget) | |||
3540 | /*-------------------------------------------------------------------------*/ | 3583 | /*-------------------------------------------------------------------------*/ |
3541 | 3584 | ||
3542 | static struct usb_gadget_driver fsg_driver = { | 3585 | static struct usb_gadget_driver fsg_driver = { |
3543 | #ifdef CONFIG_USB_GADGET_DUALSPEED | 3586 | .speed = USB_SPEED_SUPER, |
3544 | .speed = USB_SPEED_HIGH, | ||
3545 | #else | ||
3546 | .speed = USB_SPEED_FULL, | ||
3547 | #endif | ||
3548 | .function = (char *) fsg_string_product, | 3587 | .function = (char *) fsg_string_product, |
3549 | .unbind = fsg_unbind, | 3588 | .unbind = fsg_unbind, |
3550 | .disconnect = fsg_disconnect, | 3589 | .disconnect = fsg_disconnect, |
diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index d2a9dcb67088..e24f72f82a47 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c | |||
@@ -160,7 +160,7 @@ static struct usb_composite_driver msg_driver = { | |||
160 | .name = "g_mass_storage", | 160 | .name = "g_mass_storage", |
161 | .dev = &msg_device_desc, | 161 | .dev = &msg_device_desc, |
162 | .iProduct = DRIVER_DESC, | 162 | .iProduct = DRIVER_DESC, |
163 | .max_speed = USB_SPEED_HIGH, | 163 | .max_speed = USB_SPEED_SUPER, |
164 | .needs_serial = 1, | 164 | .needs_serial = 1, |
165 | }; | 165 | }; |
166 | 166 | ||
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[] = { | |||
515 | NULL, | 515 | NULL, |
516 | }; | 516 | }; |
517 | 517 | ||
518 | static struct usb_endpoint_descriptor | ||
519 | fsg_ss_bulk_in_desc = { | ||
520 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
521 | .bDescriptorType = USB_DT_ENDPOINT, | ||
522 | |||
523 | /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ | ||
524 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
525 | .wMaxPacketSize = cpu_to_le16(1024), | ||
526 | }; | ||
527 | |||
528 | static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { | ||
529 | .bLength = sizeof(fsg_ss_bulk_in_comp_desc), | ||
530 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
531 | |||
532 | /*.bMaxBurst = DYNAMIC, */ | ||
533 | }; | ||
534 | |||
535 | static struct usb_endpoint_descriptor | ||
536 | fsg_ss_bulk_out_desc = { | ||
537 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
538 | .bDescriptorType = USB_DT_ENDPOINT, | ||
539 | |||
540 | /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ | ||
541 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
542 | .wMaxPacketSize = cpu_to_le16(1024), | ||
543 | }; | ||
544 | |||
545 | static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { | ||
546 | .bLength = sizeof(fsg_ss_bulk_in_comp_desc), | ||
547 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
548 | |||
549 | /*.bMaxBurst = DYNAMIC, */ | ||
550 | }; | ||
551 | |||
552 | #ifndef FSG_NO_INTR_EP | ||
553 | |||
554 | static struct usb_endpoint_descriptor | ||
555 | fsg_ss_intr_in_desc = { | ||
556 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
557 | .bDescriptorType = USB_DT_ENDPOINT, | ||
558 | |||
559 | /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ | ||
560 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
561 | .wMaxPacketSize = cpu_to_le16(2), | ||
562 | .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ | ||
563 | }; | ||
564 | |||
565 | static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = { | ||
566 | .bLength = sizeof(fsg_ss_bulk_in_comp_desc), | ||
567 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
568 | |||
569 | .wBytesPerInterval = cpu_to_le16(2), | ||
570 | }; | ||
571 | |||
572 | #ifndef FSG_NO_OTG | ||
573 | # define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2 | ||
574 | #else | ||
575 | # define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1 | ||
576 | #endif | ||
577 | |||
578 | #endif | ||
579 | |||
580 | static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = { | ||
581 | .bLength = USB_DT_USB_EXT_CAP_SIZE, | ||
582 | .bDescriptorType = USB_DT_DEVICE_CAPABILITY, | ||
583 | .bDevCapabilityType = USB_CAP_TYPE_EXT, | ||
584 | |||
585 | .bmAttributes = cpu_to_le32(USB_LPM_SUPPORT), | ||
586 | }; | ||
587 | |||
588 | static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { | ||
589 | .bLength = USB_DT_USB_SS_CAP_SIZE, | ||
590 | .bDescriptorType = USB_DT_DEVICE_CAPABILITY, | ||
591 | .bDevCapabilityType = USB_SS_CAP_TYPE, | ||
592 | |||
593 | /* .bmAttributes = LTM is not supported yet */ | ||
594 | |||
595 | .wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION | ||
596 | | USB_FULL_SPEED_OPERATION | ||
597 | | USB_HIGH_SPEED_OPERATION | ||
598 | | USB_5GBPS_OPERATION), | ||
599 | .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, | ||
600 | .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, | ||
601 | .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT, | ||
602 | }; | ||
603 | |||
604 | static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { | ||
605 | .bLength = USB_DT_BOS_SIZE, | ||
606 | .bDescriptorType = USB_DT_BOS, | ||
607 | |||
608 | .wTotalLength = USB_DT_BOS_SIZE | ||
609 | + USB_DT_USB_EXT_CAP_SIZE | ||
610 | + USB_DT_USB_SS_CAP_SIZE, | ||
611 | |||
612 | .bNumDeviceCaps = 2, | ||
613 | }; | ||
614 | |||
615 | static struct usb_descriptor_header *fsg_ss_function[] = { | ||
616 | #ifndef FSG_NO_OTG | ||
617 | (struct usb_descriptor_header *) &fsg_otg_desc, | ||
618 | #endif | ||
619 | (struct usb_descriptor_header *) &fsg_intf_desc, | ||
620 | (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, | ||
621 | (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, | ||
622 | (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc, | ||
623 | (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, | ||
624 | #ifndef FSG_NO_INTR_EP | ||
625 | (struct usb_descriptor_header *) &fsg_ss_intr_in_desc, | ||
626 | (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc, | ||
627 | #endif | ||
628 | NULL, | ||
629 | }; | ||
630 | |||
518 | /* Maxpacket and other transfer characteristics vary by speed. */ | 631 | /* Maxpacket and other transfer characteristics vary by speed. */ |
519 | static __maybe_unused struct usb_endpoint_descriptor * | 632 | static __maybe_unused struct usb_endpoint_descriptor * |
520 | fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, | 633 | fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, |
521 | struct usb_endpoint_descriptor *hs) | 634 | struct usb_endpoint_descriptor *hs, |
635 | struct usb_endpoint_descriptor *ss) | ||
522 | { | 636 | { |
523 | if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | 637 | if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) |
638 | return ss; | ||
639 | else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) | ||
524 | return hs; | 640 | return hs; |
525 | return fs; | 641 | return fs; |
526 | } | 642 | } |