diff options
Diffstat (limited to 'drivers/usb/gadget/f_uvc.c')
-rw-r--r-- | drivers/usb/gadget/f_uvc.c | 262 |
1 files changed, 129 insertions, 133 deletions
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 92efd6ec48af..38dcedddc52c 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c | |||
@@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param; | |||
33 | /*-------------------------------------------------------------------------*/ | 33 | /*-------------------------------------------------------------------------*/ |
34 | 34 | ||
35 | /* module parameters specific to the Video streaming endpoint */ | 35 | /* module parameters specific to the Video streaming endpoint */ |
36 | static unsigned streaming_interval = 1; | 36 | static unsigned int streaming_interval = 1; |
37 | module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); | 37 | module_param(streaming_interval, uint, S_IRUGO|S_IWUSR); |
38 | MODULE_PARM_DESC(streaming_interval, "1 - 16"); | 38 | MODULE_PARM_DESC(streaming_interval, "1 - 16"); |
39 | 39 | ||
40 | static unsigned streaming_maxpacket = 1024; | 40 | static unsigned int streaming_maxpacket = 1024; |
41 | module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); | 41 | module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR); |
42 | MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)"); | 42 | MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)"); |
43 | 43 | ||
44 | static unsigned streaming_mult; | 44 | static unsigned int streaming_maxburst; |
45 | module_param(streaming_mult, uint, S_IRUGO|S_IWUSR); | ||
46 | MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)"); | ||
47 | |||
48 | static unsigned streaming_maxburst; | ||
49 | module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); | 45 | module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR); |
50 | MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); | 46 | MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); |
51 | 47 | ||
@@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)"); | |||
55 | 51 | ||
56 | /* string IDs are assigned dynamically */ | 52 | /* string IDs are assigned dynamically */ |
57 | 53 | ||
58 | #define UVC_STRING_ASSOCIATION_IDX 0 | 54 | #define UVC_STRING_CONTROL_IDX 0 |
59 | #define UVC_STRING_CONTROL_IDX 1 | 55 | #define UVC_STRING_STREAMING_IDX 1 |
60 | #define UVC_STRING_STREAMING_IDX 2 | ||
61 | 56 | ||
62 | static struct usb_string uvc_en_us_strings[] = { | 57 | static struct usb_string uvc_en_us_strings[] = { |
63 | [UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera", | 58 | [UVC_STRING_CONTROL_IDX].s = "UVC Camera", |
64 | [UVC_STRING_CONTROL_IDX].s = "Video Control", | ||
65 | [UVC_STRING_STREAMING_IDX].s = "Video Streaming", | 59 | [UVC_STRING_STREAMING_IDX].s = "Video Streaming", |
66 | { } | 60 | { } |
67 | }; | 61 | }; |
@@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = { | |||
79 | #define UVC_INTF_VIDEO_CONTROL 0 | 73 | #define UVC_INTF_VIDEO_CONTROL 0 |
80 | #define UVC_INTF_VIDEO_STREAMING 1 | 74 | #define UVC_INTF_VIDEO_STREAMING 1 |
81 | 75 | ||
82 | #define STATUS_BYTECOUNT 16 /* 16 bytes status */ | 76 | #define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */ |
83 | 77 | ||
84 | static struct usb_interface_assoc_descriptor uvc_iad __initdata = { | 78 | static struct usb_interface_assoc_descriptor uvc_iad __initdata = { |
85 | .bLength = sizeof(uvc_iad), | 79 | .bLength = sizeof(uvc_iad), |
@@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { | |||
104 | .iInterface = 0, | 98 | .iInterface = 0, |
105 | }; | 99 | }; |
106 | 100 | ||
107 | static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = { | 101 | static struct usb_endpoint_descriptor uvc_control_ep __initdata = { |
108 | .bLength = USB_DT_ENDPOINT_SIZE, | 102 | .bLength = USB_DT_ENDPOINT_SIZE, |
109 | .bDescriptorType = USB_DT_ENDPOINT, | 103 | .bDescriptorType = USB_DT_ENDPOINT, |
110 | .bEndpointAddress = USB_DIR_IN, | 104 | .bEndpointAddress = USB_DIR_IN, |
111 | .bmAttributes = USB_ENDPOINT_XFER_INT, | 105 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
112 | .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), | 106 | .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
113 | .bInterval = 8, | 107 | .bInterval = 8, |
114 | }; | 108 | }; |
115 | 109 | ||
110 | static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { | ||
111 | .bLength = sizeof(uvc_ss_control_comp), | ||
112 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
113 | /* The following 3 values can be tweaked if necessary. */ | ||
114 | .bMaxBurst = 0, | ||
115 | .bmAttributes = 0, | ||
116 | .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), | ||
117 | }; | ||
118 | |||
116 | static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { | 119 | static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = { |
117 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, | 120 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, |
118 | .bDescriptorType = USB_DT_CS_ENDPOINT, | 121 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
119 | .bDescriptorSubType = UVC_EP_INTERRUPT, | 122 | .bDescriptorSubType = UVC_EP_INTERRUPT, |
120 | .wMaxTransferSize = cpu_to_le16(STATUS_BYTECOUNT), | 123 | .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
121 | }; | 124 | }; |
122 | 125 | ||
123 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { | 126 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { |
@@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { | |||
144 | .iInterface = 0, | 147 | .iInterface = 0, |
145 | }; | 148 | }; |
146 | 149 | ||
147 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { | 150 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { |
148 | .bLength = USB_DT_ENDPOINT_SIZE, | 151 | .bLength = USB_DT_ENDPOINT_SIZE, |
149 | .bDescriptorType = USB_DT_ENDPOINT, | 152 | .bDescriptorType = USB_DT_ENDPOINT, |
150 | .bEndpointAddress = USB_DIR_IN, | 153 | .bEndpointAddress = USB_DIR_IN, |
151 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, | 154 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
152 | .wMaxPacketSize = cpu_to_le16(512), | 155 | | USB_ENDPOINT_XFER_ISOC, |
153 | .bInterval = 1, | 156 | /* The wMaxPacketSize and bInterval values will be initialized from |
157 | * module parameters. | ||
158 | */ | ||
159 | .wMaxPacketSize = 0, | ||
160 | .bInterval = 0, | ||
154 | }; | 161 | }; |
155 | 162 | ||
156 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { | 163 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { |
157 | .bLength = USB_DT_ENDPOINT_SIZE, | 164 | .bLength = USB_DT_ENDPOINT_SIZE, |
158 | .bDescriptorType = USB_DT_ENDPOINT, | 165 | .bDescriptorType = USB_DT_ENDPOINT, |
159 | .bEndpointAddress = USB_DIR_IN, | 166 | .bEndpointAddress = USB_DIR_IN, |
160 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, | 167 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
161 | .wMaxPacketSize = cpu_to_le16(1024), | 168 | | USB_ENDPOINT_XFER_ISOC, |
162 | .bInterval = 1, | 169 | /* The wMaxPacketSize and bInterval values will be initialized from |
163 | }; | 170 | * module parameters. |
164 | 171 | */ | |
165 | /* super speed support */ | 172 | .wMaxPacketSize = 0, |
166 | static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = { | 173 | .bInterval = 0, |
167 | .bLength = USB_DT_ENDPOINT_SIZE, | ||
168 | .bDescriptorType = USB_DT_ENDPOINT, | ||
169 | |||
170 | .bEndpointAddress = USB_DIR_IN, | ||
171 | .bmAttributes = USB_ENDPOINT_XFER_INT, | ||
172 | .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), | ||
173 | .bInterval = 8, | ||
174 | }; | ||
175 | |||
176 | static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = { | ||
177 | .bLength = sizeof uvc_ss_control_comp, | ||
178 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | ||
179 | |||
180 | /* the following 3 values can be tweaked if necessary */ | ||
181 | /* .bMaxBurst = 0, */ | ||
182 | /* .bmAttributes = 0, */ | ||
183 | .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT), | ||
184 | }; | 174 | }; |
185 | 175 | ||
186 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { | 176 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { |
187 | .bLength = USB_DT_ENDPOINT_SIZE, | 177 | .bLength = USB_DT_ENDPOINT_SIZE, |
188 | .bDescriptorType = USB_DT_ENDPOINT, | 178 | .bDescriptorType = USB_DT_ENDPOINT, |
189 | 179 | ||
190 | .bEndpointAddress = USB_DIR_IN, | 180 | .bEndpointAddress = USB_DIR_IN, |
191 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, | 181 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
192 | .wMaxPacketSize = cpu_to_le16(1024), | 182 | | USB_ENDPOINT_XFER_ISOC, |
193 | .bInterval = 4, | 183 | /* The wMaxPacketSize and bInterval values will be initialized from |
184 | * module parameters. | ||
185 | */ | ||
186 | .wMaxPacketSize = 0, | ||
187 | .bInterval = 0, | ||
194 | }; | 188 | }; |
195 | 189 | ||
196 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { | 190 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { |
197 | .bLength = sizeof uvc_ss_streaming_comp, | 191 | .bLength = sizeof(uvc_ss_streaming_comp), |
198 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 192 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
199 | 193 | /* The following 3 values can be tweaked if necessary. */ | |
200 | /* the following 3 values can be tweaked if necessary */ | 194 | .bMaxBurst = 0, |
201 | .bMaxBurst = 0, | 195 | .bmAttributes = 0, |
202 | .bmAttributes = 0, | 196 | .wBytesPerInterval = cpu_to_le16(1024), |
203 | .wBytesPerInterval = cpu_to_le16(1024), | ||
204 | }; | 197 | }; |
205 | 198 | ||
206 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { | 199 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { |
@@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) | |||
273 | return 0; | 266 | return 0; |
274 | } | 267 | } |
275 | 268 | ||
269 | void uvc_function_setup_continue(struct uvc_device *uvc) | ||
270 | { | ||
271 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | ||
272 | |||
273 | usb_composite_setup_continue(cdev); | ||
274 | } | ||
275 | |||
276 | static int | 276 | static int |
277 | uvc_function_get_alt(struct usb_function *f, unsigned interface) | 277 | uvc_function_get_alt(struct usb_function *f, unsigned interface) |
278 | { | 278 | { |
@@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) | |||
335 | v4l2_event_queue(uvc->vdev, &v4l2_event); | 335 | v4l2_event_queue(uvc->vdev, &v4l2_event); |
336 | 336 | ||
337 | uvc->state = UVC_STATE_CONNECTED; | 337 | uvc->state = UVC_STATE_CONNECTED; |
338 | break; | 338 | return 0; |
339 | 339 | ||
340 | case 1: | 340 | case 1: |
341 | if (uvc->state != UVC_STATE_CONNECTED) | 341 | if (uvc->state != UVC_STATE_CONNECTED) |
@@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) | |||
352 | memset(&v4l2_event, 0, sizeof(v4l2_event)); | 352 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
353 | v4l2_event.type = UVC_EVENT_STREAMON; | 353 | v4l2_event.type = UVC_EVENT_STREAMON; |
354 | v4l2_event_queue(uvc->vdev, &v4l2_event); | 354 | v4l2_event_queue(uvc->vdev, &v4l2_event); |
355 | 355 | return USB_GADGET_DELAYED_STATUS; | |
356 | uvc->state = UVC_STATE_STREAMING; | ||
357 | break; | ||
358 | 356 | ||
359 | default: | 357 | default: |
360 | return -EINVAL; | 358 | return -EINVAL; |
361 | } | 359 | } |
362 | |||
363 | return 0; | ||
364 | } | 360 | } |
365 | 361 | ||
366 | static void | 362 | static void |
@@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
454 | const struct uvc_descriptor_header * const *uvc_streaming_cls; | 450 | const struct uvc_descriptor_header * const *uvc_streaming_cls; |
455 | const struct usb_descriptor_header * const *uvc_streaming_std; | 451 | const struct usb_descriptor_header * const *uvc_streaming_std; |
456 | const struct usb_descriptor_header * const *src; | 452 | const struct usb_descriptor_header * const *src; |
457 | static struct usb_endpoint_descriptor *uvc_control_ep; | ||
458 | struct usb_descriptor_header **dst; | 453 | struct usb_descriptor_header **dst; |
459 | struct usb_descriptor_header **hdr; | 454 | struct usb_descriptor_header **hdr; |
460 | unsigned int control_size; | 455 | unsigned int control_size; |
@@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
468 | uvc_control_desc = uvc->desc.ss_control; | 463 | uvc_control_desc = uvc->desc.ss_control; |
469 | uvc_streaming_cls = uvc->desc.ss_streaming; | 464 | uvc_streaming_cls = uvc->desc.ss_streaming; |
470 | uvc_streaming_std = uvc_ss_streaming; | 465 | uvc_streaming_std = uvc_ss_streaming; |
471 | uvc_control_ep = &uvc_ss_control_ep; | ||
472 | break; | 466 | break; |
473 | 467 | ||
474 | case USB_SPEED_HIGH: | 468 | case USB_SPEED_HIGH: |
475 | uvc_control_desc = uvc->desc.fs_control; | 469 | uvc_control_desc = uvc->desc.fs_control; |
476 | uvc_streaming_cls = uvc->desc.hs_streaming; | 470 | uvc_streaming_cls = uvc->desc.hs_streaming; |
477 | uvc_streaming_std = uvc_hs_streaming; | 471 | uvc_streaming_std = uvc_hs_streaming; |
478 | uvc_control_ep = &uvc_fs_control_ep; | ||
479 | break; | 472 | break; |
480 | 473 | ||
481 | case USB_SPEED_FULL: | 474 | case USB_SPEED_FULL: |
@@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
483 | uvc_control_desc = uvc->desc.fs_control; | 476 | uvc_control_desc = uvc->desc.fs_control; |
484 | uvc_streaming_cls = uvc->desc.fs_streaming; | 477 | uvc_streaming_cls = uvc->desc.fs_streaming; |
485 | uvc_streaming_std = uvc_fs_streaming; | 478 | uvc_streaming_std = uvc_fs_streaming; |
486 | uvc_control_ep = &uvc_fs_control_ep; | ||
487 | break; | 479 | break; |
488 | } | 480 | } |
489 | 481 | ||
@@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
494 | * Class-specific UVC control descriptors | 486 | * Class-specific UVC control descriptors |
495 | * uvc_control_ep | 487 | * uvc_control_ep |
496 | * uvc_control_cs_ep | 488 | * uvc_control_cs_ep |
489 | * uvc_ss_control_comp (for SS only) | ||
497 | * uvc_streaming_intf_alt0 | 490 | * uvc_streaming_intf_alt0 |
498 | * Class-specific UVC streaming descriptors | 491 | * Class-specific UVC streaming descriptors |
499 | * uvc_{fs|hs}_streaming | 492 | * uvc_{fs|hs}_streaming |
@@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
503 | control_size = 0; | 496 | control_size = 0; |
504 | streaming_size = 0; | 497 | streaming_size = 0; |
505 | bytes = uvc_iad.bLength + uvc_control_intf.bLength | 498 | bytes = uvc_iad.bLength + uvc_control_intf.bLength |
506 | + uvc_control_ep->bLength + uvc_control_cs_ep.bLength | 499 | + uvc_control_ep.bLength + uvc_control_cs_ep.bLength |
507 | + uvc_streaming_intf_alt0.bLength; | 500 | + uvc_streaming_intf_alt0.bLength; |
508 | 501 | ||
509 | if (speed == USB_SPEED_SUPER) { | 502 | if (speed == USB_SPEED_SUPER) { |
@@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
514 | } | 507 | } |
515 | 508 | ||
516 | for (src = (const struct usb_descriptor_header **)uvc_control_desc; | 509 | for (src = (const struct usb_descriptor_header **)uvc_control_desc; |
517 | *src; ++src) { | 510 | *src; ++src) { |
518 | control_size += (*src)->bLength; | 511 | control_size += (*src)->bLength; |
519 | bytes += (*src)->bLength; | 512 | bytes += (*src)->bLength; |
520 | n_desc++; | 513 | n_desc++; |
521 | } | 514 | } |
522 | for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; | 515 | for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; |
523 | *src; ++src) { | 516 | *src; ++src) { |
524 | streaming_size += (*src)->bLength; | 517 | streaming_size += (*src)->bLength; |
525 | bytes += (*src)->bLength; | 518 | bytes += (*src)->bLength; |
526 | n_desc++; | 519 | n_desc++; |
@@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
549 | uvc_control_header->bInCollection = 1; | 542 | uvc_control_header->bInCollection = 1; |
550 | uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; | 543 | uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; |
551 | 544 | ||
552 | UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep); | 545 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep); |
553 | if (speed == USB_SPEED_SUPER) | 546 | if (speed == USB_SPEED_SUPER) |
554 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); | 547 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp); |
555 | 548 | ||
@@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) | |||
560 | UVC_COPY_DESCRIPTORS(mem, dst, | 553 | UVC_COPY_DESCRIPTORS(mem, dst, |
561 | (const struct usb_descriptor_header**)uvc_streaming_cls); | 554 | (const struct usb_descriptor_header**)uvc_streaming_cls); |
562 | uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); | 555 | uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); |
563 | uvc_streaming_header->bEndpointAddress = | 556 | uvc_streaming_header->bEndpointAddress = uvc->video.ep->address; |
564 | uvc_fs_streaming_ep.bEndpointAddress; | ||
565 | 557 | ||
566 | UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); | 558 | UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); |
567 | 559 | ||
@@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) | |||
581 | uvc->control_ep->driver_data = NULL; | 573 | uvc->control_ep->driver_data = NULL; |
582 | uvc->video.ep->driver_data = NULL; | 574 | uvc->video.ep->driver_data = NULL; |
583 | 575 | ||
584 | uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0; | 576 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0; |
585 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); | 577 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
586 | kfree(uvc->control_buf); | 578 | kfree(uvc->control_buf); |
587 | 579 | ||
@@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
595 | { | 587 | { |
596 | struct usb_composite_dev *cdev = c->cdev; | 588 | struct usb_composite_dev *cdev = c->cdev; |
597 | struct uvc_device *uvc = to_uvc(f); | 589 | struct uvc_device *uvc = to_uvc(f); |
590 | unsigned int max_packet_mult; | ||
591 | unsigned int max_packet_size; | ||
598 | struct usb_ep *ep; | 592 | struct usb_ep *ep; |
599 | int ret = -EINVAL; | 593 | int ret = -EINVAL; |
600 | 594 | ||
601 | INFO(cdev, "uvc_function_bind\n"); | 595 | INFO(cdev, "uvc_function_bind\n"); |
602 | 596 | ||
603 | /* sanity check the streaming endpoint module parameters */ | 597 | /* Sanity check the streaming endpoint module parameters. |
604 | if (streaming_interval < 1) | ||
605 | streaming_interval = 1; | ||
606 | if (streaming_interval > 16) | ||
607 | streaming_interval = 16; | ||
608 | if (streaming_mult > 2) | ||
609 | streaming_mult = 2; | ||
610 | if (streaming_maxburst > 15) | ||
611 | streaming_maxburst = 15; | ||
612 | |||
613 | /* | ||
614 | * fill in the FS video streaming specific descriptors from the | ||
615 | * module parameters | ||
616 | */ | 598 | */ |
617 | uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ? | 599 | streaming_interval = clamp(streaming_interval, 1U, 16U); |
618 | 1023 : streaming_maxpacket; | 600 | streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U); |
601 | streaming_maxburst = min(streaming_maxburst, 15U); | ||
602 | |||
603 | /* Fill in the FS/HS/SS Video Streaming specific descriptors from the | ||
604 | * module parameters. | ||
605 | * | ||
606 | * NOTE: We assume that the user knows what they are doing and won't | ||
607 | * give parameters that their UDC doesn't support. | ||
608 | */ | ||
609 | if (streaming_maxpacket <= 1024) { | ||
610 | max_packet_mult = 1; | ||
611 | max_packet_size = streaming_maxpacket; | ||
612 | } else if (streaming_maxpacket <= 2048) { | ||
613 | max_packet_mult = 2; | ||
614 | max_packet_size = streaming_maxpacket / 2; | ||
615 | } else { | ||
616 | max_packet_mult = 3; | ||
617 | max_packet_size = streaming_maxpacket / 3; | ||
618 | } | ||
619 | |||
620 | uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U); | ||
619 | uvc_fs_streaming_ep.bInterval = streaming_interval; | 621 | uvc_fs_streaming_ep.bInterval = streaming_interval; |
620 | 622 | ||
623 | uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size; | ||
624 | uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11); | ||
625 | uvc_hs_streaming_ep.bInterval = streaming_interval; | ||
626 | |||
627 | uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size; | ||
628 | uvc_ss_streaming_ep.bInterval = streaming_interval; | ||
629 | uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; | ||
630 | uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; | ||
631 | uvc_ss_streaming_comp.wBytesPerInterval = | ||
632 | max_packet_size * max_packet_mult * streaming_maxburst; | ||
633 | |||
621 | /* Allocate endpoints. */ | 634 | /* Allocate endpoints. */ |
622 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep); | 635 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); |
623 | if (!ep) { | 636 | if (!ep) { |
624 | INFO(cdev, "Unable to allocate control EP\n"); | 637 | INFO(cdev, "Unable to allocate control EP\n"); |
625 | goto error; | 638 | goto error; |
@@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
627 | uvc->control_ep = ep; | 640 | uvc->control_ep = ep; |
628 | ep->driver_data = uvc; | 641 | ep->driver_data = uvc; |
629 | 642 | ||
630 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); | 643 | if (gadget_is_superspeed(c->cdev->gadget)) |
644 | ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, | ||
645 | &uvc_ss_streaming_comp); | ||
646 | else if (gadget_is_dualspeed(cdev->gadget)) | ||
647 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); | ||
648 | else | ||
649 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); | ||
650 | |||
631 | if (!ep) { | 651 | if (!ep) { |
632 | INFO(cdev, "Unable to allocate streaming EP\n"); | 652 | INFO(cdev, "Unable to allocate streaming EP\n"); |
633 | goto error; | 653 | goto error; |
@@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
635 | uvc->video.ep = ep; | 655 | uvc->video.ep = ep; |
636 | ep->driver_data = uvc; | 656 | ep->driver_data = uvc; |
637 | 657 | ||
658 | uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; | ||
659 | uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; | ||
660 | uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; | ||
661 | |||
638 | /* Allocate interface IDs. */ | 662 | /* Allocate interface IDs. */ |
639 | if ((ret = usb_interface_id(c, f)) < 0) | 663 | if ((ret = usb_interface_id(c, f)) < 0) |
640 | goto error; | 664 | goto error; |
@@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) | |||
648 | uvc_streaming_intf_alt1.bInterfaceNumber = ret; | 672 | uvc_streaming_intf_alt1.bInterfaceNumber = ret; |
649 | uvc->streaming_intf = ret; | 673 | uvc->streaming_intf = ret; |
650 | 674 | ||
651 | /* sanity check the streaming endpoint module parameters */ | ||
652 | if (streaming_maxpacket > 1024) | ||
653 | streaming_maxpacket = 1024; | ||
654 | /* | ||
655 | * Fill in the HS descriptors from the module parameters for the Video | ||
656 | * Streaming endpoint. | ||
657 | * NOTE: We assume that the user knows what they are doing and won't | ||
658 | * give parameters that their UDC doesn't support. | ||
659 | */ | ||
660 | uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; | ||
661 | uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; | ||
662 | uvc_hs_streaming_ep.bInterval = streaming_interval; | ||
663 | uvc_hs_streaming_ep.bEndpointAddress = | ||
664 | uvc_fs_streaming_ep.bEndpointAddress; | ||
665 | |||
666 | /* | ||
667 | * Fill in the SS descriptors from the module parameters for the Video | ||
668 | * Streaming endpoint. | ||
669 | * NOTE: We assume that the user knows what they are doing and won't | ||
670 | * give parameters that their UDC doesn't support. | ||
671 | */ | ||
672 | uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; | ||
673 | uvc_ss_streaming_ep.bInterval = streaming_interval; | ||
674 | uvc_ss_streaming_comp.bmAttributes = streaming_mult; | ||
675 | uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst; | ||
676 | uvc_ss_streaming_comp.wBytesPerInterval = | ||
677 | streaming_maxpacket * (streaming_mult + 1) * | ||
678 | (streaming_maxburst + 1); | ||
679 | uvc_ss_streaming_ep.bEndpointAddress = | ||
680 | uvc_fs_streaming_ep.bEndpointAddress; | ||
681 | |||
682 | /* Copy descriptors */ | 675 | /* Copy descriptors */ |
683 | f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); | 676 | f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); |
684 | if (gadget_is_dualspeed(cdev->gadget)) | 677 | if (gadget_is_dualspeed(cdev->gadget)) |
@@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c, | |||
775 | 768 | ||
776 | /* Validate the descriptors. */ | 769 | /* Validate the descriptors. */ |
777 | if (fs_control == NULL || fs_control[0] == NULL || | 770 | if (fs_control == NULL || fs_control[0] == NULL || |
778 | fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) | 771 | fs_control[0]->bDescriptorSubType != UVC_VC_HEADER) |
779 | goto error; | 772 | goto error; |
780 | 773 | ||
781 | if (ss_control == NULL || ss_control[0] == NULL || | 774 | if (ss_control == NULL || ss_control[0] == NULL || |
782 | ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) | 775 | ss_control[0]->bDescriptorSubType != UVC_VC_HEADER) |
783 | goto error; | 776 | goto error; |
784 | 777 | ||
785 | if (fs_streaming == NULL || fs_streaming[0] == NULL || | 778 | if (fs_streaming == NULL || fs_streaming[0] == NULL || |
786 | fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | 779 | fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) |
787 | goto error; | 780 | goto error; |
788 | 781 | ||
789 | if (hs_streaming == NULL || hs_streaming[0] == NULL || | 782 | if (hs_streaming == NULL || hs_streaming[0] == NULL || |
790 | hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | 783 | hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) |
791 | goto error; | 784 | goto error; |
792 | 785 | ||
793 | if (ss_streaming == NULL || ss_streaming[0] == NULL || | 786 | if (ss_streaming == NULL || ss_streaming[0] == NULL || |
794 | ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) | 787 | ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) |
795 | goto error; | 788 | goto error; |
796 | 789 | ||
797 | uvc->desc.fs_control = fs_control; | 790 | uvc->desc.fs_control = fs_control; |
@@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c, | |||
800 | uvc->desc.hs_streaming = hs_streaming; | 793 | uvc->desc.hs_streaming = hs_streaming; |
801 | uvc->desc.ss_streaming = ss_streaming; | 794 | uvc->desc.ss_streaming = ss_streaming; |
802 | 795 | ||
803 | /* Allocate string descriptor numbers. */ | 796 | /* String descriptors are global, we only need to allocate string IDs |
804 | if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) { | 797 | * for the first UVC function. UVC functions beyond the first (if any) |
798 | * will reuse the same IDs. | ||
799 | */ | ||
800 | if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) { | ||
805 | ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings); | 801 | ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings); |
806 | if (ret) | 802 | if (ret) |
807 | goto error; | 803 | goto error; |
808 | uvc_iad.iFunction = | 804 | uvc_iad.iFunction = |
809 | uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id; | 805 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; |
810 | uvc_control_intf.iInterface = | 806 | uvc_control_intf.iInterface = |
811 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; | 807 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id; |
812 | ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id; | 808 | ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id; |