Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: add isochronous support to gadget zero

Add two isochronous endpoints to the gadget zero source/sink
function. They are enabled by selecting alternate interface 1, so
by default they are not enabled. Module parameters for setting all
the isoc endpoint characteristics are also provided.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
Signed-off-by: Paul Zimmerman <paulz@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>

authored by

Paul Zimmerman and committed by
Felipe Balbi
b4036ccd 20c5e74c

+387 -65
+2 -2
drivers/usb/gadget/f_loopback.c
··· 286 286 struct usb_composite_dev *cdev; 287 287 288 288 cdev = loop->function.config->cdev; 289 - disable_endpoints(cdev, loop->in_ep, loop->out_ep); 289 + disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL); 290 290 VDBG(cdev, "%s disabled\n", loop->function.name); 291 291 } 292 292 ··· 329 329 * than 'buflen' bytes each. 330 330 */ 331 331 for (i = 0; i < qlen && result == 0; i++) { 332 - req = alloc_ep_req(ep); 332 + req = alloc_ep_req(ep, 0); 333 333 if (req) { 334 334 req->complete = loopback_complete; 335 335 result = usb_ep_queue(ep, req, GFP_ATOMIC);
+369 -55
drivers/usb/gadget/f_sourcesink.c
··· 51 51 52 52 struct usb_ep *in_ep; 53 53 struct usb_ep *out_ep; 54 + struct usb_ep *iso_in_ep; 55 + struct usb_ep *iso_out_ep; 56 + int cur_alt; 54 57 }; 55 58 56 59 static inline struct f_sourcesink *func_to_ss(struct usb_function *f) ··· 62 59 } 63 60 64 61 static unsigned pattern; 65 - module_param(pattern, uint, 0); 66 - MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); 62 + module_param(pattern, uint, S_IRUGO|S_IWUSR); 63 + MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63, 2 = none"); 64 + 65 + static unsigned isoc_interval = 4; 66 + module_param(isoc_interval, uint, S_IRUGO|S_IWUSR); 67 + MODULE_PARM_DESC(isoc_interval, "1 - 16"); 68 + 69 + static unsigned isoc_maxpacket = 1024; 70 + module_param(isoc_maxpacket, uint, S_IRUGO|S_IWUSR); 71 + MODULE_PARM_DESC(isoc_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); 72 + 73 + static unsigned isoc_mult; 74 + module_param(isoc_mult, uint, S_IRUGO|S_IWUSR); 75 + MODULE_PARM_DESC(isoc_mult, "0 - 2 (hs/ss only)"); 76 + 77 + static unsigned isoc_maxburst; 78 + module_param(isoc_maxburst, uint, S_IRUGO|S_IWUSR); 79 + MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)"); 67 80 68 81 /*-------------------------------------------------------------------------*/ 69 82 70 - static struct usb_interface_descriptor source_sink_intf = { 71 - .bLength = sizeof source_sink_intf, 83 + static struct usb_interface_descriptor source_sink_intf_alt0 = { 84 + .bLength = USB_DT_INTERFACE_SIZE, 72 85 .bDescriptorType = USB_DT_INTERFACE, 73 86 87 + .bAlternateSetting = 0, 74 88 .bNumEndpoints = 2, 75 89 .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 76 - /* .iInterface = DYNAMIC */ 90 + /* .iInterface = DYNAMIC */ 91 + }; 92 + 93 + static struct usb_interface_descriptor source_sink_intf_alt1 = { 94 + .bLength = USB_DT_INTERFACE_SIZE, 95 + .bDescriptorType = USB_DT_INTERFACE, 96 + 97 + .bAlternateSetting = 1, 98 + .bNumEndpoints = 4, 99 + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, 100 + /* .iInterface = DYNAMIC */ 77 101 }; 78 102 79 103 /* full speed support: */ ··· 121 91 .bmAttributes = USB_ENDPOINT_XFER_BULK, 122 92 }; 123 93 94 + static struct usb_endpoint_descriptor fs_iso_source_desc = { 95 + .bLength = USB_DT_ENDPOINT_SIZE, 96 + .bDescriptorType = USB_DT_ENDPOINT, 97 + 98 + .bEndpointAddress = USB_DIR_IN, 99 + .bmAttributes = USB_ENDPOINT_XFER_ISOC, 100 + .wMaxPacketSize = cpu_to_le16(1023), 101 + .bInterval = 4, 102 + }; 103 + 104 + static struct usb_endpoint_descriptor fs_iso_sink_desc = { 105 + .bLength = USB_DT_ENDPOINT_SIZE, 106 + .bDescriptorType = USB_DT_ENDPOINT, 107 + 108 + .bEndpointAddress = USB_DIR_OUT, 109 + .bmAttributes = USB_ENDPOINT_XFER_ISOC, 110 + .wMaxPacketSize = cpu_to_le16(1023), 111 + .bInterval = 4, 112 + }; 113 + 124 114 static struct usb_descriptor_header *fs_source_sink_descs[] = { 125 - (struct usb_descriptor_header *) &source_sink_intf, 115 + (struct usb_descriptor_header *) &source_sink_intf_alt0, 126 116 (struct usb_descriptor_header *) &fs_sink_desc, 127 117 (struct usb_descriptor_header *) &fs_source_desc, 118 + (struct usb_descriptor_header *) &source_sink_intf_alt1, 119 + #define FS_ALT_IFC_1_OFFSET 3 120 + (struct usb_descriptor_header *) &fs_sink_desc, 121 + (struct usb_descriptor_header *) &fs_source_desc, 122 + (struct usb_descriptor_header *) &fs_iso_sink_desc, 123 + (struct usb_descriptor_header *) &fs_iso_source_desc, 128 124 NULL, 129 125 }; 130 126 ··· 172 116 .wMaxPacketSize = cpu_to_le16(512), 173 117 }; 174 118 119 + static struct usb_endpoint_descriptor hs_iso_source_desc = { 120 + .bLength = USB_DT_ENDPOINT_SIZE, 121 + .bDescriptorType = USB_DT_ENDPOINT, 122 + 123 + .bmAttributes = USB_ENDPOINT_XFER_ISOC, 124 + .wMaxPacketSize = cpu_to_le16(1024), 125 + .bInterval = 4, 126 + }; 127 + 128 + static struct usb_endpoint_descriptor hs_iso_sink_desc = { 129 + .bLength = USB_DT_ENDPOINT_SIZE, 130 + .bDescriptorType = USB_DT_ENDPOINT, 131 + 132 + .bmAttributes = USB_ENDPOINT_XFER_ISOC, 133 + .wMaxPacketSize = cpu_to_le16(1024), 134 + .bInterval = 4, 135 + }; 136 + 175 137 static struct usb_descriptor_header *hs_source_sink_descs[] = { 176 - (struct usb_descriptor_header *) &source_sink_intf, 138 + (struct usb_descriptor_header *) &source_sink_intf_alt0, 177 139 (struct usb_descriptor_header *) &hs_source_desc, 178 140 (struct usb_descriptor_header *) &hs_sink_desc, 141 + (struct usb_descriptor_header *) &source_sink_intf_alt1, 142 + #define HS_ALT_IFC_1_OFFSET 3 143 + (struct usb_descriptor_header *) &hs_source_desc, 144 + (struct usb_descriptor_header *) &hs_sink_desc, 145 + (struct usb_descriptor_header *) &hs_iso_source_desc, 146 + (struct usb_descriptor_header *) &hs_iso_sink_desc, 179 147 NULL, 180 148 }; 181 149 ··· 216 136 struct usb_ss_ep_comp_descriptor ss_source_comp_desc = { 217 137 .bLength = USB_DT_SS_EP_COMP_SIZE, 218 138 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 139 + 219 140 .bMaxBurst = 0, 220 141 .bmAttributes = 0, 221 142 .wBytesPerInterval = 0, ··· 233 152 struct usb_ss_ep_comp_descriptor ss_sink_comp_desc = { 234 153 .bLength = USB_DT_SS_EP_COMP_SIZE, 235 154 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 155 + 236 156 .bMaxBurst = 0, 237 157 .bmAttributes = 0, 238 158 .wBytesPerInterval = 0, 239 159 }; 240 160 161 + static struct usb_endpoint_descriptor ss_iso_source_desc = { 162 + .bLength = USB_DT_ENDPOINT_SIZE, 163 + .bDescriptorType = USB_DT_ENDPOINT, 164 + 165 + .bmAttributes = USB_ENDPOINT_XFER_ISOC, 166 + .wMaxPacketSize = cpu_to_le16(1024), 167 + .bInterval = 4, 168 + }; 169 + 170 + struct usb_ss_ep_comp_descriptor ss_iso_source_comp_desc = { 171 + .bLength = USB_DT_SS_EP_COMP_SIZE, 172 + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 173 + 174 + .bMaxBurst = 0, 175 + .bmAttributes = 0, 176 + .wBytesPerInterval = cpu_to_le16(1024), 177 + }; 178 + 179 + static struct usb_endpoint_descriptor ss_iso_sink_desc = { 180 + .bLength = USB_DT_ENDPOINT_SIZE, 181 + .bDescriptorType = USB_DT_ENDPOINT, 182 + 183 + .bmAttributes = USB_ENDPOINT_XFER_ISOC, 184 + .wMaxPacketSize = cpu_to_le16(1024), 185 + .bInterval = 4, 186 + }; 187 + 188 + struct usb_ss_ep_comp_descriptor ss_iso_sink_comp_desc = { 189 + .bLength = USB_DT_SS_EP_COMP_SIZE, 190 + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 191 + 192 + .bMaxBurst = 0, 193 + .bmAttributes = 0, 194 + .wBytesPerInterval = cpu_to_le16(1024), 195 + }; 196 + 241 197 static struct usb_descriptor_header *ss_source_sink_descs[] = { 242 - (struct usb_descriptor_header *) &source_sink_intf, 198 + (struct usb_descriptor_header *) &source_sink_intf_alt0, 243 199 (struct usb_descriptor_header *) &ss_source_desc, 244 200 (struct usb_descriptor_header *) &ss_source_comp_desc, 245 201 (struct usb_descriptor_header *) &ss_sink_desc, 246 202 (struct usb_descriptor_header *) &ss_sink_comp_desc, 203 + (struct usb_descriptor_header *) &source_sink_intf_alt1, 204 + #define SS_ALT_IFC_1_OFFSET 5 205 + (struct usb_descriptor_header *) &ss_source_desc, 206 + (struct usb_descriptor_header *) &ss_source_comp_desc, 207 + (struct usb_descriptor_header *) &ss_sink_desc, 208 + (struct usb_descriptor_header *) &ss_sink_comp_desc, 209 + (struct usb_descriptor_header *) &ss_iso_source_desc, 210 + (struct usb_descriptor_header *) &ss_iso_source_comp_desc, 211 + (struct usb_descriptor_header *) &ss_iso_sink_desc, 212 + (struct usb_descriptor_header *) &ss_iso_sink_comp_desc, 247 213 NULL, 248 214 }; 249 215 ··· 324 196 id = usb_interface_id(c, f); 325 197 if (id < 0) 326 198 return id; 327 - source_sink_intf.bInterfaceNumber = id; 199 + source_sink_intf_alt0.bInterfaceNumber = id; 200 + source_sink_intf_alt1.bInterfaceNumber = id; 328 201 329 - /* allocate endpoints */ 202 + /* allocate bulk endpoints */ 330 203 ss->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_source_desc); 331 204 if (!ss->in_ep) { 332 205 autoconf_fail: ··· 342 213 goto autoconf_fail; 343 214 ss->out_ep->driver_data = cdev; /* claim */ 344 215 216 + /* sanity check the isoc module parameters */ 217 + if (isoc_interval < 1) 218 + isoc_interval = 1; 219 + if (isoc_interval > 16) 220 + isoc_interval = 16; 221 + if (isoc_mult > 2) 222 + isoc_mult = 2; 223 + if (isoc_maxburst > 15) 224 + isoc_maxburst = 15; 225 + 226 + /* fill in the FS isoc descriptors from the module parameters */ 227 + fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ? 228 + 1023 : isoc_maxpacket; 229 + fs_iso_source_desc.bInterval = isoc_interval; 230 + fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ? 231 + 1023 : isoc_maxpacket; 232 + fs_iso_sink_desc.bInterval = isoc_interval; 233 + 234 + /* allocate iso endpoints */ 235 + ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc); 236 + if (!ss->iso_in_ep) 237 + goto no_iso; 238 + ss->iso_in_ep->driver_data = cdev; /* claim */ 239 + 240 + ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc); 241 + if (ss->iso_out_ep) { 242 + ss->iso_out_ep->driver_data = cdev; /* claim */ 243 + } else { 244 + ss->iso_in_ep->driver_data = NULL; 245 + ss->iso_in_ep = NULL; 246 + no_iso: 247 + /* 248 + * We still want to work even if the UDC doesn't have isoc 249 + * endpoints, so null out the alt interface that contains 250 + * them and continue. 251 + */ 252 + fs_source_sink_descs[FS_ALT_IFC_1_OFFSET] = NULL; 253 + hs_source_sink_descs[HS_ALT_IFC_1_OFFSET] = NULL; 254 + ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL; 255 + } 256 + 257 + if (isoc_maxpacket > 1024) 258 + isoc_maxpacket = 1024; 259 + 345 260 /* support high speed hardware */ 346 261 if (gadget_is_dualspeed(c->cdev->gadget)) { 347 262 hs_source_desc.bEndpointAddress = 348 263 fs_source_desc.bEndpointAddress; 349 264 hs_sink_desc.bEndpointAddress = 350 265 fs_sink_desc.bEndpointAddress; 266 + 267 + /* 268 + * Fill in the HS isoc descriptors from the module parameters. 269 + * We assume that the user knows what they are doing and won't 270 + * give parameters that their UDC doesn't support. 271 + */ 272 + hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket; 273 + hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11; 274 + hs_iso_source_desc.bInterval = isoc_interval; 275 + hs_iso_source_desc.bEndpointAddress = 276 + fs_iso_source_desc.bEndpointAddress; 277 + 278 + hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; 279 + hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11; 280 + hs_iso_sink_desc.bInterval = isoc_interval; 281 + hs_iso_sink_desc.bEndpointAddress = 282 + fs_iso_sink_desc.bEndpointAddress; 283 + 351 284 f->hs_descriptors = hs_source_sink_descs; 352 285 } 353 286 ··· 419 228 fs_source_desc.bEndpointAddress; 420 229 ss_sink_desc.bEndpointAddress = 421 230 fs_sink_desc.bEndpointAddress; 231 + 232 + /* 233 + * Fill in the SS isoc descriptors from the module parameters. 234 + * We assume that the user knows what they are doing and won't 235 + * give parameters that their UDC doesn't support. 236 + */ 237 + ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket; 238 + ss_iso_source_desc.bInterval = isoc_interval; 239 + ss_iso_source_comp_desc.bmAttributes = isoc_mult; 240 + ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst; 241 + ss_iso_source_comp_desc.wBytesPerInterval = 242 + isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); 243 + ss_iso_source_desc.bEndpointAddress = 244 + fs_iso_source_desc.bEndpointAddress; 245 + 246 + ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; 247 + ss_iso_sink_desc.bInterval = isoc_interval; 248 + ss_iso_sink_comp_desc.bmAttributes = isoc_mult; 249 + ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst; 250 + ss_iso_sink_comp_desc.wBytesPerInterval = 251 + isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); 252 + ss_iso_sink_desc.bEndpointAddress = 253 + fs_iso_sink_desc.bEndpointAddress; 254 + 422 255 f->ss_descriptors = ss_source_sink_descs; 423 256 } 424 257 425 - DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", 258 + DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n", 426 259 (gadget_is_superspeed(c->cdev->gadget) ? "super" : 427 260 (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")), 428 - f->name, ss->in_ep->name, ss->out_ep->name); 261 + f->name, ss->in_ep->name, ss->out_ep->name, 262 + ss->iso_in_ep ? ss->iso_in_ep->name : "<none>", 263 + ss->iso_out_ep ? ss->iso_out_ep->name : "<none>"); 429 264 return 0; 430 265 } 431 266 ··· 468 251 u8 *buf = req->buf; 469 252 struct usb_composite_dev *cdev = ss->function.config->cdev; 470 253 254 + if (pattern == 2) 255 + return 0; 256 + 471 257 for (i = 0; i < req->actual; i++, buf++) { 472 258 switch (pattern) { 473 259 ··· 485 265 * each usb transfer request should be. Resync is done 486 266 * with set_interface or set_config. (We *WANT* it to 487 267 * get quickly out of sync if controllers or their drivers 488 - * stutter for any reason, including buffer duplcation...) 268 + * stutter for any reason, including buffer duplication...) 489 269 */ 490 270 case 1: 491 271 if (*buf == (u8)(i % 63)) ··· 512 292 for (i = 0; i < req->length; i++) 513 293 *buf++ = (u8) (i % 63); 514 294 break; 295 + case 2: 296 + break; 515 297 } 516 298 } 517 299 518 300 static void source_sink_complete(struct usb_ep *ep, struct usb_request *req) 519 301 { 520 - struct f_sourcesink *ss = ep->driver_data; 521 - struct usb_composite_dev *cdev = ss->function.config->cdev; 522 - int status = req->status; 302 + struct usb_composite_dev *cdev; 303 + struct f_sourcesink *ss = ep->driver_data; 304 + int status = req->status; 305 + 306 + /* driver_data will be null if ep has been disabled */ 307 + if (!ss) 308 + return; 309 + 310 + cdev = ss->function.config->cdev; 523 311 524 312 switch (status) { 525 313 526 314 case 0: /* normal completion? */ 527 315 if (ep == ss->out_ep) { 528 316 check_read_data(ss, req); 529 - memset(req->buf, 0x55, req->length); 317 + if (pattern != 2) 318 + memset(req->buf, 0x55, req->length); 530 319 } else 531 320 reinit_write_data(ep, req); 532 321 break; ··· 573 344 } 574 345 } 575 346 576 - static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in) 347 + static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in, 348 + bool is_iso, int speed) 577 349 { 578 350 struct usb_ep *ep; 579 351 struct usb_request *req; 580 - int status; 352 + int i, size, status; 581 353 582 - ep = is_in ? ss->in_ep : ss->out_ep; 583 - req = alloc_ep_req(ep); 584 - if (!req) 585 - return -ENOMEM; 354 + for (i = 0; i < 8; i++) { 355 + if (is_iso) { 356 + switch (speed) { 357 + case USB_SPEED_SUPER: 358 + size = isoc_maxpacket * (isoc_mult + 1) * 359 + (isoc_maxburst + 1); 360 + break; 361 + case USB_SPEED_HIGH: 362 + size = isoc_maxpacket * (isoc_mult + 1); 363 + break; 364 + default: 365 + size = isoc_maxpacket > 1023 ? 366 + 1023 : isoc_maxpacket; 367 + break; 368 + } 369 + ep = is_in ? ss->iso_in_ep : ss->iso_out_ep; 370 + req = alloc_ep_req(ep, size); 371 + } else { 372 + ep = is_in ? ss->in_ep : ss->out_ep; 373 + req = alloc_ep_req(ep, 0); 374 + } 586 375 587 - req->complete = source_sink_complete; 588 - if (is_in) 589 - reinit_write_data(ep, req); 590 - else 591 - memset(req->buf, 0x55, req->length); 376 + if (!req) 377 + return -ENOMEM; 592 378 593 - status = usb_ep_queue(ep, req, GFP_ATOMIC); 594 - if (status) { 595 - struct usb_composite_dev *cdev; 379 + req->complete = source_sink_complete; 380 + if (is_in) 381 + reinit_write_data(ep, req); 382 + else if (pattern != 2) 383 + memset(req->buf, 0x55, req->length); 596 384 597 - cdev = ss->function.config->cdev; 598 - ERROR(cdev, "start %s %s --> %d\n", 599 - is_in ? "IN" : "OUT", 600 - ep->name, status); 601 - free_ep_req(ep, req); 385 + status = usb_ep_queue(ep, req, GFP_ATOMIC); 386 + if (status) { 387 + struct usb_composite_dev *cdev; 388 + 389 + cdev = ss->function.config->cdev; 390 + ERROR(cdev, "start %s%s %s --> %d\n", 391 + is_iso ? "ISO-" : "", is_in ? "IN" : "OUT", 392 + ep->name, status); 393 + free_ep_req(ep, req); 394 + } 395 + 396 + if (!is_iso) 397 + break; 602 398 } 603 399 604 400 return status; ··· 634 380 struct usb_composite_dev *cdev; 635 381 636 382 cdev = ss->function.config->cdev; 637 - disable_endpoints(cdev, ss->in_ep, ss->out_ep); 383 + disable_endpoints(cdev, ss->in_ep, ss->out_ep, ss->iso_in_ep, 384 + ss->iso_out_ep); 638 385 VDBG(cdev, "%s disabled\n", ss->function.name); 639 386 } 640 387 641 388 static int 642 - enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) 389 + enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss, 390 + int alt) 643 391 { 644 392 int result = 0; 393 + int speed = cdev->gadget->speed; 645 394 struct usb_ep *ep; 646 395 647 - /* one endpoint writes (sources) zeroes IN (to the host) */ 396 + /* one bulk endpoint writes (sources) zeroes IN (to the host) */ 648 397 ep = ss->in_ep; 649 398 result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); 650 399 if (result) ··· 657 400 return result; 658 401 ep->driver_data = ss; 659 402 660 - result = source_sink_start_ep(ss, true); 403 + result = source_sink_start_ep(ss, true, false, speed); 661 404 if (result < 0) { 662 405 fail: 663 406 ep = ss->in_ep; ··· 666 409 return result; 667 410 } 668 411 669 - /* one endpoint reads (sinks) anything OUT (from the host) */ 412 + /* one bulk endpoint reads (sinks) anything OUT (from the host) */ 670 413 ep = ss->out_ep; 671 414 result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); 672 415 if (result) ··· 676 419 goto fail; 677 420 ep->driver_data = ss; 678 421 679 - result = source_sink_start_ep(ss, false); 422 + result = source_sink_start_ep(ss, false, false, speed); 680 423 if (result < 0) { 424 + fail2: 425 + ep = ss->out_ep; 681 426 usb_ep_disable(ep); 682 427 ep->driver_data = NULL; 683 428 goto fail; 684 429 } 685 430 686 - DBG(cdev, "%s enabled\n", ss->function.name); 431 + if (alt == 0) 432 + goto out; 433 + 434 + /* one iso endpoint writes (sources) zeroes IN (to the host) */ 435 + ep = ss->iso_in_ep; 436 + if (ep) { 437 + result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); 438 + if (result) 439 + goto fail2; 440 + result = usb_ep_enable(ep); 441 + if (result < 0) 442 + goto fail2; 443 + ep->driver_data = ss; 444 + 445 + result = source_sink_start_ep(ss, true, true, speed); 446 + if (result < 0) { 447 + fail3: 448 + ep = ss->iso_in_ep; 449 + if (ep) { 450 + usb_ep_disable(ep); 451 + ep->driver_data = NULL; 452 + } 453 + goto fail2; 454 + } 455 + } 456 + 457 + /* one iso endpoint reads (sinks) anything OUT (from the host) */ 458 + ep = ss->iso_out_ep; 459 + if (ep) { 460 + result = config_ep_by_speed(cdev->gadget, &(ss->function), ep); 461 + if (result) 462 + goto fail3; 463 + result = usb_ep_enable(ep); 464 + if (result < 0) 465 + goto fail3; 466 + ep->driver_data = ss; 467 + 468 + result = source_sink_start_ep(ss, false, true, speed); 469 + if (result < 0) { 470 + usb_ep_disable(ep); 471 + ep->driver_data = NULL; 472 + goto fail3; 473 + } 474 + } 475 + out: 476 + ss->cur_alt = alt; 477 + 478 + DBG(cdev, "%s enabled, alt intf %d\n", ss->function.name, alt); 687 479 return result; 688 480 } 689 481 690 482 static int sourcesink_set_alt(struct usb_function *f, 691 483 unsigned intf, unsigned alt) 692 484 { 693 - struct f_sourcesink *ss = func_to_ss(f); 694 - struct usb_composite_dev *cdev = f->config->cdev; 485 + struct f_sourcesink *ss = func_to_ss(f); 486 + struct usb_composite_dev *cdev = f->config->cdev; 695 487 696 - /* we know alt is zero */ 697 488 if (ss->in_ep->driver_data) 698 489 disable_source_sink(ss); 699 - return enable_source_sink(cdev, ss); 490 + return enable_source_sink(cdev, ss, alt); 491 + } 492 + 493 + static int sourcesink_get_alt(struct usb_function *f, unsigned intf) 494 + { 495 + struct f_sourcesink *ss = func_to_ss(f); 496 + 497 + return ss->cur_alt; 700 498 } 701 499 702 500 static void sourcesink_disable(struct usb_function *f) ··· 777 465 ss->function.bind = sourcesink_bind; 778 466 ss->function.unbind = sourcesink_unbind; 779 467 ss->function.set_alt = sourcesink_set_alt; 468 + ss->function.get_alt = sourcesink_get_alt; 780 469 ss->function.disable = sourcesink_disable; 781 470 782 471 status = usb_add_function(c, &ss->function); ··· 849 536 req->length = value; 850 537 value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); 851 538 if (value < 0) 852 - ERROR(c->cdev, "source/sinkc response, err %d\n", 539 + ERROR(c->cdev, "source/sink response, err %d\n", 853 540 value); 854 541 } 855 542 ··· 858 545 } 859 546 860 547 static struct usb_configuration sourcesink_driver = { 861 - .label = "source/sink", 862 - .strings = sourcesink_strings, 863 - .setup = sourcesink_setup, 864 - .bConfigurationValue = 3, 865 - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 866 - /* .iConfiguration = DYNAMIC */ 548 + .label = "source/sink", 549 + .strings = sourcesink_strings, 550 + .setup = sourcesink_setup, 551 + .bConfigurationValue = 3, 552 + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, 553 + /* .iConfiguration = DYNAMIC */ 867 554 }; 868 555 869 556 /** ··· 880 567 return id; 881 568 strings_sourcesink[0].id = id; 882 569 883 - source_sink_intf.iInterface = id; 570 + source_sink_intf_alt0.iInterface = id; 571 + source_sink_intf_alt1.iInterface = id; 884 572 sourcesink_driver.iConfiguration = id; 885 573 886 574 /* support autoresume for remote wakeup testing */
+3 -2
drivers/usb/gadget/g_zero.h
··· 13 13 extern const struct usb_descriptor_header *otg_desc[]; 14 14 15 15 /* common utilities */ 16 - struct usb_request *alloc_ep_req(struct usb_ep *ep); 16 + struct usb_request *alloc_ep_req(struct usb_ep *ep, int len); 17 17 void free_ep_req(struct usb_ep *ep, struct usb_request *req); 18 18 void disable_endpoints(struct usb_composite_dev *cdev, 19 - struct usb_ep *in, struct usb_ep *out); 19 + struct usb_ep *in, struct usb_ep *out, 20 + struct usb_ep *iso_in, struct usb_ep *iso_out); 20 21 21 22 /* configuration-specific linkup */ 22 23 int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume);
+13 -6
drivers/usb/gadget/zero.c
··· 72 72 73 73 static const char longname[] = "Gadget Zero"; 74 74 75 - unsigned buflen = 4096; 75 + unsigned buflen = 4096; /* only used for bulk endpoints */ 76 76 module_param(buflen, uint, 0); 77 77 78 78 /* ··· 170 170 171 171 /*-------------------------------------------------------------------------*/ 172 172 173 - struct usb_request *alloc_ep_req(struct usb_ep *ep) 173 + struct usb_request *alloc_ep_req(struct usb_ep *ep, int len) 174 174 { 175 175 struct usb_request *req; 176 176 177 177 req = usb_ep_alloc_request(ep, GFP_ATOMIC); 178 178 if (req) { 179 - req->length = buflen; 180 - req->buf = kmalloc(buflen, GFP_ATOMIC); 179 + if (len) 180 + req->length = len; 181 + else 182 + req->length = buflen; 183 + req->buf = kmalloc(req->length, GFP_ATOMIC); 181 184 if (!req->buf) { 182 185 usb_ep_free_request(ep, req); 183 186 req = NULL; ··· 209 206 } 210 207 211 208 void disable_endpoints(struct usb_composite_dev *cdev, 212 - struct usb_ep *in, struct usb_ep *out) 209 + struct usb_ep *in, struct usb_ep *out, 210 + struct usb_ep *iso_in, struct usb_ep *iso_out) 213 211 { 214 212 disable_ep(cdev, in); 215 213 disable_ep(cdev, out); 214 + if (iso_in) 215 + disable_ep(cdev, iso_in); 216 + if (iso_out) 217 + disable_ep(cdev, iso_out); 216 218 } 217 219 218 220 /*-------------------------------------------------------------------------*/ ··· 318 310 longname, gadget->name); 319 311 device_desc.bcdDevice = cpu_to_le16(0x9999); 320 312 } 321 - 322 313 323 314 INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); 324 315