Commit | Line | Data |
---|---|---|
5fd54ace | 1 | // SPDX-License-Identifier: GPL-2.0+ |
cdda479f LP |
2 | /* |
3 | * uvc_gadget.c -- USB Video Class Gadget driver | |
4 | * | |
5 | * Copyright (C) 2009-2010 | |
6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) | |
cdda479f LP |
7 | */ |
8 | ||
cdda479f LP |
9 | #include <linux/device.h> |
10 | #include <linux/errno.h> | |
11 | #include <linux/fs.h> | |
284eb166 | 12 | #include <linux/kernel.h> |
cdda479f | 13 | #include <linux/list.h> |
284eb166 | 14 | #include <linux/module.h> |
cdda479f | 15 | #include <linux/mutex.h> |
4d2079c1 | 16 | #include <linux/string.h> |
cdda479f LP |
17 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb/gadget.h> | |
284eb166 | 19 | #include <linux/usb/g_uvc.h> |
cdda479f LP |
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" | |
46919a23 | 28 | #include "uvc_configfs.h" |
3a83c16e AP |
29 | #include "uvc_v4l2.h" |
30 | #include "uvc_video.h" | |
cdda479f | 31 | |
5d9955f8 | 32 | unsigned int uvc_gadget_trace_param; |
20970d82 LP |
33 | module_param_named(trace, uvc_gadget_trace_param, uint, 0644); |
34 | MODULE_PARM_DESC(trace, "Trace level bitmask"); | |
fbcaba0e | 35 | |
cdda479f LP |
36 | /* -------------------------------------------------------------------------- |
37 | * Function descriptors | |
38 | */ | |
39 | ||
40 | /* string IDs are assigned dynamically */ | |
41 | ||
cdda479f | 42 | static struct usb_string uvc_en_us_strings[] = { |
324e4f85 | 43 | /* [UVC_STRING_CONTROL_IDX].s = DYNAMIC, */ |
cdda479f LP |
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 | ||
912ca429 | 61 | #define UVC_STATUS_MAX_PACKET_SIZE 16 /* 16 bytes status */ |
57976636 | 62 | |
6d11ed76 | 63 | static struct usb_interface_assoc_descriptor uvc_iad = { |
bbafc0cb | 64 | .bLength = sizeof(uvc_iad), |
cdda479f LP |
65 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
66 | .bFirstInterface = 0, | |
67 | .bInterfaceCount = 2, | |
68 | .bFunctionClass = USB_CLASS_VIDEO, | |
bbafc0cb | 69 | .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, |
cdda479f LP |
70 | .bFunctionProtocol = 0x00, |
71 | .iFunction = 0, | |
72 | }; | |
73 | ||
6d11ed76 | 74 | static struct usb_interface_descriptor uvc_control_intf = { |
cdda479f LP |
75 | .bLength = USB_DT_INTERFACE_SIZE, |
76 | .bDescriptorType = USB_DT_INTERFACE, | |
77 | .bInterfaceNumber = UVC_INTF_VIDEO_CONTROL, | |
78 | .bAlternateSetting = 0, | |
130c4dcb | 79 | .bNumEndpoints = 0, |
cdda479f | 80 | .bInterfaceClass = USB_CLASS_VIDEO, |
bbafc0cb | 81 | .bInterfaceSubClass = UVC_SC_VIDEOCONTROL, |
cdda479f LP |
82 | .bInterfaceProtocol = 0x00, |
83 | .iInterface = 0, | |
84 | }; | |
85 | ||
3078212c | 86 | static struct usb_endpoint_descriptor uvc_interrupt_ep = { |
cdda479f LP |
87 | .bLength = USB_DT_ENDPOINT_SIZE, |
88 | .bDescriptorType = USB_DT_ENDPOINT, | |
89 | .bEndpointAddress = USB_DIR_IN, | |
90 | .bmAttributes = USB_ENDPOINT_XFER_INT, | |
912ca429 | 91 | .wMaxPacketSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
cdda479f LP |
92 | .bInterval = 8, |
93 | }; | |
94 | ||
3078212c DS |
95 | static struct usb_ss_ep_comp_descriptor uvc_ss_interrupt_comp = { |
96 | .bLength = sizeof(uvc_ss_interrupt_comp), | |
48eee0b4 LP |
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 | ||
3078212c | 104 | static struct uvc_control_endpoint_descriptor uvc_interrupt_cs_ep = { |
cdda479f LP |
105 | .bLength = UVC_DT_CONTROL_ENDPOINT_SIZE, |
106 | .bDescriptorType = USB_DT_CS_ENDPOINT, | |
107 | .bDescriptorSubType = UVC_EP_INTERRUPT, | |
912ca429 | 108 | .wMaxTransferSize = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE), |
cdda479f LP |
109 | }; |
110 | ||
6d11ed76 | 111 | static struct usb_interface_descriptor uvc_streaming_intf_alt0 = { |
cdda479f LP |
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, | |
bbafc0cb | 118 | .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, |
cdda479f LP |
119 | .bInterfaceProtocol = 0x00, |
120 | .iInterface = 0, | |
121 | }; | |
122 | ||
6d11ed76 | 123 | static struct usb_interface_descriptor uvc_streaming_intf_alt1 = { |
cdda479f LP |
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, | |
bbafc0cb | 130 | .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, |
cdda479f LP |
131 | .bInterfaceProtocol = 0x00, |
132 | .iInterface = 0, | |
133 | }; | |
134 | ||
6d11ed76 | 135 | static struct usb_endpoint_descriptor uvc_fs_streaming_ep = { |
cdda479f LP |
136 | .bLength = USB_DT_ENDPOINT_SIZE, |
137 | .bDescriptorType = USB_DT_ENDPOINT, | |
138 | .bEndpointAddress = USB_DIR_IN, | |
609a0532 BS |
139 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
140 | | USB_ENDPOINT_XFER_ISOC, | |
c5d337a3 LP |
141 | /* |
142 | * The wMaxPacketSize and bInterval values will be initialized from | |
20777dde LP |
143 | * module parameters. |
144 | */ | |
cdda479f LP |
145 | }; |
146 | ||
6d11ed76 | 147 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep = { |
fbcaba0e BS |
148 | .bLength = USB_DT_ENDPOINT_SIZE, |
149 | .bDescriptorType = USB_DT_ENDPOINT, | |
150 | .bEndpointAddress = USB_DIR_IN, | |
609a0532 BS |
151 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
152 | | USB_ENDPOINT_XFER_ISOC, | |
c5d337a3 LP |
153 | /* |
154 | * The wMaxPacketSize and bInterval values will be initialized from | |
20777dde LP |
155 | * module parameters. |
156 | */ | |
fbcaba0e BS |
157 | }; |
158 | ||
6d11ed76 | 159 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep = { |
ee6a4d87 LP |
160 | .bLength = USB_DT_ENDPOINT_SIZE, |
161 | .bDescriptorType = USB_DT_ENDPOINT, | |
fbcaba0e | 162 | |
ee6a4d87 | 163 | .bEndpointAddress = USB_DIR_IN, |
609a0532 BS |
164 | .bmAttributes = USB_ENDPOINT_SYNC_ASYNC |
165 | | USB_ENDPOINT_XFER_ISOC, | |
c5d337a3 LP |
166 | /* |
167 | * The wMaxPacketSize and bInterval values will be initialized from | |
20777dde LP |
168 | * module parameters. |
169 | */ | |
fbcaba0e BS |
170 | }; |
171 | ||
6d11ed76 | 172 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = { |
ee6a4d87 LP |
173 | .bLength = sizeof(uvc_ss_streaming_comp), |
174 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
c5d337a3 LP |
175 | /* |
176 | * The bMaxBurst, bmAttributes and wBytesPerInterval values will be | |
dbbafe66 LP |
177 | * initialized from module parameters. |
178 | */ | |
fbcaba0e BS |
179 | }; |
180 | ||
cdda479f LP |
181 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { |
182 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, | |
fbcaba0e | 183 | (struct usb_descriptor_header *) &uvc_fs_streaming_ep, |
cdda479f LP |
184 | NULL, |
185 | }; | |
186 | ||
187 | static const struct usb_descriptor_header * const uvc_hs_streaming[] = { | |
188 | (struct usb_descriptor_header *) &uvc_streaming_intf_alt1, | |
fbcaba0e BS |
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, | |
cdda479f LP |
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; | |
4c92670b SH |
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); | |
dbe98b30 | 219 | v4l2_event_queue(&uvc->vdev, &v4l2_event); |
cdda479f LP |
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; | |
d182bf15 MG |
229 | unsigned int interface = le16_to_cpu(ctrl->wIndex) & 0xff; |
230 | struct usb_ctrlrequest *mctrl; | |
cdda479f | 231 | |
cdda479f | 232 | if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { |
dc0f755b | 233 | uvcg_info(f, "invalid request type\n"); |
cdda479f LP |
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 | ||
c5d337a3 LP |
241 | /* |
242 | * Tell the complete callback to generate an event for the next request | |
26a029f2 LP |
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 | ||
cdda479f LP |
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)); | |
d182bf15 MG |
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 | ||
dbe98b30 | 261 | v4l2_event_queue(&uvc->vdev, &v4l2_event); |
cdda479f LP |
262 | |
263 | return 0; | |
264 | } | |
265 | ||
991544dc | 266 | void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep) |
41837c35 BS |
267 | { |
268 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | |
269 | ||
991544dc AR |
270 | if (disable_ep && uvc->video.ep) |
271 | usb_ep_disable(uvc->video.ep); | |
272 | ||
41837c35 BS |
273 | usb_composite_setup_continue(cdev); |
274 | } | |
275 | ||
cdda479f LP |
276 | static int |
277 | uvc_function_get_alt(struct usb_function *f, unsigned interface) | |
278 | { | |
279 | struct uvc_device *uvc = to_uvc(f); | |
280 | ||
dc0f755b | 281 | uvcg_info(f, "%s(%u)\n", __func__, interface); |
cdda479f LP |
282 | |
283 | if (interface == uvc->control_intf) | |
284 | return 0; | |
285 | else if (interface != uvc->streaming_intf) | |
286 | return -EINVAL; | |
287 | else | |
d62bf8c1 | 288 | return uvc->video.ep->enabled ? 1 : 0; |
cdda479f LP |
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); | |
c92bae75 | 295 | struct usb_composite_dev *cdev = f->config->cdev; |
cdda479f LP |
296 | struct v4l2_event v4l2_event; |
297 | struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; | |
fbcaba0e | 298 | int ret; |
cdda479f | 299 | |
dc0f755b | 300 | uvcg_info(f, "%s(%u, %u)\n", __func__, interface, alt); |
cdda479f LP |
301 | |
302 | if (interface == uvc->control_intf) { | |
303 | if (alt) | |
304 | return -EINVAL; | |
305 | ||
130c4dcb DS |
306 | if (uvc->enable_interrupt_ep) { |
307 | uvcg_info(f, "reset UVC interrupt endpoint\n"); | |
308 | usb_ep_disable(uvc->interrupt_ep); | |
62e37078 | 309 | |
130c4dcb DS |
310 | if (!uvc->interrupt_ep->desc) |
311 | if (config_ep_by_speed(cdev->gadget, f, | |
312 | uvc->interrupt_ep)) | |
313 | return -EINVAL; | |
62e37078 | 314 | |
130c4dcb DS |
315 | usb_ep_enable(uvc->interrupt_ep); |
316 | } | |
62e37078 | 317 | |
cdda479f LP |
318 | if (uvc->state == UVC_STATE_DISCONNECTED) { |
319 | memset(&v4l2_event, 0, sizeof(v4l2_event)); | |
320 | v4l2_event.type = UVC_EVENT_CONNECT; | |
c92bae75 | 321 | uvc_event->speed = cdev->gadget->speed; |
dbe98b30 | 322 | v4l2_event_queue(&uvc->vdev, &v4l2_event); |
cdda479f LP |
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 | ||
cdda479f LP |
343 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
344 | v4l2_event.type = UVC_EVENT_STREAMOFF; | |
dbe98b30 | 345 | v4l2_event_queue(&uvc->vdev, &v4l2_event); |
cdda479f | 346 | |
991544dc | 347 | return USB_GADGET_DELAYED_STATUS; |
cdda479f LP |
348 | |
349 | case 1: | |
350 | if (uvc->state != UVC_STATE_CONNECTED) | |
351 | return 0; | |
352 | ||
c92bae75 FB |
353 | if (!uvc->video.ep) |
354 | return -EINVAL; | |
355 | ||
dc0f755b | 356 | uvcg_info(f, "reset UVC\n"); |
d62bf8c1 | 357 | usb_ep_disable(uvc->video.ep); |
cdda479f | 358 | |
c92bae75 FB |
359 | ret = config_ep_by_speed(f->config->cdev->gadget, |
360 | &(uvc->func), uvc->video.ep); | |
361 | if (ret) | |
362 | return ret; | |
363 | usb_ep_enable(uvc->video.ep); | |
c92bae75 | 364 | |
cdda479f LP |
365 | memset(&v4l2_event, 0, sizeof(v4l2_event)); |
366 | v4l2_event.type = UVC_EVENT_STREAMON; | |
dbe98b30 | 367 | v4l2_event_queue(&uvc->vdev, &v4l2_event); |
41837c35 | 368 | return USB_GADGET_DELAYED_STATUS; |
cdda479f LP |
369 | |
370 | default: | |
371 | return -EINVAL; | |
372 | } | |
cdda479f LP |
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 | ||
dc0f755b | 381 | uvcg_info(f, "%s()\n", __func__); |
cdda479f LP |
382 | |
383 | memset(&v4l2_event, 0, sizeof(v4l2_event)); | |
384 | v4l2_event.type = UVC_EVENT_DISCONNECT; | |
dbe98b30 | 385 | v4l2_event_queue(&uvc->vdev, &v4l2_event); |
cdda479f LP |
386 | |
387 | uvc->state = UVC_STATE_DISCONNECTED; | |
e3122f5f | 388 | |
d62bf8c1 | 389 | usb_ep_disable(uvc->video.ep); |
130c4dcb DS |
390 | if (uvc->enable_interrupt_ep) |
391 | usb_ep_disable(uvc->interrupt_ep); | |
cdda479f LP |
392 | } |
393 | ||
394 | /* -------------------------------------------------------------------------- | |
395 | * Connection / disconnection | |
396 | */ | |
397 | ||
398 | void | |
399 | uvc_function_connect(struct uvc_device *uvc) | |
400 | { | |
cdda479f LP |
401 | int ret; |
402 | ||
403 | if ((ret = usb_function_activate(&uvc->func)) < 0) | |
dc0f755b | 404 | uvcg_info(&uvc->func, "UVC connect failed with %d\n", ret); |
cdda479f LP |
405 | } |
406 | ||
407 | void | |
408 | uvc_function_disconnect(struct uvc_device *uvc) | |
409 | { | |
cdda479f LP |
410 | int ret; |
411 | ||
412 | if ((ret = usb_function_deactivate(&uvc->func)) < 0) | |
dc0f755b | 413 | uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret); |
cdda479f LP |
414 | } |
415 | ||
416 | /* -------------------------------------------------------------------------- | |
417 | * USB probe and disconnect | |
418 | */ | |
419 | ||
d7af78b9 KB |
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, "%s\n", uvc->func.fi->group.cg_item.ci_name); | |
426 | } | |
427 | ||
428 | static DEVICE_ATTR_RO(function_name); | |
429 | ||
cdda479f LP |
430 | static int |
431 | uvc_register_video(struct uvc_device *uvc) | |
432 | { | |
433 | struct usb_composite_dev *cdev = uvc->func.config->cdev; | |
d7af78b9 | 434 | int ret; |
cdda479f LP |
435 | |
436 | /* TODO reference counting. */ | |
a15e17ac | 437 | memset(&uvc->vdev, 0, sizeof(uvc->vdev)); |
dbe98b30 | 438 | uvc->vdev.v4l2_dev = &uvc->v4l2_dev; |
b9b82d3d | 439 | uvc->vdev.v4l2_dev->dev = &cdev->gadget->dev; |
dbe98b30 HV |
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; | |
1397e3ec | 445 | uvc->vdev.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; |
b7db5733 | 446 | strscpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name)); |
dbe98b30 HV |
447 | |
448 | video_set_drvdata(&uvc->vdev, uvc); | |
449 | ||
0ceba550 | 450 | ret = video_register_device(&uvc->vdev, VFL_TYPE_VIDEO, -1); |
d7af78b9 KB |
451 | if (ret < 0) |
452 | return ret; | |
453 | ||
454 | ret = device_create_file(&uvc->vdev.dev, &dev_attr_function_name); | |
455 | if (ret < 0) { | |
456 | video_unregister_device(&uvc->vdev); | |
457 | return ret; | |
458 | } | |
459 | ||
460 | return 0; | |
cdda479f LP |
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 | ||
a7289452 DS |
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 | ||
6d11ed76 | 499 | static struct usb_descriptor_header ** |
cdda479f LP |
500 | uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) |
501 | { | |
502 | struct uvc_input_header_descriptor *uvc_streaming_header; | |
503 | struct uvc_header_descriptor *uvc_control_header; | |
fbcaba0e | 504 | const struct uvc_descriptor_header * const *uvc_control_desc; |
cdda479f LP |
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; | |
a7289452 | 510 | struct uvcg_extension *xu; |
cdda479f LP |
511 | unsigned int control_size; |
512 | unsigned int streaming_size; | |
513 | unsigned int n_desc; | |
514 | unsigned int bytes; | |
515 | void *mem; | |
516 | ||
fbcaba0e | 517 | switch (speed) { |
c70793fb | 518 | case USB_SPEED_SUPER_PLUS: |
fbcaba0e BS |
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; | |
fbcaba0e BS |
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; | |
fbcaba0e BS |
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; | |
fbcaba0e BS |
536 | break; |
537 | } | |
cdda479f | 538 | |
6c25955e AP |
539 | if (!uvc_control_desc || !uvc_streaming_cls) |
540 | return ERR_PTR(-ENODEV); | |
541 | ||
c5d337a3 LP |
542 | /* |
543 | * Descriptors layout | |
cdda479f LP |
544 | * |
545 | * uvc_iad | |
546 | * uvc_control_intf | |
547 | * Class-specific UVC control descriptors | |
3078212c DS |
548 | * uvc_interrupt_ep |
549 | * uvc_interrupt_cs_ep | |
550 | * uvc_ss_interrupt_comp (for SS only) | |
cdda479f LP |
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 | |
cdda479f | 560 | + uvc_streaming_intf_alt0.bLength; |
cdda479f | 561 | |
130c4dcb DS |
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 | ||
c70793fb SW |
567 | if (speed == USB_SPEED_SUPER || |
568 | speed == USB_SPEED_SUPER_PLUS) { | |
130c4dcb DS |
569 | bytes += uvc_ss_interrupt_comp.bLength; |
570 | n_desc += 1; | |
571 | } | |
fbcaba0e BS |
572 | } |
573 | ||
574 | for (src = (const struct usb_descriptor_header **)uvc_control_desc; | |
ee6a4d87 | 575 | *src; ++src) { |
cdda479f LP |
576 | control_size += (*src)->bLength; |
577 | bytes += (*src)->bLength; | |
578 | n_desc++; | |
579 | } | |
a7289452 DS |
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 | ||
fbcaba0e | 587 | for (src = (const struct usb_descriptor_header **)uvc_streaming_cls; |
ee6a4d87 | 588 | *src; ++src) { |
cdda479f LP |
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((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, | |
fbcaba0e | 612 | (const struct usb_descriptor_header **)uvc_control_desc); |
a7289452 DS |
613 | |
614 | list_for_each_entry(xu, uvc->desc.extension_units, list) | |
615 | UVC_COPY_XU_DESCRIPTOR(mem, dst, &xu->desc); | |
616 | ||
cdda479f LP |
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 | ||
130c4dcb DS |
621 | if (uvc->enable_interrupt_ep) { |
622 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep); | |
c70793fb SW |
623 | if (speed == USB_SPEED_SUPER || |
624 | speed == USB_SPEED_SUPER_PLUS) | |
130c4dcb DS |
625 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_interrupt_comp); |
626 | ||
627 | UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_cs_ep); | |
628 | } | |
fbcaba0e | 629 | |
cdda479f LP |
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); | |
0485ec0d | 636 | uvc_streaming_header->bEndpointAddress = uvc->video.ep->address; |
cdda479f LP |
637 | |
638 | UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std); | |
639 | ||
640 | *dst = NULL; | |
641 | return hdr; | |
642 | } | |
643 | ||
6d11ed76 | 644 | static int |
cdda479f LP |
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); | |
9963f744 | 649 | struct uvcg_extension *xu; |
13443799 | 650 | struct usb_string *us; |
20777dde LP |
651 | unsigned int max_packet_mult; |
652 | unsigned int max_packet_size; | |
cdda479f | 653 | struct usb_ep *ep; |
6d11ed76 | 654 | struct f_uvc_opts *opts; |
cdda479f LP |
655 | int ret = -EINVAL; |
656 | ||
dc0f755b | 657 | uvcg_info(f, "%s()\n", __func__); |
cdda479f | 658 | |
bbea6de1 | 659 | opts = fi_to_f_uvc_opts(f->fi); |
c5d337a3 | 660 | /* Sanity check the streaming endpoint module parameters. */ |
6d11ed76 AP |
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 | ||
16bb05d9 RQ |
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); | |
dc0f755b LP |
669 | uvcg_info(f, "overriding streaming_maxpacket to %d\n", |
670 | opts->streaming_maxpacket); | |
16bb05d9 RQ |
671 | } |
672 | ||
c5d337a3 LP |
673 | /* |
674 | * Fill in the FS/HS/SS Video Streaming specific descriptors from the | |
6d11ed76 AP |
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 = | |
e102609f | 692 | cpu_to_le16(min(opts->streaming_maxpacket, 1023U)); |
6d11ed76 AP |
693 | uvc_fs_streaming_ep.bInterval = opts->streaming_interval; |
694 | ||
e102609f LP |
695 | uvc_hs_streaming_ep.wMaxPacketSize = |
696 | cpu_to_le16(max_packet_size | ((max_packet_mult - 1) << 11)); | |
26adde04 PL |
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; | |
6d11ed76 | 703 | |
e102609f | 704 | uvc_ss_streaming_ep.wMaxPacketSize = cpu_to_le16(max_packet_size); |
6d11ed76 AP |
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 = | |
e102609f | 709 | cpu_to_le16(max_packet_size * max_packet_mult * |
09424c50 | 710 | (opts->streaming_maxburst + 1)); |
20777dde | 711 | |
cdda479f | 712 | /* Allocate endpoints. */ |
130c4dcb DS |
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; | |
cdda479f | 721 | } |
130c4dcb | 722 | uvc->enable_interrupt_ep = opts->enable_interrupt_ep; |
cdda479f | 723 | |
895ee5ae FL |
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(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(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 | ||
cdda479f | 740 | if (!ep) { |
dc0f755b | 741 | uvcg_info(f, "Unable to allocate streaming EP\n"); |
cdda479f LP |
742 | goto error; |
743 | } | |
744 | uvc->video.ep = ep; | |
cdda479f | 745 | |
895ee5ae | 746 | uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
0485ec0d LP |
747 | uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address; |
748 | uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address; | |
20777dde | 749 | |
9963f744 DS |
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 | ||
cf13d6e4 DS |
758 | /* |
759 | * We attach the hard-coded defaults incase the user does not provide | |
760 | * any more appropriate strings through configfs. | |
761 | */ | |
324e4f85 | 762 | uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->function_name; |
13443799 AP |
763 | us = usb_gstrings_attach(cdev, uvc_function_strings, |
764 | ARRAY_SIZE(uvc_en_us_strings)); | |
765 | if (IS_ERR(us)) { | |
766 | ret = PTR_ERR(us); | |
767 | goto error; | |
6d11ed76 | 768 | } |
cf13d6e4 DS |
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; | |
6d11ed76 | 778 | |
cdda479f LP |
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; | |
bf715448 | 785 | opts->control_interface = ret; |
cdda479f LP |
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; | |
bf715448 | 792 | opts->streaming_interface = ret; |
cdda479f | 793 | |
10287bae SAS |
794 | /* Copy descriptors */ |
795 | f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL); | |
6c25955e AP |
796 | if (IS_ERR(f->fs_descriptors)) { |
797 | ret = PTR_ERR(f->fs_descriptors); | |
798 | f->fs_descriptors = NULL; | |
799 | goto error; | |
800 | } | |
46decc82 LY |
801 | |
802 | f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH); | |
803 | if (IS_ERR(f->hs_descriptors)) { | |
804 | ret = PTR_ERR(f->hs_descriptors); | |
805 | f->hs_descriptors = NULL; | |
806 | goto error; | |
6c25955e | 807 | } |
46decc82 LY |
808 | |
809 | f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); | |
810 | if (IS_ERR(f->ss_descriptors)) { | |
811 | ret = PTR_ERR(f->ss_descriptors); | |
812 | f->ss_descriptors = NULL; | |
813 | goto error; | |
6c25955e | 814 | } |
cdda479f | 815 | |
c70793fb SW |
816 | f->ssp_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER_PLUS); |
817 | if (IS_ERR(f->ssp_descriptors)) { | |
818 | ret = PTR_ERR(f->ssp_descriptors); | |
819 | f->ssp_descriptors = NULL; | |
820 | goto error; | |
821 | } | |
822 | ||
cdda479f LP |
823 | /* Preallocate control endpoint request. */ |
824 | uvc->control_req = usb_ep_alloc_request(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 | ||
b60f9aa1 | 835 | if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { |
dc0f755b | 836 | uvcg_err(f, "failed to register V4L2 device\n"); |
b60f9aa1 HV |
837 | goto error; |
838 | } | |
839 | ||
cdda479f | 840 | /* Initialise video. */ |
dc0f755b | 841 | ret = uvcg_video_init(&uvc->video, uvc); |
cdda479f | 842 | if (ret < 0) |
f0c48566 | 843 | goto v4l2_error; |
cdda479f LP |
844 | |
845 | /* Register a V4L2 device. */ | |
846 | ret = uvc_register_video(uvc); | |
847 | if (ret < 0) { | |
dc0f755b | 848 | uvcg_err(f, "failed to register video device\n"); |
f0c48566 | 849 | goto v4l2_error; |
cdda479f LP |
850 | } |
851 | ||
852 | return 0; | |
853 | ||
f0c48566 | 854 | v4l2_error: |
b60f9aa1 | 855 | v4l2_device_unregister(&uvc->v4l2_dev); |
f0c48566 | 856 | error: |
e7379857 | 857 | if (uvc->control_req) |
0f9df939 | 858 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
e7379857 | 859 | kfree(uvc->control_buf); |
0f9df939 | 860 | |
10287bae | 861 | usb_free_all_descriptors(f); |
cdda479f LP |
862 | return ret; |
863 | } | |
864 | ||
865 | /* -------------------------------------------------------------------------- | |
866 | * USB gadget function | |
867 | */ | |
868 | ||
6d11ed76 AP |
869 | static void uvc_free_inst(struct usb_function_instance *f) |
870 | { | |
bbea6de1 | 871 | struct f_uvc_opts *opts = fi_to_f_uvc_opts(f); |
6d11ed76 | 872 | |
46919a23 | 873 | mutex_destroy(&opts->lock); |
6d11ed76 AP |
874 | kfree(opts); |
875 | } | |
876 | ||
877 | static struct usb_function_instance *uvc_alloc_inst(void) | |
878 | { | |
879 | struct f_uvc_opts *opts; | |
46919a23 AP |
880 | struct uvc_camera_terminal_descriptor *cd; |
881 | struct uvc_processing_unit_descriptor *pd; | |
882 | struct uvc_output_terminal_descriptor *od; | |
46919a23 | 883 | struct uvc_descriptor_header **ctl_cls; |
efbf0af7 | 884 | int ret; |
6d11ed76 AP |
885 | |
886 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | |
887 | if (!opts) | |
888 | return ERR_PTR(-ENOMEM); | |
889 | opts->func_inst.free_func_inst = uvc_free_inst; | |
46919a23 AP |
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; | |
6a154ec9 | 919 | pd->bmVideoStandards = 0; |
46919a23 AP |
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 | ||
0525210c DS |
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 | ||
46919a23 AP |
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 | ||
0525210c DS |
958 | INIT_LIST_HEAD(&opts->extension_units); |
959 | ||
46919a23 AP |
960 | opts->streaming_interval = 1; |
961 | opts->streaming_maxpacket = 1024; | |
324e4f85 | 962 | snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera"); |
46919a23 | 963 | |
efbf0af7 LP |
964 | ret = uvcg_attach_configfs(opts); |
965 | if (ret < 0) { | |
966 | kfree(opts); | |
967 | return ERR_PTR(ret); | |
968 | } | |
969 | ||
6d11ed76 AP |
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); | |
46919a23 AP |
976 | struct f_uvc_opts *opts = container_of(f->fi, struct f_uvc_opts, |
977 | func_inst); | |
f1fd91a0 AP |
978 | if (!opts->header) |
979 | config_item_put(&uvc->header->item); | |
46919a23 | 980 | --opts->refcnt; |
6d11ed76 AP |
981 | kfree(uvc); |
982 | } | |
983 | ||
e6bab2b6 MT |
984 | static void uvc_function_unbind(struct usb_configuration *c, |
985 | struct usb_function *f) | |
6d11ed76 AP |
986 | { |
987 | struct usb_composite_dev *cdev = c->cdev; | |
988 | struct uvc_device *uvc = to_uvc(f); | |
9b91a652 | 989 | struct uvc_video *video = &uvc->video; |
b81ac439 | 990 | long wait_ret = 1; |
6d11ed76 | 991 | |
e6bab2b6 | 992 | uvcg_info(f, "%s()\n", __func__); |
6d11ed76 | 993 | |
9b91a652 MG |
994 | if (video->async_wq) |
995 | destroy_workqueue(video->async_wq); | |
996 | ||
c5d337a3 LP |
997 | /* |
998 | * If we know we're connected via v4l2, then there should be a cleanup | |
b81ac439 DV |
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 | ||
d7af78b9 | 1010 | device_remove_file(&uvc->vdev.dev, &dev_attr_function_name); |
dbe98b30 | 1011 | video_unregister_device(&uvc->vdev); |
6d11ed76 | 1012 | v4l2_device_unregister(&uvc->v4l2_dev); |
6d11ed76 | 1013 | |
b81ac439 | 1014 | if (uvc->func_connected) { |
c5d337a3 LP |
1015 | /* |
1016 | * Wait for the release to occur to ensure there are no longer any | |
b81ac439 DV |
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 | ||
6d11ed76 AP |
1026 | usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); |
1027 | kfree(uvc->control_buf); | |
1028 | ||
1029 | usb_free_all_descriptors(f); | |
1030 | } | |
1031 | ||
4a6698b8 | 1032 | static struct usb_function *uvc_alloc(struct usb_function_instance *fi) |
6d11ed76 AP |
1033 | { |
1034 | struct uvc_device *uvc; | |
1035 | struct f_uvc_opts *opts; | |
46919a23 | 1036 | struct uvc_descriptor_header **strm_cls; |
588b9e85 | 1037 | struct config_item *streaming, *header, *h; |
6d11ed76 AP |
1038 | |
1039 | uvc = kzalloc(sizeof(*uvc), GFP_KERNEL); | |
1040 | if (uvc == NULL) | |
1041 | return ERR_PTR(-ENOMEM); | |
1042 | ||
d8e96c4b | 1043 | mutex_init(&uvc->video.mutex); |
6d11ed76 | 1044 | uvc->state = UVC_STATE_DISCONNECTED; |
b81ac439 | 1045 | init_waitqueue_head(&uvc->func_connected_queue); |
bbea6de1 | 1046 | opts = fi_to_f_uvc_opts(fi); |
6d11ed76 | 1047 | |
46919a23 AP |
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 | ||
6d11ed76 AP |
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; | |
588b9e85 | 1070 | |
f1fd91a0 AP |
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(streaming), "header"); | |
1079 | config_item_put(streaming); | |
1080 | if (!header) | |
1081 | goto err_config; | |
1082 | ||
1083 | h = config_group_find_item(to_config_group(header), "h"); | |
1084 | config_item_put(header); | |
1085 | if (!h) | |
1086 | goto err_config; | |
1087 | ||
1088 | uvc->header = to_uvcg_streaming_header(h); | |
1089 | if (!uvc->header->linked) { | |
1090 | mutex_unlock(&opts->lock); | |
1091 | kfree(uvc); | |
1092 | return ERR_PTR(-EBUSY); | |
1093 | } | |
588b9e85 MG |
1094 | } |
1095 | ||
a7289452 DS |
1096 | uvc->desc.extension_units = &opts->extension_units; |
1097 | ||
46919a23 AP |
1098 | ++opts->refcnt; |
1099 | mutex_unlock(&opts->lock); | |
6d11ed76 AP |
1100 | |
1101 | /* Register the function. */ | |
1102 | uvc->func.name = "uvc"; | |
6d11ed76 | 1103 | uvc->func.bind = uvc_function_bind; |
e6bab2b6 | 1104 | uvc->func.unbind = uvc_function_unbind; |
6d11ed76 AP |
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; | |
f277bf27 | 1110 | uvc->func.bind_deactivated = true; |
6d11ed76 AP |
1111 | |
1112 | return &uvc->func; | |
588b9e85 MG |
1113 | |
1114 | err_config: | |
1115 | mutex_unlock(&opts->lock); | |
1116 | kfree(uvc); | |
1117 | return ERR_PTR(-ENOENT); | |
6d11ed76 AP |
1118 | } |
1119 | ||
1120 | DECLARE_USB_FUNCTION_INIT(uvc, uvc_alloc_inst, uvc_alloc); | |
1cb9ba5e | 1121 | MODULE_DESCRIPTION("USB Video Class Gadget driver"); |
6d11ed76 AP |
1122 | MODULE_LICENSE("GPL"); |
1123 | MODULE_AUTHOR("Laurent Pinchart"); |