aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c257
1 files changed, 239 insertions, 18 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 897e4f57422f..c5abe270970a 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -27,7 +27,7 @@
27#include <linux/utsname.h> 27#include <linux/utsname.h>
28 28
29#include <linux/usb/composite.h> 29#include <linux/usb/composite.h>
30 30#include <asm/unaligned.h>
31 31
32/* 32/*
33 * The code in this file is utility code, used to build a gadget driver 33 * The code in this file is utility code, used to build a gadget driver
@@ -128,6 +128,9 @@ int config_ep_by_speed(struct usb_gadget *g,
128 struct usb_endpoint_descriptor *chosen_desc = NULL; 128 struct usb_endpoint_descriptor *chosen_desc = NULL;
129 struct usb_descriptor_header **speed_desc = NULL; 129 struct usb_descriptor_header **speed_desc = NULL;
130 130
131 struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
132 int want_comp_desc = 0;
133
131 struct usb_descriptor_header **d_spd; /* cursor for speed desc */ 134 struct usb_descriptor_header **d_spd; /* cursor for speed desc */
132 135
133 if (!g || !f || !_ep) 136 if (!g || !f || !_ep)
@@ -135,6 +138,13 @@ int config_ep_by_speed(struct usb_gadget *g,
135 138
136 /* select desired speed */ 139 /* select desired speed */
137 switch (g->speed) { 140 switch (g->speed) {
141 case USB_SPEED_SUPER:
142 if (gadget_is_superspeed(g)) {
143 speed_desc = f->ss_descriptors;
144 want_comp_desc = 1;
145 break;
146 }
147 /* else: Fall trough */
138 case USB_SPEED_HIGH: 148 case USB_SPEED_HIGH:
139 if (gadget_is_dualspeed(g)) { 149 if (gadget_is_dualspeed(g)) {
140 speed_desc = f->hs_descriptors; 150 speed_desc = f->hs_descriptors;
@@ -156,7 +166,36 @@ ep_found:
156 /* commit results */ 166 /* commit results */
157 _ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize); 167 _ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize);
158 _ep->desc = chosen_desc; 168 _ep->desc = chosen_desc;
169 _ep->comp_desc = NULL;
170 _ep->maxburst = 0;
171 _ep->mult = 0;
172 if (!want_comp_desc)
173 return 0;
159 174
175 /*
176 * Companion descriptor should follow EP descriptor
177 * USB 3.0 spec, #9.6.7
178 */
179 comp_desc = (struct usb_ss_ep_comp_descriptor *)*(++d_spd);
180 if (!comp_desc ||
181 (comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP))
182 return -EIO;
183 _ep->comp_desc = comp_desc;
184 if (g->speed == USB_SPEED_SUPER) {
185 switch (usb_endpoint_type(_ep->desc)) {
186 case USB_ENDPOINT_XFER_BULK:
187 case USB_ENDPOINT_XFER_INT:
188 _ep->maxburst = comp_desc->bMaxBurst;
189 break;
190 case USB_ENDPOINT_XFER_ISOC:
191 /* mult: bits 1:0 of bmAttributes */
192 _ep->mult = comp_desc->bmAttributes & 0x3;
193 break;
194 default:
195 /* Do nothing for control endpoints */
196 break;
197 }
198 }
160 return 0; 199 return 0;
161} 200}
162 201
@@ -208,6 +247,8 @@ int usb_add_function(struct usb_configuration *config,
208 config->fullspeed = true; 247 config->fullspeed = true;
209 if (!config->highspeed && function->hs_descriptors) 248 if (!config->highspeed && function->hs_descriptors)
210 config->highspeed = true; 249 config->highspeed = true;
250 if (!config->superspeed && function->ss_descriptors)
251 config->superspeed = true;
211 252
212done: 253done:
213 if (value) 254 if (value)
@@ -351,10 +392,17 @@ static int config_buf(struct usb_configuration *config,
351 list_for_each_entry(f, &config->functions, list) { 392 list_for_each_entry(f, &config->functions, list) {
352 struct usb_descriptor_header **descriptors; 393 struct usb_descriptor_header **descriptors;
353 394
354 if (speed == USB_SPEED_HIGH) 395 switch (speed) {
396 case USB_SPEED_SUPER:
397 descriptors = f->ss_descriptors;
398 break;
399 case USB_SPEED_HIGH:
355 descriptors = f->hs_descriptors; 400 descriptors = f->hs_descriptors;
356 else 401 break;
402 default:
357 descriptors = f->descriptors; 403 descriptors = f->descriptors;
404 }
405
358 if (!descriptors) 406 if (!descriptors)
359 continue; 407 continue;
360 status = usb_descriptor_fillbuf(next, len, 408 status = usb_descriptor_fillbuf(next, len,
@@ -377,9 +425,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
377 u8 type = w_value >> 8; 425 u8 type = w_value >> 8;
378 enum usb_device_speed speed = USB_SPEED_UNKNOWN; 426 enum usb_device_speed speed = USB_SPEED_UNKNOWN;
379 427
380 if (gadget_is_dualspeed(gadget)) { 428 if (gadget->speed == USB_SPEED_SUPER)
381 int hs = 0; 429 speed = gadget->speed;
382 430 else if (gadget_is_dualspeed(gadget)) {
431 int hs = 0;
383 if (gadget->speed == USB_SPEED_HIGH) 432 if (gadget->speed == USB_SPEED_HIGH)
384 hs = 1; 433 hs = 1;
385 if (type == USB_DT_OTHER_SPEED_CONFIG) 434 if (type == USB_DT_OTHER_SPEED_CONFIG)
@@ -393,13 +442,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
393 w_value &= 0xff; 442 w_value &= 0xff;
394 list_for_each_entry(c, &cdev->configs, list) { 443 list_for_each_entry(c, &cdev->configs, list) {
395 /* ignore configs that won't work at this speed */ 444 /* ignore configs that won't work at this speed */
396 if (speed == USB_SPEED_HIGH) { 445 switch (speed) {
446 case USB_SPEED_SUPER:
447 if (!c->superspeed)
448 continue;
449 break;
450 case USB_SPEED_HIGH:
397 if (!c->highspeed) 451 if (!c->highspeed)
398 continue; 452 continue;
399 } else { 453 break;
454 default:
400 if (!c->fullspeed) 455 if (!c->fullspeed)
401 continue; 456 continue;
402 } 457 }
458
403 if (w_value == 0) 459 if (w_value == 0)
404 return config_buf(c, speed, cdev->req->buf, type); 460 return config_buf(c, speed, cdev->req->buf, type);
405 w_value--; 461 w_value--;
@@ -413,16 +469,22 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
413 struct usb_configuration *c; 469 struct usb_configuration *c;
414 unsigned count = 0; 470 unsigned count = 0;
415 int hs = 0; 471 int hs = 0;
472 int ss = 0;
416 473
417 if (gadget_is_dualspeed(gadget)) { 474 if (gadget_is_dualspeed(gadget)) {
418 if (gadget->speed == USB_SPEED_HIGH) 475 if (gadget->speed == USB_SPEED_HIGH)
419 hs = 1; 476 hs = 1;
477 if (gadget->speed == USB_SPEED_SUPER)
478 ss = 1;
420 if (type == USB_DT_DEVICE_QUALIFIER) 479 if (type == USB_DT_DEVICE_QUALIFIER)
421 hs = !hs; 480 hs = !hs;
422 } 481 }
423 list_for_each_entry(c, &cdev->configs, list) { 482 list_for_each_entry(c, &cdev->configs, list) {
424 /* ignore configs that won't work at this speed */ 483 /* ignore configs that won't work at this speed */
425 if (hs) { 484 if (ss) {
485 if (!c->superspeed)
486 continue;
487 } else if (hs) {
426 if (!c->highspeed) 488 if (!c->highspeed)
427 continue; 489 continue;
428 } else { 490 } else {
@@ -434,6 +496,71 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
434 return count; 496 return count;
435} 497}
436 498
499/**
500 * bos_desc() - prepares the BOS descriptor.
501 * @cdev: pointer to usb_composite device to generate the bos
502 * descriptor for
503 *
504 * This function generates the BOS (Binary Device Object)
505 * descriptor and its device capabilities descriptors. The BOS
506 * descriptor should be supported by a SuperSpeed device.
507 */
508static int bos_desc(struct usb_composite_dev *cdev)
509{
510 struct usb_ext_cap_descriptor *usb_ext;
511 struct usb_ss_cap_descriptor *ss_cap;
512 struct usb_dcd_config_params dcd_config_params;
513 struct usb_bos_descriptor *bos = cdev->req->buf;
514
515 bos->bLength = USB_DT_BOS_SIZE;
516 bos->bDescriptorType = USB_DT_BOS;
517
518 bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE);
519 bos->bNumDeviceCaps = 0;
520
521 /*
522 * A SuperSpeed device shall include the USB2.0 extension descriptor
523 * and shall support LPM when operating in USB2.0 HS mode.
524 */
525 usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
526 bos->bNumDeviceCaps++;
527 le16_add_cpu(&bos->wTotalLength, USB_DT_USB_EXT_CAP_SIZE);
528 usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
529 usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
530 usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
531 usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT);
532
533 /*
534 * The Superspeed USB Capability descriptor shall be implemented by all
535 * SuperSpeed devices.
536 */
537 ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
538 bos->bNumDeviceCaps++;
539 le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
540 ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
541 ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
542 ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
543 ss_cap->bmAttributes = 0; /* LTM is not supported yet */
544 ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
545 USB_FULL_SPEED_OPERATION |
546 USB_HIGH_SPEED_OPERATION |
547 USB_5GBPS_OPERATION);
548 ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
549
550 /* Get Controller configuration */
551 if (cdev->gadget->ops->get_config_params)
552 cdev->gadget->ops->get_config_params(&dcd_config_params);
553 else {
554 dcd_config_params.bU1devExitLat = USB_DEFULT_U1_DEV_EXIT_LAT;
555 dcd_config_params.bU2DevExitLat =
556 cpu_to_le16(USB_DEFULT_U2_DEV_EXIT_LAT);
557 }
558 ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
559 ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
560
561 return le16_to_cpu(bos->wTotalLength);
562}
563
437static void device_qual(struct usb_composite_dev *cdev) 564static void device_qual(struct usb_composite_dev *cdev)
438{ 565{
439 struct usb_qualifier_descriptor *qual = cdev->req->buf; 566 struct usb_qualifier_descriptor *qual = cdev->req->buf;
@@ -477,20 +604,27 @@ static int set_config(struct usb_composite_dev *cdev,
477 unsigned power = gadget_is_otg(gadget) ? 8 : 100; 604 unsigned power = gadget_is_otg(gadget) ? 8 : 100;
478 int tmp; 605 int tmp;
479 606
480 if (cdev->config)
481 reset_config(cdev);
482
483 if (number) { 607 if (number) {
484 list_for_each_entry(c, &cdev->configs, list) { 608 list_for_each_entry(c, &cdev->configs, list) {
485 if (c->bConfigurationValue == number) { 609 if (c->bConfigurationValue == number) {
610 /*
611 * We disable the FDs of the previous
612 * configuration only if the new configuration
613 * is a valid one
614 */
615 if (cdev->config)
616 reset_config(cdev);
486 result = 0; 617 result = 0;
487 break; 618 break;
488 } 619 }
489 } 620 }
490 if (result < 0) 621 if (result < 0)
491 goto done; 622 goto done;
492 } else 623 } else { /* Zero configuration value - need to reset the config */
624 if (cdev->config)
625 reset_config(cdev);
493 result = 0; 626 result = 0;
627 }
494 628
495 INFO(cdev, "%s speed config #%d: %s\n", 629 INFO(cdev, "%s speed config #%d: %s\n",
496 ({ char *speed; 630 ({ char *speed;
@@ -504,6 +638,9 @@ static int set_config(struct usb_composite_dev *cdev,
504 case USB_SPEED_HIGH: 638 case USB_SPEED_HIGH:
505 speed = "high"; 639 speed = "high";
506 break; 640 break;
641 case USB_SPEED_SUPER:
642 speed = "super";
643 break;
507 default: 644 default:
508 speed = "?"; 645 speed = "?";
509 break; 646 break;
@@ -528,10 +665,16 @@ static int set_config(struct usb_composite_dev *cdev,
528 * function's setup callback instead of the current 665 * function's setup callback instead of the current
529 * configuration's setup callback. 666 * configuration's setup callback.
530 */ 667 */
531 if (gadget->speed == USB_SPEED_HIGH) 668 switch (gadget->speed) {
669 case USB_SPEED_SUPER:
670 descriptors = f->ss_descriptors;
671 break;
672 case USB_SPEED_HIGH:
532 descriptors = f->hs_descriptors; 673 descriptors = f->hs_descriptors;
533 else 674 break;
675 default:
534 descriptors = f->descriptors; 676 descriptors = f->descriptors;
677 }
535 678
536 for (; *descriptors; ++descriptors) { 679 for (; *descriptors; ++descriptors) {
537 struct usb_endpoint_descriptor *ep; 680 struct usb_endpoint_descriptor *ep;
@@ -624,8 +767,9 @@ int usb_add_config(struct usb_composite_dev *cdev,
624 } else { 767 } else {
625 unsigned i; 768 unsigned i;
626 769
627 DBG(cdev, "cfg %d/%p speeds:%s%s\n", 770 DBG(cdev, "cfg %d/%p speeds:%s%s%s\n",
628 config->bConfigurationValue, config, 771 config->bConfigurationValue, config,
772 config->superspeed ? " super" : "",
629 config->highspeed ? " high" : "", 773 config->highspeed ? " high" : "",
630 config->fullspeed 774 config->fullspeed
631 ? (gadget_is_dualspeed(cdev->gadget) 775 ? (gadget_is_dualspeed(cdev->gadget)
@@ -904,6 +1048,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
904 struct usb_composite_dev *cdev = get_gadget_data(gadget); 1048 struct usb_composite_dev *cdev = get_gadget_data(gadget);
905 struct usb_request *req = cdev->req; 1049 struct usb_request *req = cdev->req;
906 int value = -EOPNOTSUPP; 1050 int value = -EOPNOTSUPP;
1051 int status = 0;
907 u16 w_index = le16_to_cpu(ctrl->wIndex); 1052 u16 w_index = le16_to_cpu(ctrl->wIndex);
908 u8 intf = w_index & 0xFF; 1053 u8 intf = w_index & 0xFF;
909 u16 w_value = le16_to_cpu(ctrl->wValue); 1054 u16 w_value = le16_to_cpu(ctrl->wValue);
@@ -931,18 +1076,29 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
931 case USB_DT_DEVICE: 1076 case USB_DT_DEVICE:
932 cdev->desc.bNumConfigurations = 1077 cdev->desc.bNumConfigurations =
933 count_configs(cdev, USB_DT_DEVICE); 1078 count_configs(cdev, USB_DT_DEVICE);
1079 cdev->desc.bMaxPacketSize0 =
1080 cdev->gadget->ep0->maxpacket;
1081 if (gadget_is_superspeed(gadget)) {
1082 if (gadget->speed >= USB_SPEED_SUPER)
1083 cdev->desc.bcdUSB = cpu_to_le16(0x0300);
1084 else
1085 cdev->desc.bcdUSB = cpu_to_le16(0x0210);
1086 }
1087
934 value = min(w_length, (u16) sizeof cdev->desc); 1088 value = min(w_length, (u16) sizeof cdev->desc);
935 memcpy(req->buf, &cdev->desc, value); 1089 memcpy(req->buf, &cdev->desc, value);
936 break; 1090 break;
937 case USB_DT_DEVICE_QUALIFIER: 1091 case USB_DT_DEVICE_QUALIFIER:
938 if (!gadget_is_dualspeed(gadget)) 1092 if (!gadget_is_dualspeed(gadget) ||
1093 gadget->speed >= USB_SPEED_SUPER)
939 break; 1094 break;
940 device_qual(cdev); 1095 device_qual(cdev);
941 value = min_t(int, w_length, 1096 value = min_t(int, w_length,
942 sizeof(struct usb_qualifier_descriptor)); 1097 sizeof(struct usb_qualifier_descriptor));
943 break; 1098 break;
944 case USB_DT_OTHER_SPEED_CONFIG: 1099 case USB_DT_OTHER_SPEED_CONFIG:
945 if (!gadget_is_dualspeed(gadget)) 1100 if (!gadget_is_dualspeed(gadget) ||
1101 gadget->speed >= USB_SPEED_SUPER)
946 break; 1102 break;
947 /* FALLTHROUGH */ 1103 /* FALLTHROUGH */
948 case USB_DT_CONFIG: 1104 case USB_DT_CONFIG:
@@ -956,6 +1112,12 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
956 if (value >= 0) 1112 if (value >= 0)
957 value = min(w_length, (u16) value); 1113 value = min(w_length, (u16) value);
958 break; 1114 break;
1115 case USB_DT_BOS:
1116 if (gadget_is_superspeed(gadget)) {
1117 value = bos_desc(cdev);
1118 value = min(w_length, (u16) value);
1119 }
1120 break;
959 } 1121 }
960 break; 1122 break;
961 1123
@@ -1023,6 +1185,61 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
1023 *((u8 *)req->buf) = value; 1185 *((u8 *)req->buf) = value;
1024 value = min(w_length, (u16) 1); 1186 value = min(w_length, (u16) 1);
1025 break; 1187 break;
1188
1189 /*
1190 * USB 3.0 additions:
1191 * Function driver should handle get_status request. If such cb
1192 * wasn't supplied we respond with default value = 0
1193 * Note: function driver should supply such cb only for the first
1194 * interface of the function
1195 */
1196 case USB_REQ_GET_STATUS:
1197 if (!gadget_is_superspeed(gadget))
1198 goto unknown;
1199 if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE))
1200 goto unknown;
1201 value = 2; /* This is the length of the get_status reply */
1202 put_unaligned_le16(0, req->buf);
1203 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
1204 break;
1205 f = cdev->config->interface[intf];
1206 if (!f)
1207 break;
1208 status = f->get_status ? f->get_status(f) : 0;
1209 if (status < 0)
1210 break;
1211 put_unaligned_le16(status & 0x0000ffff, req->buf);
1212 break;
1213 /*
1214 * Function drivers should handle SetFeature/ClearFeature
1215 * (FUNCTION_SUSPEND) request. function_suspend cb should be supplied
1216 * only for the first interface of the function
1217 */
1218 case USB_REQ_CLEAR_FEATURE:
1219 case USB_REQ_SET_FEATURE:
1220 if (!gadget_is_superspeed(gadget))
1221 goto unknown;
1222 if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE))
1223 goto unknown;
1224 switch (w_value) {
1225 case USB_INTRF_FUNC_SUSPEND:
1226 if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
1227 break;
1228 f = cdev->config->interface[intf];
1229 if (!f)
1230 break;
1231 value = 0;
1232 if (f->func_suspend)
1233 value = f->func_suspend(f, w_index >> 8);
1234 if (value < 0) {
1235 ERROR(cdev,
1236 "func_suspend() returned error %d\n",
1237 value);
1238 value = 0;
1239 }
1240 break;
1241 }
1242 break;
1026 default: 1243 default:
1027unknown: 1244unknown:
1028 VDBG(cdev, 1245 VDBG(cdev,
@@ -1340,7 +1557,11 @@ composite_resume(struct usb_gadget *gadget)
1340/*-------------------------------------------------------------------------*/ 1557/*-------------------------------------------------------------------------*/
1341 1558
1342static struct usb_gadget_driver composite_driver = { 1559static struct usb_gadget_driver composite_driver = {
1560#ifdef CONFIG_USB_GADGET_SUPERSPEED
1561 .speed = USB_SPEED_SUPER,
1562#else
1343 .speed = USB_SPEED_HIGH, 1563 .speed = USB_SPEED_HIGH,
1564#endif
1344 1565
1345 .unbind = composite_unbind, 1566 .unbind = composite_unbind,
1346 1567