1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * uvc_gadget.c -- USB Video Class Gadget driver |
4 | * |
5 | * Copyright (C) 2009-2010 |
6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
7 | */ |
8 | |
9 | #include <linux/device.h> |
10 | #include <linux/errno.h> |
11 | #include <linux/fs.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/list.h> |
14 | #include <linux/module.h> |
15 | #include <linux/mutex.h> |
16 | #include <linux/string.h> |
17 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb/gadget.h> |
19 | #include <linux/usb/g_uvc.h> |
20 | #include <linux/usb/video.h> |
21 | #include <linux/vmalloc.h> |
22 | #include <linux/wait.h> |
23 | |
24 | #include <media/v4l2-dev.h> |
25 | #include <media/v4l2-event.h> |
26 | |
27 | #include "uvc.h" |
28 | #include "uvc_configfs.h" |
29 | #include "uvc_v4l2.h" |
30 | #include "uvc_video.h" |
31 | |
32 | unsigned int uvc_gadget_trace_param; |
33 | module_param_named(trace, uvc_gadget_trace_param, uint, 0644); |
34 | MODULE_PARM_DESC(trace, "Trace level bitmask" ); |
35 | |
36 | /* -------------------------------------------------------------------------- |
37 | * Function descriptors |
38 | */ |
39 | |
40 | /* string IDs are assigned dynamically */ |
41 | |
42 | static struct usb_string uvc_en_us_strings[] = { |
43 | /* [UVC_STRING_CONTROL_IDX].s = DYNAMIC, */ |
44 | [UVC_STRING_STREAMING_IDX].s = "Video Streaming" , |
45 | { } |
46 | }; |
47 | |
48 | static struct usb_gadget_strings uvc_stringtab = { |
49 | .language = 0x0409, /* en-us */ |
50 | .strings = uvc_en_us_strings, |
51 | }; |
52 | |
53 | static struct usb_gadget_strings *uvc_function_strings[] = { |
54 | &uvc_stringtab, |
55 | NULL, |
56 | }; |
57 | |
58 | #define UVC_INTF_VIDEO_CONTROL 0 |
59 | #define UVC_INTF_VIDEO_STREAMING 1 |
60 | |
61 | #define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */ |
62 | |
63 | static struct usb_interface_assoc_descriptor uvc_iad = { |
64 | .bLength = sizeof(uvc_iad), |
65 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
66 | .bFirstInterface = 0, |
67 | .bInterfaceCount = 2, |
68 | .bFunctionClass = USB_CLASS_VIDEO, |
69 | .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, |
70 | .bFunctionProtocol = 0x00, |
71 | .iFunction = 0, |
72 | }; |
73 | |
74 | static struct usb_interface_descriptor uvc_control_intf = { |
75 | .bLength = USB_DT_INTERFACE_SIZE, |
76 | .bDescriptorType = USB_DT_INTERFACE, |
77 | .bInterfaceNumber = UVC_INTF_VIDEO_CONTROL, |
78 | .bAlternateSetting = 0, |
79 | .bNumEndpoints = 0, |
80 | .bInterfaceClass = USB_CLASS_VIDEO, |
81 | .bInterfaceSubClass = UVC_SC_VIDEOCONTROL, |
82 | .bInterfaceProtocol = 0x00, |
83 | .iInterface = 0, |
84 | }; |
85 | |
86 | static struct usb_endpoint_descriptor uvc_interrupt_ep = { |
87 | .bLength = USB_DT_ENDPOINT_SIZE, |
88 | .bDescriptorType = USB_DT_ENDPOINT, |
89 | .bEndpointAddress = USB_DIR_IN, |
90 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
91 | .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
92 | .bInterval = 8, |
93 | }; |
94 | |
95 | static struct usb_ss_ep_comp_descriptor uvc_ss_interrupt_comp = { |
96 | .bLength = sizeof(uvc_ss_interrupt_comp), |
97 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
98 | /* The following 3 values can be tweaked if necessary. */ |
99 | .bMaxBurst = 0, |
100 | .bmAttributes = 0, |
101 | .wBytesPerInterval = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
102 | }; |
103 | |
104 | static struct uvc_control_endpoint_descriptor uvc_interrupt_cs_ep = { |
105 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, |
106 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
107 | .bDescriptorSubType = UVC_EP_INTERRUPT, |
108 | .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
109 | }; |
110 | |
111 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 = { |
112 | .bLength = USB_DT_INTERFACE_SIZE, |
113 | .bDescriptorType = USB_DT_INTERFACE, |
114 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, |
115 | .bAlternateSetting = 0, |
116 | .bNumEndpoints = 0, |
117 | .bInterfaceClass = USB_CLASS_VIDEO, |
118 | .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, |
119 | .bInterfaceProtocol = 0x00, |
120 | .iInterface = 0, |
121 | }; |
122 | |
123 | static struct usb_interface_descriptor uvc_streaming_intf_alt1 = { |
124 | .bLength = USB_DT_INTERFACE_SIZE, |
125 | .bDescriptorType = USB_DT_INTERFACE, |
126 | .bInterfaceNumber = UVC_INTF_VIDEO_STREAMING, |
127 | .bAlternateSetting = 1, |
128 | .bNumEndpoints = 1, |
129 | .bInterfaceClass = USB_CLASS_VIDEO, |
130 | .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, |
131 | .bInterfaceProtocol = 0x00, |
132 | .iInterface = 0, |
133 | }; |
134 | |
135 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { |
136 | .bLength = USB_DT_ENDPOINT_SIZE, |
137 | .bDescriptorType = USB_DT_ENDPOINT, |
138 | .bEndpointAddress = USB_DIR_IN, |
139 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
140 | | USB_ENDPOINT_XFER_ISOC, |
141 | /* |
142 | * The wMaxPacketSize and bInterval values will be initialized from |
143 | * module parameters. |
144 | */ |
145 | }; |
146 | |
147 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { |
148 | .bLength = USB_DT_ENDPOINT_SIZE, |
149 | .bDescriptorType = USB_DT_ENDPOINT, |
150 | .bEndpointAddress = USB_DIR_IN, |
151 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
152 | | USB_ENDPOINT_XFER_ISOC, |
153 | /* |
154 | * The wMaxPacketSize and bInterval values will be initialized from |
155 | * module parameters. |
156 | */ |
157 | }; |
158 | |
159 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep = { |
160 | .bLength = USB_DT_ENDPOINT_SIZE, |
161 | .bDescriptorType = USB_DT_ENDPOINT, |
162 | |
163 | .bEndpointAddress = USB_DIR_IN, |
164 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
165 | | USB_ENDPOINT_XFER_ISOC, |
166 | /* |
167 | * The wMaxPacketSize and bInterval values will be initialized from |
168 | * module parameters. |
169 | */ |
170 | }; |
171 | |
172 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { |
173 | .bLength = sizeof(uvc_ss_streaming_comp), |
174 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
175 | /* |
176 | * The bMaxBurst, bmAttributes and wBytesPerInterval values will be |
177 | * initialized from module parameters. |
178 | */ |
179 | }; |
180 | |
181 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { |
182 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, |
183 | (struct usb_descriptor_header *) &uvc_fs_streaming_ep, |
184 | NULL, |
185 | }; |
186 | |
187 | static const struct usb_descriptor_header * const uvc_hs_streaming[] = { |
188 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, |
189 | (struct usb_descriptor_header *) &uvc_hs_streaming_ep, |
190 | NULL, |
191 | }; |
192 | |
193 | static const struct usb_descriptor_header * const uvc_ss_streaming[] = { |
194 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, |
195 | (struct usb_descriptor_header *) &uvc_ss_streaming_ep, |
196 | (struct usb_descriptor_header *) &uvc_ss_streaming_comp, |
197 | NULL, |
198 | }; |
199 | |
200 | /* -------------------------------------------------------------------------- |
201 | * Control requests |
202 | */ |
203 | |
204 | static void |
205 | uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) |
206 | { |
207 | struct uvc_device *uvc = req->context; |
208 | struct v4l2_event v4l2_event; |
209 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
210 | |
211 | if (uvc->event_setup_out) { |
212 | uvc->event_setup_out = 0; |
213 | |
214 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
215 | v4l2_event.type = UVC_EVENT_DATA; |
216 | uvc_event->data.length = min_t(unsigned int, req->actual, |
217 | sizeof(uvc_event->data.data)); |
218 | memcpy(&uvc_event->data.data, req->buf, uvc_event->data.length); |
219 | v4l2_event_queue(vdev: &uvc->vdev, ev: &v4l2_event); |
220 | } |
221 | } |
222 | |
223 | static int |
224 | uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) |
225 | { |
226 | struct uvc_device *uvc = to_uvc(f); |
227 | struct v4l2_event v4l2_event; |
228 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
229 | unsigned int interface = le16_to_cpu(ctrl->wIndex) & 0xff; |
230 | struct usb_ctrlrequest *mctrl; |
231 | |
232 | if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { |
233 | uvcg_info(f, "invalid request type\n" ); |
234 | return -EINVAL; |
235 | } |
236 | |
237 | /* Stall too big requests. */ |
238 | if (le16_to_cpu(ctrl->wLength) > UVC_MAX_REQUEST_SIZE) |
239 | return -EINVAL; |
240 | |
241 | /* |
242 | * Tell the complete callback to generate an event for the next request |
243 | * that will be enqueued by UVCIOC_SEND_RESPONSE. |
244 | */ |
245 | uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN); |
246 | uvc->event_length = le16_to_cpu(ctrl->wLength); |
247 | |
248 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
249 | v4l2_event.type = UVC_EVENT_SETUP; |
250 | memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); |
251 | |
252 | /* check for the interface number, fixup the interface number in |
253 | * the ctrl request so the userspace doesn't have to bother with |
254 | * offset and configfs parsing |
255 | */ |
256 | mctrl = &uvc_event->req; |
257 | mctrl->wIndex &= ~cpu_to_le16(0xff); |
258 | if (interface == uvc->streaming_intf) |
259 | mctrl->wIndex = cpu_to_le16(UVC_STRING_STREAMING_IDX); |
260 | |
261 | v4l2_event_queue(vdev: &uvc->vdev, ev: &v4l2_event); |
262 | |
263 | return 0; |
264 | } |
265 | |
266 | void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep) |
267 | { |
268 | struct usb_composite_dev *cdev = uvc->func.config->cdev; |
269 | |
270 | if (disable_ep && uvc->video.ep) |
271 | usb_ep_disable(ep: uvc->video.ep); |
272 | |
273 | usb_composite_setup_continue(cdev); |
274 | } |
275 | |
276 | static int |
277 | uvc_function_get_alt(struct usb_function *f, unsigned interface) |
278 | { |
279 | struct uvc_device *uvc = to_uvc(f); |
280 | |
281 | uvcg_info(f, "%s(%u)\n" , __func__, interface); |
282 | |
283 | if (interface == uvc->control_intf) |
284 | return 0; |
285 | else if (interface != uvc->streaming_intf) |
286 | return -EINVAL; |
287 | else |
288 | return uvc->video.ep->enabled ? 1 : 0; |
289 | } |
290 | |
291 | static int |
292 | uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) |
293 | { |
294 | struct uvc_device *uvc = to_uvc(f); |
295 | struct usb_composite_dev *cdev = f->config->cdev; |
296 | struct v4l2_event v4l2_event; |
297 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; |
298 | int ret; |
299 | |
300 | uvcg_info(f, "%s(%u, %u)\n" , __func__, interface, alt); |
301 | |
302 | if (interface == uvc->control_intf) { |
303 | if (alt) |
304 | return -EINVAL; |
305 | |
306 | if (uvc->enable_interrupt_ep) { |
307 | uvcg_info(f, "reset UVC interrupt endpoint\n" ); |
308 | usb_ep_disable(ep: uvc->interrupt_ep); |
309 | |
310 | if (!uvc->interrupt_ep->desc) |
311 | if (config_ep_by_speed(g: cdev->gadget, f, |
312 | ep: uvc->interrupt_ep)) |
313 | return -EINVAL; |
314 | |
315 | usb_ep_enable(ep: uvc->interrupt_ep); |
316 | } |
317 | |
318 | if (uvc->state == UVC_STATE_DISCONNECTED) { |
319 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
320 | v4l2_event.type = UVC_EVENT_CONNECT; |
321 | uvc_event->speed = cdev->gadget->speed; |
322 | v4l2_event_queue(vdev: &uvc->vdev, ev: &v4l2_event); |
323 | |
324 | uvc->state = UVC_STATE_CONNECTED; |
325 | } |
326 | |
327 | return 0; |
328 | } |
329 | |
330 | if (interface != uvc->streaming_intf) |
331 | return -EINVAL; |
332 | |
333 | /* TODO |
334 | if (usb_endpoint_xfer_bulk(&uvc->desc.vs_ep)) |
335 | return alt ? -EINVAL : 0; |
336 | */ |
337 | |
338 | switch (alt) { |
339 | case 0: |
340 | if (uvc->state != UVC_STATE_STREAMING) |
341 | return 0; |
342 | |
343 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
344 | v4l2_event.type = UVC_EVENT_STREAMOFF; |
345 | v4l2_event_queue(vdev: &uvc->vdev, ev: &v4l2_event); |
346 | |
347 | return USB_GADGET_DELAYED_STATUS; |
348 | |
349 | case 1: |
350 | if (uvc->state != UVC_STATE_CONNECTED) |
351 | return 0; |
352 | |
353 | if (!uvc->video.ep) |
354 | return -EINVAL; |
355 | |
356 | uvcg_info(f, "reset UVC\n" ); |
357 | usb_ep_disable(ep: uvc->video.ep); |
358 | |
359 | ret = config_ep_by_speed(g: f->config->cdev->gadget, |
360 | f: &(uvc->func), ep: uvc->video.ep); |
361 | if (ret) |
362 | return ret; |
363 | usb_ep_enable(ep: uvc->video.ep); |
364 | |
365 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
366 | v4l2_event.type = UVC_EVENT_STREAMON; |
367 | v4l2_event_queue(vdev: &uvc->vdev, ev: &v4l2_event); |
368 | return USB_GADGET_DELAYED_STATUS; |
369 | |
370 | default: |
371 | return -EINVAL; |
372 | } |
373 | } |
374 | |
375 | static void |
376 | uvc_function_disable(struct usb_function *f) |
377 | { |
378 | struct uvc_device *uvc = to_uvc(f); |
379 | struct v4l2_event v4l2_event; |
380 | |
381 | uvcg_info(f, "%s()\n" , __func__); |
382 | |
383 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
384 | v4l2_event.type = UVC_EVENT_DISCONNECT; |
385 | v4l2_event_queue(vdev: &uvc->vdev, ev: &v4l2_event); |
386 | |
387 | uvc->state = UVC_STATE_DISCONNECTED; |
388 | |
389 | usb_ep_disable(ep: uvc->video.ep); |
390 | if (uvc->enable_interrupt_ep) |
391 | usb_ep_disable(ep: uvc->interrupt_ep); |
392 | } |
393 | |
394 | /* -------------------------------------------------------------------------- |
395 | * Connection / disconnection |
396 | */ |
397 | |
398 | void |
399 | uvc_function_connect(struct uvc_device *uvc) |
400 | { |
401 | int ret; |
402 | |
403 | if ((ret = usb_function_activate(&uvc->func)) < 0) |
404 | uvcg_info(&uvc->func, "UVC connect failed with %d\n" , ret); |
405 | } |
406 | |
407 | void |
408 | uvc_function_disconnect(struct uvc_device *uvc) |
409 | { |
410 | int ret; |
411 | |
412 | if ((ret = usb_function_deactivate(&uvc->func)) < 0) |
413 | uvcg_info(&uvc->func, "UVC disconnect failed with %d\n" , ret); |
414 | } |
415 | |
416 | /* -------------------------------------------------------------------------- |
417 | * USB probe and disconnect |
418 | */ |
419 | |
420 | static ssize_t function_name_show(struct device *dev, |
421 | struct device_attribute *attr, char *buf) |
422 | { |
423 | struct uvc_device *uvc = dev_get_drvdata(dev); |
424 | |
425 | return sprintf(buf, fmt: "%s\n" , uvc->func.fi->group.cg_item.ci_name); |
426 | } |
427 | |
428 | static DEVICE_ATTR_RO(function_name); |
429 | |
430 | static int |
431 | uvc_register_video(struct uvc_device *uvc) |
432 | { |
433 | struct usb_composite_dev *cdev = uvc->func.config->cdev; |
434 | int ret; |
435 | |
436 | /* TODO reference counting. */ |
437 | memset(&uvc->vdev, 0, sizeof(uvc->vdev)); |
438 | uvc->vdev.v4l2_dev = &uvc->v4l2_dev; |
439 | uvc->vdev.v4l2_dev->dev = &cdev->gadget->dev; |
440 | uvc->vdev.fops = &uvc_v4l2_fops; |
441 | uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops; |
442 | uvc->vdev.release = video_device_release_empty; |
443 | uvc->vdev.vfl_dir = VFL_DIR_TX; |
444 | uvc->vdev.lock = &uvc->video.mutex; |
445 | uvc->vdev.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; |
446 | strscpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name)); |
447 | |
448 | video_set_drvdata(vdev: &uvc->vdev, data: uvc); |
449 | |
450 | ret = video_register_device(vdev: &uvc->vdev, type: VFL_TYPE_VIDEO, nr: -1); |
451 | if (ret < 0) |
452 | return ret; |
453 | |
454 | ret = device_create_file(device: &uvc->vdev.dev, entry: &dev_attr_function_name); |
455 | if (ret < 0) { |
456 | video_unregister_device(vdev: &uvc->vdev); |
457 | return ret; |
458 | } |
459 | |
460 | return 0; |
461 | } |
462 | |
463 | #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \ |
464 | do { \ |
465 | memcpy(mem, desc, (desc)->bLength); \ |
466 | *(dst)++ = mem; \ |
467 | mem += (desc)->bLength; \ |
468 | } while (0); |
469 | |
470 | #define UVC_COPY_DESCRIPTORS(mem, dst, src) \ |
471 | do { \ |
472 | const struct usb_descriptor_header * const *__src; \ |
473 | for (__src = src; *__src; ++__src) { \ |
474 | memcpy(mem, *__src, (*__src)->bLength); \ |
475 | *dst++ = mem; \ |
476 | mem += (*__src)->bLength; \ |
477 | } \ |
478 | } while (0) |
479 | |
480 | #define UVC_COPY_XU_DESCRIPTOR(mem, dst, desc) \ |
481 | do { \ |
482 | *(dst)++ = mem; \ |
483 | memcpy(mem, desc, 22); /* bLength to bNrInPins */ \ |
484 | mem += 22; \ |
485 | \ |
486 | memcpy(mem, (desc)->baSourceID, (desc)->bNrInPins); \ |
487 | mem += (desc)->bNrInPins; \ |
488 | \ |
489 | memcpy(mem, &(desc)->bControlSize, 1); \ |
490 | mem++; \ |
491 | \ |
492 | memcpy(mem, (desc)->bmControls, (desc)->bControlSize); \ |
493 | mem += (desc)->bControlSize; \ |
494 | \ |
495 | memcpy(mem, &(desc)->iExtension, 1); \ |
496 | mem++; \ |
497 | } while (0) |
498 | |
499 | static struct usb_descriptor_header ** |
500 | uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) |
501 | { |
502 | struct uvc_input_header_descriptor *; |
503 | struct uvc_header_descriptor *; |
504 | const struct uvc_descriptor_header * const *uvc_control_desc; |
505 | const struct uvc_descriptor_header * const *uvc_streaming_cls; |
506 | const struct usb_descriptor_header * const *uvc_streaming_std; |
507 | const struct usb_descriptor_header * const *src; |
508 | struct usb_descriptor_header **dst; |
509 | struct usb_descriptor_header **hdr; |
510 | struct uvcg_extension *xu; |
511 | unsigned int control_size; |
512 | unsigned int streaming_size; |
513 | unsigned int n_desc; |
514 | unsigned int bytes; |
515 | void *mem; |
516 | |
517 | switch (speed) { |
518 | case USB_SPEED_SUPER_PLUS: |
519 | case USB_SPEED_SUPER: |
520 | uvc_control_desc = uvc->desc.ss_control; |
521 | uvc_streaming_cls = uvc->desc.ss_streaming; |
522 | uvc_streaming_std = uvc_ss_streaming; |
523 | break; |
524 | |
525 | case USB_SPEED_HIGH: |
526 | uvc_control_desc = uvc->desc.fs_control; |
527 | uvc_streaming_cls = uvc->desc.hs_streaming; |
528 | uvc_streaming_std = uvc_hs_streaming; |
529 | break; |
530 | |
531 | case USB_SPEED_FULL: |
532 | default: |
533 | uvc_control_desc = uvc->desc.fs_control; |
534 | uvc_streaming_cls = uvc->desc.fs_streaming; |
535 | uvc_streaming_std = uvc_fs_streaming; |
536 | break; |
537 | } |
538 | |
539 | if (!uvc_control_desc || !uvc_streaming_cls) |
540 | return ERR_PTR(error: -ENODEV); |
541 | |
542 | /* |
543 | * Descriptors layout |
544 | * |
545 | * uvc_iad |
546 | * uvc_control_intf |
547 | * Class-specific UVC control descriptors |
548 | * uvc_interrupt_ep |
549 | * uvc_interrupt_cs_ep |
550 | * uvc_ss_interrupt_comp (for SS only) |
551 | * uvc_streaming_intf_alt0 |
552 | * Class-specific UVC streaming descriptors |
553 | * uvc_{fs|hs}_streaming |
554 | */ |
555 | |
556 | /* Count descriptors and compute their size. */ |
557 | control_size = 0; |
558 | streaming_size = 0; |
559 | bytes = uvc_iad.bLength + uvc_control_intf.bLength |
560 | + uvc_streaming_intf_alt0.bLength; |
561 | |
562 | n_desc = 3; |
563 | if (uvc->enable_interrupt_ep) { |
564 | bytes += uvc_interrupt_ep.bLength + uvc_interrupt_cs_ep.bLength; |
565 | n_desc += 2; |
566 | |
567 | if (speed == USB_SPEED_SUPER || |
568 | speed == USB_SPEED_SUPER_PLUS) { |
569 | bytes += uvc_ss_interrupt_comp.bLength; |
570 | n_desc += 1; |
571 | } |
572 | } |
573 | |
574 | for (src = (const struct usb_descriptor_header **)uvc_control_desc; |
575 | *src; ++src) { |
576 | control_size += (*src)->bLength; |
577 | bytes += (*src)->bLength; |
578 | n_desc++; |
579 | } |
580 | |
581 | list_for_each_entry(xu, uvc->desc.extension_units, list) { |
582 | control_size += xu->desc.bLength; |
583 | bytes += xu->desc.bLength; |
584 | n_desc++; |
585 | } |
586 | |
587 | for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; |
588 | *src; ++src) { |
589 | streaming_size += (*src)->bLength; |
590 | bytes += (*src)->bLength; |
591 | n_desc++; |
592 | } |
593 | for (src = uvc_streaming_std; *src; ++src) { |
594 | bytes += (*src)->bLength; |
595 | n_desc++; |
596 | } |
597 | |
598 | mem = kmalloc(size: (n_desc + 1) * sizeof(*src) + bytes, GFP_KERNEL); |
599 | if (mem == NULL) |
600 | return NULL; |
601 | |
602 | hdr = mem; |
603 | dst = mem; |
604 | mem += (n_desc + 1) * sizeof(*src); |
605 | |
606 | /* Copy the descriptors. */ |
607 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_iad); |
608 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_intf); |
609 | |
610 | uvc_control_header = mem; |
611 | UVC_COPY_DESCRIPTORS(mem, dst, |
612 | (const struct usb_descriptor_header **)uvc_control_desc); |
613 | |
614 | list_for_each_entry(xu, uvc->desc.extension_units, list) |
615 | UVC_COPY_XU_DESCRIPTOR(mem, dst, &xu->desc); |
616 | |
617 | uvc_control_header->wTotalLength = cpu_to_le16(control_size); |
618 | uvc_control_header->bInCollection = 1; |
619 | uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf; |
620 | |
621 | if (uvc->enable_interrupt_ep) { |
622 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep); |
623 | if (speed == USB_SPEED_SUPER || |
624 | speed == USB_SPEED_SUPER_PLUS) |
625 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_interrupt_comp); |
626 | |
627 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_cs_ep); |
628 | } |
629 | |
630 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_streaming_intf_alt0); |
631 | |
632 | uvc_streaming_header = mem; |
633 | UVC_COPY_DESCRIPTORS(mem, dst, |
634 | (const struct usb_descriptor_header**)uvc_streaming_cls); |
635 | uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size); |
636 | uvc_streaming_header->bEndpointAddress = uvc->video.ep->address; |
637 | |
638 | UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); |
639 | |
640 | *dst = NULL; |
641 | return hdr; |
642 | } |
643 | |
644 | static int |
645 | uvc_function_bind(struct usb_configuration *c, struct usb_function *f) |
646 | { |
647 | struct usb_composite_dev *cdev = c->cdev; |
648 | struct uvc_device *uvc = to_uvc(f); |
649 | struct uvcg_extension *xu; |
650 | struct usb_string *us; |
651 | unsigned int max_packet_mult; |
652 | unsigned int max_packet_size; |
653 | struct usb_ep *ep; |
654 | struct f_uvc_opts *opts; |
655 | int ret = -EINVAL; |
656 | |
657 | uvcg_info(f, "%s()\n" , __func__); |
658 | |
659 | opts = fi_to_f_uvc_opts(f->fi); |
660 | /* Sanity check the streaming endpoint module parameters. */ |
661 | opts->streaming_interval = clamp(opts->streaming_interval, 1U, 16U); |
662 | opts->streaming_maxpacket = clamp(opts->streaming_maxpacket, 1U, 3072U); |
663 | opts->streaming_maxburst = min(opts->streaming_maxburst, 15U); |
664 | |
665 | /* For SS, wMaxPacketSize has to be 1024 if bMaxBurst is not 0 */ |
666 | if (opts->streaming_maxburst && |
667 | (opts->streaming_maxpacket % 1024) != 0) { |
668 | opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024); |
669 | uvcg_info(f, "overriding streaming_maxpacket to %d\n" , |
670 | opts->streaming_maxpacket); |
671 | } |
672 | |
673 | /* |
674 | * Fill in the FS/HS/SS Video Streaming specific descriptors from the |
675 | * module parameters. |
676 | * |
677 | * NOTE: We assume that the user knows what they are doing and won't |
678 | * give parameters that their UDC doesn't support. |
679 | */ |
680 | if (opts->streaming_maxpacket <= 1024) { |
681 | max_packet_mult = 1; |
682 | max_packet_size = opts->streaming_maxpacket; |
683 | } else if (opts->streaming_maxpacket <= 2048) { |
684 | max_packet_mult = 2; |
685 | max_packet_size = opts->streaming_maxpacket / 2; |
686 | } else { |
687 | max_packet_mult = 3; |
688 | max_packet_size = opts->streaming_maxpacket / 3; |
689 | } |
690 | |
691 | uvc_fs_streaming_ep.wMaxPacketSize = |
692 | cpu_to_le16(min(opts->streaming_maxpacket, 1023U)); |
693 | uvc_fs_streaming_ep.bInterval = opts->streaming_interval; |
694 | |
695 | uvc_hs_streaming_ep.wMaxPacketSize = |
696 | cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); |
697 | |
698 | /* A high-bandwidth endpoint must specify a bInterval value of 1 */ |
699 | if (max_packet_mult > 1) |
700 | uvc_hs_streaming_ep.bInterval = 1; |
701 | else |
702 | uvc_hs_streaming_ep.bInterval = opts->streaming_interval; |
703 | |
704 | uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); |
705 | uvc_ss_streaming_ep.bInterval = opts->streaming_interval; |
706 | uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1; |
707 | uvc_ss_streaming_comp.bMaxBurst = opts->streaming_maxburst; |
708 | uvc_ss_streaming_comp.wBytesPerInterval = |
709 | cpu_to_le16(max_packet_size * max_packet_mult * |
710 | (opts->streaming_maxburst + 1)); |
711 | |
712 | /* Allocate endpoints. */ |
713 | if (opts->enable_interrupt_ep) { |
714 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_interrupt_ep); |
715 | if (!ep) { |
716 | uvcg_info(f, "Unable to allocate interrupt EP\n" ); |
717 | goto error; |
718 | } |
719 | uvc->interrupt_ep = ep; |
720 | uvc_control_intf.bNumEndpoints = 1; |
721 | } |
722 | uvc->enable_interrupt_ep = opts->enable_interrupt_ep; |
723 | |
724 | /* |
725 | * gadget_is_{super|dual}speed() API check UDC controller capitblity. It should pass down |
726 | * highest speed endpoint descriptor to UDC controller. So UDC controller driver can reserve |
727 | * enough resource at check_config(), especially mult and maxburst. So UDC driver (such as |
728 | * cdns3) can know need at least (mult + 1) * (maxburst + 1) * wMaxPacketSize internal |
729 | * memory for this uvc functions. This is the only straightforward method to resolve the UDC |
730 | * resource allocation issue in the current gadget framework. |
731 | */ |
732 | if (gadget_is_superspeed(g: c->cdev->gadget)) |
733 | ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep, |
734 | &uvc_ss_streaming_comp); |
735 | else if (gadget_is_dualspeed(g: cdev->gadget)) |
736 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep); |
737 | else |
738 | ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep); |
739 | |
740 | if (!ep) { |
741 | uvcg_info(f, "Unable to allocate streaming EP\n" ); |
742 | goto error; |
743 | } |
744 | uvc->video.ep = ep; |
745 | |
746 | uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
747 | uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
748 | uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
749 | |
750 | /* |
751 | * XUs can have an arbitrary string descriptor describing them. If they |
752 | * have one pick up the ID. |
753 | */ |
754 | list_for_each_entry(xu, &opts->extension_units, list) |
755 | if (xu->string_descriptor_index) |
756 | xu->desc.iExtension = cdev->usb_strings[xu->string_descriptor_index].id; |
757 | |
758 | /* |
759 | * We attach the hard-coded defaults incase the user does not provide |
760 | * any more appropriate strings through configfs. |
761 | */ |
762 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->function_name; |
763 | us = usb_gstrings_attach(cdev, sp: uvc_function_strings, |
764 | ARRAY_SIZE(uvc_en_us_strings)); |
765 | if (IS_ERR(ptr: us)) { |
766 | ret = PTR_ERR(ptr: us); |
767 | goto error; |
768 | } |
769 | |
770 | uvc_iad.iFunction = opts->iad_index ? cdev->usb_strings[opts->iad_index].id : |
771 | us[UVC_STRING_CONTROL_IDX].id; |
772 | uvc_streaming_intf_alt0.iInterface = opts->vs0_index ? |
773 | cdev->usb_strings[opts->vs0_index].id : |
774 | us[UVC_STRING_STREAMING_IDX].id; |
775 | uvc_streaming_intf_alt1.iInterface = opts->vs1_index ? |
776 | cdev->usb_strings[opts->vs1_index].id : |
777 | us[UVC_STRING_STREAMING_IDX].id; |
778 | |
779 | /* Allocate interface IDs. */ |
780 | if ((ret = usb_interface_id(c, f)) < 0) |
781 | goto error; |
782 | uvc_iad.bFirstInterface = ret; |
783 | uvc_control_intf.bInterfaceNumber = ret; |
784 | uvc->control_intf = ret; |
785 | opts->control_interface = ret; |
786 | |
787 | if ((ret = usb_interface_id(c, f)) < 0) |
788 | goto error; |
789 | uvc_streaming_intf_alt0.bInterfaceNumber = ret; |
790 | uvc_streaming_intf_alt1.bInterfaceNumber = ret; |
791 | uvc->streaming_intf = ret; |
792 | opts->streaming_interface = ret; |
793 | |
794 | /* Copy descriptors */ |
795 | f->fs_descriptors = uvc_copy_descriptors(uvc, speed: USB_SPEED_FULL); |
796 | if (IS_ERR(ptr: f->fs_descriptors)) { |
797 | ret = PTR_ERR(ptr: f->fs_descriptors); |
798 | f->fs_descriptors = NULL; |
799 | goto error; |
800 | } |
801 | |
802 | f->hs_descriptors = uvc_copy_descriptors(uvc, speed: USB_SPEED_HIGH); |
803 | if (IS_ERR(ptr: f->hs_descriptors)) { |
804 | ret = PTR_ERR(ptr: f->hs_descriptors); |
805 | f->hs_descriptors = NULL; |
806 | goto error; |
807 | } |
808 | |
809 | f->ss_descriptors = uvc_copy_descriptors(uvc, speed: USB_SPEED_SUPER); |
810 | if (IS_ERR(ptr: f->ss_descriptors)) { |
811 | ret = PTR_ERR(ptr: f->ss_descriptors); |
812 | f->ss_descriptors = NULL; |
813 | goto error; |
814 | } |
815 | |
816 | f->ssp_descriptors = uvc_copy_descriptors(uvc, speed: USB_SPEED_SUPER_PLUS); |
817 | if (IS_ERR(ptr: f->ssp_descriptors)) { |
818 | ret = PTR_ERR(ptr: f->ssp_descriptors); |
819 | f->ssp_descriptors = NULL; |
820 | goto error; |
821 | } |
822 | |
823 | /* Preallocate control endpoint request. */ |
824 | uvc->control_req = usb_ep_alloc_request(ep: cdev->gadget->ep0, GFP_KERNEL); |
825 | uvc->control_buf = kmalloc(UVC_MAX_REQUEST_SIZE, GFP_KERNEL); |
826 | if (uvc->control_req == NULL || uvc->control_buf == NULL) { |
827 | ret = -ENOMEM; |
828 | goto error; |
829 | } |
830 | |
831 | uvc->control_req->buf = uvc->control_buf; |
832 | uvc->control_req->complete = uvc_function_ep0_complete; |
833 | uvc->control_req->context = uvc; |
834 | |
835 | if (v4l2_device_register(dev: &cdev->gadget->dev, v4l2_dev: &uvc->v4l2_dev)) { |
836 | uvcg_err(f, "failed to register V4L2 device\n" ); |
837 | goto error; |
838 | } |
839 | |
840 | /* Initialise video. */ |
841 | ret = uvcg_video_init(video: &uvc->video, uvc); |
842 | if (ret < 0) |
843 | goto v4l2_error; |
844 | |
845 | /* Register a V4L2 device. */ |
846 | ret = uvc_register_video(uvc); |
847 | if (ret < 0) { |
848 | uvcg_err(f, "failed to register video device\n" ); |
849 | goto v4l2_error; |
850 | } |
851 | |
852 | return 0; |
853 | |
854 | v4l2_error: |
855 | v4l2_device_unregister(v4l2_dev: &uvc->v4l2_dev); |
856 | error: |
857 | if (uvc->control_req) |
858 | usb_ep_free_request(ep: cdev->gadget->ep0, req: uvc->control_req); |
859 | kfree(objp: uvc->control_buf); |
860 | |
861 | usb_free_all_descriptors(f); |
862 | return ret; |
863 | } |
864 | |
865 | /* -------------------------------------------------------------------------- |
866 | * USB gadget function |
867 | */ |
868 | |
869 | static void uvc_free_inst(struct usb_function_instance *f) |
870 | { |
871 | struct f_uvc_opts *opts = fi_to_f_uvc_opts(f); |
872 | |
873 | mutex_destroy(lock: &opts->lock); |
874 | kfree(objp: opts); |
875 | } |
876 | |
877 | static struct usb_function_instance *uvc_alloc_inst(void) |
878 | { |
879 | struct f_uvc_opts *opts; |
880 | struct uvc_camera_terminal_descriptor *cd; |
881 | struct uvc_processing_unit_descriptor *pd; |
882 | struct uvc_output_terminal_descriptor *od; |
883 | struct uvc_descriptor_header **ctl_cls; |
884 | int ret; |
885 | |
886 | opts = kzalloc(size: sizeof(*opts), GFP_KERNEL); |
887 | if (!opts) |
888 | return ERR_PTR(error: -ENOMEM); |
889 | opts->func_inst.free_func_inst = uvc_free_inst; |
890 | mutex_init(&opts->lock); |
891 | |
892 | cd = &opts->uvc_camera_terminal; |
893 | cd->bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3); |
894 | cd->bDescriptorType = USB_DT_CS_INTERFACE; |
895 | cd->bDescriptorSubType = UVC_VC_INPUT_TERMINAL; |
896 | cd->bTerminalID = 1; |
897 | cd->wTerminalType = cpu_to_le16(0x0201); |
898 | cd->bAssocTerminal = 0; |
899 | cd->iTerminal = 0; |
900 | cd->wObjectiveFocalLengthMin = cpu_to_le16(0); |
901 | cd->wObjectiveFocalLengthMax = cpu_to_le16(0); |
902 | cd->wOcularFocalLength = cpu_to_le16(0); |
903 | cd->bControlSize = 3; |
904 | cd->bmControls[0] = 2; |
905 | cd->bmControls[1] = 0; |
906 | cd->bmControls[2] = 0; |
907 | |
908 | pd = &opts->uvc_processing; |
909 | pd->bLength = UVC_DT_PROCESSING_UNIT_SIZE(2); |
910 | pd->bDescriptorType = USB_DT_CS_INTERFACE; |
911 | pd->bDescriptorSubType = UVC_VC_PROCESSING_UNIT; |
912 | pd->bUnitID = 2; |
913 | pd->bSourceID = 1; |
914 | pd->wMaxMultiplier = cpu_to_le16(16*1024); |
915 | pd->bControlSize = 2; |
916 | pd->bmControls[0] = 1; |
917 | pd->bmControls[1] = 0; |
918 | pd->iProcessing = 0; |
919 | pd->bmVideoStandards = 0; |
920 | |
921 | od = &opts->uvc_output_terminal; |
922 | od->bLength = UVC_DT_OUTPUT_TERMINAL_SIZE; |
923 | od->bDescriptorType = USB_DT_CS_INTERFACE; |
924 | od->bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL; |
925 | od->bTerminalID = 3; |
926 | od->wTerminalType = cpu_to_le16(0x0101); |
927 | od->bAssocTerminal = 0; |
928 | od->bSourceID = 2; |
929 | od->iTerminal = 0; |
930 | |
931 | /* |
932 | * With the ability to add XUs to the UVC function graph, we need to be |
933 | * able to allocate unique unit IDs to them. The IDs are 1-based, with |
934 | * the CT, PU and OT above consuming the first 3. |
935 | */ |
936 | opts->last_unit_id = 3; |
937 | |
938 | /* Prepare fs control class descriptors for configfs-based gadgets */ |
939 | ctl_cls = opts->uvc_fs_control_cls; |
940 | ctl_cls[0] = NULL; /* assigned elsewhere by configfs */ |
941 | ctl_cls[1] = (struct uvc_descriptor_header *)cd; |
942 | ctl_cls[2] = (struct uvc_descriptor_header *)pd; |
943 | ctl_cls[3] = (struct uvc_descriptor_header *)od; |
944 | ctl_cls[4] = NULL; /* NULL-terminate */ |
945 | opts->fs_control = |
946 | (const struct uvc_descriptor_header * const *)ctl_cls; |
947 | |
948 | /* Prepare hs control class descriptors for configfs-based gadgets */ |
949 | ctl_cls = opts->uvc_ss_control_cls; |
950 | ctl_cls[0] = NULL; /* assigned elsewhere by configfs */ |
951 | ctl_cls[1] = (struct uvc_descriptor_header *)cd; |
952 | ctl_cls[2] = (struct uvc_descriptor_header *)pd; |
953 | ctl_cls[3] = (struct uvc_descriptor_header *)od; |
954 | ctl_cls[4] = NULL; /* NULL-terminate */ |
955 | opts->ss_control = |
956 | (const struct uvc_descriptor_header * const *)ctl_cls; |
957 | |
958 | INIT_LIST_HEAD(list: &opts->extension_units); |
959 | |
960 | opts->streaming_interval = 1; |
961 | opts->streaming_maxpacket = 1024; |
962 | snprintf(buf: opts->function_name, size: sizeof(opts->function_name), fmt: "UVC Camera" ); |
963 | |
964 | ret = uvcg_attach_configfs(opts); |
965 | if (ret < 0) { |
966 | kfree(objp: opts); |
967 | return ERR_PTR(error: ret); |
968 | } |
969 | |
970 | return &opts->func_inst; |
971 | } |
972 | |
973 | static void uvc_free(struct usb_function *f) |
974 | { |
975 | struct uvc_device *uvc = to_uvc(f); |
976 | struct f_uvc_opts *opts = container_of(f->fi, struct f_uvc_opts, |
977 | func_inst); |
978 | if (!opts->header) |
979 | config_item_put(&uvc->header->item); |
980 | --opts->refcnt; |
981 | kfree(objp: uvc); |
982 | } |
983 | |
984 | static void uvc_function_unbind(struct usb_configuration *c, |
985 | struct usb_function *f) |
986 | { |
987 | struct usb_composite_dev *cdev = c->cdev; |
988 | struct uvc_device *uvc = to_uvc(f); |
989 | struct uvc_video *video = &uvc->video; |
990 | long wait_ret = 1; |
991 | |
992 | uvcg_info(f, "%s()\n" , __func__); |
993 | |
994 | if (video->async_wq) |
995 | destroy_workqueue(wq: video->async_wq); |
996 | |
997 | /* |
998 | * If we know we're connected via v4l2, then there should be a cleanup |
999 | * of the device from userspace either via UVC_EVENT_DISCONNECT or |
1000 | * though the video device removal uevent. Allow some time for the |
1001 | * application to close out before things get deleted. |
1002 | */ |
1003 | if (uvc->func_connected) { |
1004 | uvcg_dbg(f, "waiting for clean disconnect\n" ); |
1005 | wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, |
1006 | uvc->func_connected == false, msecs_to_jiffies(500)); |
1007 | uvcg_dbg(f, "done waiting with ret: %ld\n" , wait_ret); |
1008 | } |
1009 | |
1010 | device_remove_file(dev: &uvc->vdev.dev, attr: &dev_attr_function_name); |
1011 | video_unregister_device(vdev: &uvc->vdev); |
1012 | v4l2_device_unregister(v4l2_dev: &uvc->v4l2_dev); |
1013 | |
1014 | if (uvc->func_connected) { |
1015 | /* |
1016 | * Wait for the release to occur to ensure there are no longer any |
1017 | * pending operations that may cause panics when resources are cleaned |
1018 | * up. |
1019 | */ |
1020 | uvcg_warn(f, "%s no clean disconnect, wait for release\n" , __func__); |
1021 | wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, |
1022 | uvc->func_connected == false, msecs_to_jiffies(1000)); |
1023 | uvcg_dbg(f, "done waiting for release with ret: %ld\n" , wait_ret); |
1024 | } |
1025 | |
1026 | usb_ep_free_request(ep: cdev->gadget->ep0, req: uvc->control_req); |
1027 | kfree(objp: uvc->control_buf); |
1028 | |
1029 | usb_free_all_descriptors(f); |
1030 | } |
1031 | |
1032 | static struct usb_function *uvc_alloc(struct usb_function_instance *fi) |
1033 | { |
1034 | struct uvc_device *uvc; |
1035 | struct f_uvc_opts *opts; |
1036 | struct uvc_descriptor_header **strm_cls; |
1037 | struct config_item *streaming, *, *h; |
1038 | |
1039 | uvc = kzalloc(size: sizeof(*uvc), GFP_KERNEL); |
1040 | if (uvc == NULL) |
1041 | return ERR_PTR(error: -ENOMEM); |
1042 | |
1043 | mutex_init(&uvc->video.mutex); |
1044 | uvc->state = UVC_STATE_DISCONNECTED; |
1045 | init_waitqueue_head(&uvc->func_connected_queue); |
1046 | opts = fi_to_f_uvc_opts(fi); |
1047 | |
1048 | mutex_lock(&opts->lock); |
1049 | if (opts->uvc_fs_streaming_cls) { |
1050 | strm_cls = opts->uvc_fs_streaming_cls; |
1051 | opts->fs_streaming = |
1052 | (const struct uvc_descriptor_header * const *)strm_cls; |
1053 | } |
1054 | if (opts->uvc_hs_streaming_cls) { |
1055 | strm_cls = opts->uvc_hs_streaming_cls; |
1056 | opts->hs_streaming = |
1057 | (const struct uvc_descriptor_header * const *)strm_cls; |
1058 | } |
1059 | if (opts->uvc_ss_streaming_cls) { |
1060 | strm_cls = opts->uvc_ss_streaming_cls; |
1061 | opts->ss_streaming = |
1062 | (const struct uvc_descriptor_header * const *)strm_cls; |
1063 | } |
1064 | |
1065 | uvc->desc.fs_control = opts->fs_control; |
1066 | uvc->desc.ss_control = opts->ss_control; |
1067 | uvc->desc.fs_streaming = opts->fs_streaming; |
1068 | uvc->desc.hs_streaming = opts->hs_streaming; |
1069 | uvc->desc.ss_streaming = opts->ss_streaming; |
1070 | |
1071 | if (opts->header) { |
1072 | uvc->header = opts->header; |
1073 | } else { |
1074 | streaming = config_group_find_item(&opts->func_inst.group, "streaming" ); |
1075 | if (!streaming) |
1076 | goto err_config; |
1077 | |
1078 | header = config_group_find_item(to_config_group(item: streaming), "header" ); |
1079 | config_item_put(streaming); |
1080 | if (!header) |
1081 | goto err_config; |
1082 | |
1083 | h = config_group_find_item(to_config_group(item: header), "h" ); |
1084 | config_item_put(header); |
1085 | if (!h) |
1086 | goto err_config; |
1087 | |
1088 | uvc->header = to_uvcg_streaming_header(item: h); |
1089 | if (!uvc->header->linked) { |
1090 | mutex_unlock(lock: &opts->lock); |
1091 | kfree(objp: uvc); |
1092 | return ERR_PTR(error: -EBUSY); |
1093 | } |
1094 | } |
1095 | |
1096 | uvc->desc.extension_units = &opts->extension_units; |
1097 | |
1098 | ++opts->refcnt; |
1099 | mutex_unlock(lock: &opts->lock); |
1100 | |
1101 | /* Register the function. */ |
1102 | uvc->func.name = "uvc" ; |
1103 | uvc->func.bind = uvc_function_bind; |
1104 | uvc->func.unbind = uvc_function_unbind; |
1105 | uvc->func.get_alt = uvc_function_get_alt; |
1106 | uvc->func.set_alt = uvc_function_set_alt; |
1107 | uvc->func.disable = uvc_function_disable; |
1108 | uvc->func.setup = uvc_function_setup; |
1109 | uvc->func.free_func = uvc_free; |
1110 | uvc->func.bind_deactivated = true; |
1111 | |
1112 | return &uvc->func; |
1113 | |
1114 | err_config: |
1115 | mutex_unlock(lock: &opts->lock); |
1116 | kfree(objp: uvc); |
1117 | return ERR_PTR(error: -ENOENT); |
1118 | } |
1119 | |
1120 | DECLARE_USB_FUNCTION_INIT(uvc, uvc_alloc_inst, uvc_alloc); |
1121 | MODULE_LICENSE("GPL" ); |
1122 | MODULE_AUTHOR("Laurent Pinchart" ); |
1123 | |