1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * uvc_v4l2.c -- USB Video Class driver - V4L2 API |
4 | * |
5 | * Copyright (C) 2005-2010 |
6 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
7 | */ |
8 | |
9 | #include <linux/bits.h> |
10 | #include <linux/compat.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/list.h> |
13 | #include <linux/module.h> |
14 | #include <linux/slab.h> |
15 | #include <linux/usb.h> |
16 | #include <linux/videodev2.h> |
17 | #include <linux/vmalloc.h> |
18 | #include <linux/mm.h> |
19 | #include <linux/wait.h> |
20 | #include <linux/atomic.h> |
21 | |
22 | #include <media/v4l2-common.h> |
23 | #include <media/v4l2-ctrls.h> |
24 | #include <media/v4l2-event.h> |
25 | #include <media/v4l2-ioctl.h> |
26 | |
27 | #include "uvcvideo.h" |
28 | |
29 | static int uvc_control_add_xu_mapping(struct uvc_video_chain *chain, |
30 | struct uvc_control_mapping *map, |
31 | const struct uvc_xu_control_mapping *xmap) |
32 | { |
33 | unsigned int i; |
34 | size_t size; |
35 | int ret; |
36 | |
37 | /* |
38 | * Prevent excessive memory consumption, as well as integer |
39 | * overflows. |
40 | */ |
41 | if (xmap->menu_count == 0 || |
42 | xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) |
43 | return -EINVAL; |
44 | |
45 | map->menu_names = NULL; |
46 | map->menu_mapping = NULL; |
47 | |
48 | map->menu_mask = GENMASK(xmap->menu_count - 1, 0); |
49 | |
50 | size = xmap->menu_count * sizeof(*map->menu_mapping); |
51 | map->menu_mapping = kzalloc(size, GFP_KERNEL); |
52 | if (!map->menu_mapping) { |
53 | ret = -ENOMEM; |
54 | goto done; |
55 | } |
56 | |
57 | for (i = 0; i < xmap->menu_count ; i++) { |
58 | if (copy_from_user(to: (u32 *)&map->menu_mapping[i], |
59 | from: &xmap->menu_info[i].value, |
60 | n: sizeof(map->menu_mapping[i]))) { |
61 | ret = -EACCES; |
62 | goto done; |
63 | } |
64 | } |
65 | |
66 | /* |
67 | * Always use the standard naming if available, otherwise copy the |
68 | * names supplied by userspace. |
69 | */ |
70 | if (!v4l2_ctrl_get_menu(id: map->id)) { |
71 | size = xmap->menu_count * sizeof(map->menu_names[0]); |
72 | map->menu_names = kzalloc(size, GFP_KERNEL); |
73 | if (!map->menu_names) { |
74 | ret = -ENOMEM; |
75 | goto done; |
76 | } |
77 | |
78 | for (i = 0; i < xmap->menu_count ; i++) { |
79 | /* sizeof(names[i]) - 1: to take care of \0 */ |
80 | if (copy_from_user(to: (char *)map->menu_names[i], |
81 | from: xmap->menu_info[i].name, |
82 | n: sizeof(map->menu_names[i]) - 1)) { |
83 | ret = -EACCES; |
84 | goto done; |
85 | } |
86 | } |
87 | } |
88 | |
89 | ret = uvc_ctrl_add_mapping(chain, mapping: map); |
90 | |
91 | done: |
92 | kfree(objp: map->menu_names); |
93 | map->menu_names = NULL; |
94 | kfree(objp: map->menu_mapping); |
95 | map->menu_mapping = NULL; |
96 | |
97 | return ret; |
98 | } |
99 | |
100 | /* ------------------------------------------------------------------------ |
101 | * UVC ioctls |
102 | */ |
103 | static int uvc_ioctl_xu_ctrl_map(struct uvc_video_chain *chain, |
104 | struct uvc_xu_control_mapping *xmap) |
105 | { |
106 | struct uvc_control_mapping *map; |
107 | int ret; |
108 | |
109 | map = kzalloc(size: sizeof(*map), GFP_KERNEL); |
110 | if (map == NULL) |
111 | return -ENOMEM; |
112 | |
113 | map->id = xmap->id; |
114 | /* Non standard control id. */ |
115 | if (v4l2_ctrl_get_name(id: map->id) == NULL) { |
116 | if (xmap->name[0] == '\0') { |
117 | ret = -EINVAL; |
118 | goto free_map; |
119 | } |
120 | xmap->name[sizeof(xmap->name) - 1] = '\0'; |
121 | map->name = xmap->name; |
122 | } |
123 | memcpy(map->entity, xmap->entity, sizeof(map->entity)); |
124 | map->selector = xmap->selector; |
125 | map->size = xmap->size; |
126 | map->offset = xmap->offset; |
127 | map->v4l2_type = xmap->v4l2_type; |
128 | map->data_type = xmap->data_type; |
129 | |
130 | switch (xmap->v4l2_type) { |
131 | case V4L2_CTRL_TYPE_INTEGER: |
132 | case V4L2_CTRL_TYPE_BOOLEAN: |
133 | case V4L2_CTRL_TYPE_BUTTON: |
134 | ret = uvc_ctrl_add_mapping(chain, mapping: map); |
135 | break; |
136 | |
137 | case V4L2_CTRL_TYPE_MENU: |
138 | ret = uvc_control_add_xu_mapping(chain, map, xmap); |
139 | break; |
140 | |
141 | default: |
142 | uvc_dbg(chain->dev, CONTROL, |
143 | "Unsupported V4L2 control type %u\n" , xmap->v4l2_type); |
144 | ret = -ENOTTY; |
145 | break; |
146 | } |
147 | |
148 | free_map: |
149 | kfree(objp: map); |
150 | |
151 | return ret; |
152 | } |
153 | |
154 | /* ------------------------------------------------------------------------ |
155 | * V4L2 interface |
156 | */ |
157 | |
158 | /* |
159 | * Find the frame interval closest to the requested frame interval for the |
160 | * given frame format and size. This should be done by the device as part of |
161 | * the Video Probe and Commit negotiation, but some hardware don't implement |
162 | * that feature. |
163 | */ |
164 | static u32 uvc_try_frame_interval(const struct uvc_frame *frame, u32 interval) |
165 | { |
166 | unsigned int i; |
167 | |
168 | if (frame->bFrameIntervalType) { |
169 | u32 best = -1, dist; |
170 | |
171 | for (i = 0; i < frame->bFrameIntervalType; ++i) { |
172 | dist = interval > frame->dwFrameInterval[i] |
173 | ? interval - frame->dwFrameInterval[i] |
174 | : frame->dwFrameInterval[i] - interval; |
175 | |
176 | if (dist > best) |
177 | break; |
178 | |
179 | best = dist; |
180 | } |
181 | |
182 | interval = frame->dwFrameInterval[i-1]; |
183 | } else { |
184 | const u32 min = frame->dwFrameInterval[0]; |
185 | const u32 max = frame->dwFrameInterval[1]; |
186 | const u32 step = frame->dwFrameInterval[2]; |
187 | |
188 | interval = min + (interval - min + step/2) / step * step; |
189 | if (interval > max) |
190 | interval = max; |
191 | } |
192 | |
193 | return interval; |
194 | } |
195 | |
196 | static u32 uvc_v4l2_get_bytesperline(const struct uvc_format *format, |
197 | const struct uvc_frame *frame) |
198 | { |
199 | switch (format->fcc) { |
200 | case V4L2_PIX_FMT_NV12: |
201 | case V4L2_PIX_FMT_YVU420: |
202 | case V4L2_PIX_FMT_YUV420: |
203 | case V4L2_PIX_FMT_M420: |
204 | return frame->wWidth; |
205 | |
206 | default: |
207 | return format->bpp * frame->wWidth / 8; |
208 | } |
209 | } |
210 | |
211 | static int uvc_v4l2_try_format(struct uvc_streaming *stream, |
212 | struct v4l2_format *fmt, struct uvc_streaming_control *probe, |
213 | const struct uvc_format **uvc_format, |
214 | const struct uvc_frame **uvc_frame) |
215 | { |
216 | const struct uvc_format *format = NULL; |
217 | const struct uvc_frame *frame = NULL; |
218 | u16 rw, rh; |
219 | unsigned int d, maxd; |
220 | unsigned int i; |
221 | u32 interval; |
222 | int ret = 0; |
223 | u8 *fcc; |
224 | |
225 | if (fmt->type != stream->type) |
226 | return -EINVAL; |
227 | |
228 | fcc = (u8 *)&fmt->fmt.pix.pixelformat; |
229 | uvc_dbg(stream->dev, FORMAT, "Trying format 0x%08x (%c%c%c%c): %ux%u\n" , |
230 | fmt->fmt.pix.pixelformat, |
231 | fcc[0], fcc[1], fcc[2], fcc[3], |
232 | fmt->fmt.pix.width, fmt->fmt.pix.height); |
233 | |
234 | /* |
235 | * Check if the hardware supports the requested format, use the default |
236 | * format otherwise. |
237 | */ |
238 | for (i = 0; i < stream->nformats; ++i) { |
239 | format = &stream->formats[i]; |
240 | if (format->fcc == fmt->fmt.pix.pixelformat) |
241 | break; |
242 | } |
243 | |
244 | if (i == stream->nformats) { |
245 | format = stream->def_format; |
246 | fmt->fmt.pix.pixelformat = format->fcc; |
247 | } |
248 | |
249 | /* |
250 | * Find the closest image size. The distance between image sizes is |
251 | * the size in pixels of the non-overlapping regions between the |
252 | * requested size and the frame-specified size. |
253 | */ |
254 | rw = fmt->fmt.pix.width; |
255 | rh = fmt->fmt.pix.height; |
256 | maxd = (unsigned int)-1; |
257 | |
258 | for (i = 0; i < format->nframes; ++i) { |
259 | u16 w = format->frames[i].wWidth; |
260 | u16 h = format->frames[i].wHeight; |
261 | |
262 | d = min(w, rw) * min(h, rh); |
263 | d = w*h + rw*rh - 2*d; |
264 | if (d < maxd) { |
265 | maxd = d; |
266 | frame = &format->frames[i]; |
267 | } |
268 | |
269 | if (maxd == 0) |
270 | break; |
271 | } |
272 | |
273 | if (frame == NULL) { |
274 | uvc_dbg(stream->dev, FORMAT, "Unsupported size %ux%u\n" , |
275 | fmt->fmt.pix.width, fmt->fmt.pix.height); |
276 | return -EINVAL; |
277 | } |
278 | |
279 | /* Use the default frame interval. */ |
280 | interval = frame->dwDefaultFrameInterval; |
281 | uvc_dbg(stream->dev, FORMAT, |
282 | "Using default frame interval %u.%u us (%u.%u fps)\n" , |
283 | interval / 10, interval % 10, 10000000 / interval, |
284 | (100000000 / interval) % 10); |
285 | |
286 | /* Set the format index, frame index and frame interval. */ |
287 | memset(probe, 0, sizeof(*probe)); |
288 | probe->bmHint = 1; /* dwFrameInterval */ |
289 | probe->bFormatIndex = format->index; |
290 | probe->bFrameIndex = frame->bFrameIndex; |
291 | probe->dwFrameInterval = uvc_try_frame_interval(frame, interval); |
292 | /* |
293 | * Some webcams stall the probe control set request when the |
294 | * dwMaxVideoFrameSize field is set to zero. The UVC specification |
295 | * clearly states that the field is read-only from the host, so this |
296 | * is a webcam bug. Set dwMaxVideoFrameSize to the value reported by |
297 | * the webcam to work around the problem. |
298 | * |
299 | * The workaround could probably be enabled for all webcams, so the |
300 | * quirk can be removed if needed. It's currently useful to detect |
301 | * webcam bugs and fix them before they hit the market (providing |
302 | * developers test their webcams with the Linux driver as well as with |
303 | * the Windows driver). |
304 | */ |
305 | mutex_lock(&stream->mutex); |
306 | if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS) |
307 | probe->dwMaxVideoFrameSize = |
308 | stream->ctrl.dwMaxVideoFrameSize; |
309 | |
310 | /* Probe the device. */ |
311 | ret = uvc_probe_video(stream, probe); |
312 | mutex_unlock(lock: &stream->mutex); |
313 | if (ret < 0) |
314 | return ret; |
315 | |
316 | /* |
317 | * After the probe, update fmt with the values returned from |
318 | * negotiation with the device. Some devices return invalid bFormatIndex |
319 | * and bFrameIndex values, in which case we can only assume they have |
320 | * accepted the requested format as-is. |
321 | */ |
322 | for (i = 0; i < stream->nformats; ++i) { |
323 | if (probe->bFormatIndex == stream->formats[i].index) { |
324 | format = &stream->formats[i]; |
325 | break; |
326 | } |
327 | } |
328 | |
329 | if (i == stream->nformats) |
330 | uvc_dbg(stream->dev, FORMAT, |
331 | "Unknown bFormatIndex %u, using default\n" , |
332 | probe->bFormatIndex); |
333 | |
334 | for (i = 0; i < format->nframes; ++i) { |
335 | if (probe->bFrameIndex == format->frames[i].bFrameIndex) { |
336 | frame = &format->frames[i]; |
337 | break; |
338 | } |
339 | } |
340 | |
341 | if (i == format->nframes) |
342 | uvc_dbg(stream->dev, FORMAT, |
343 | "Unknown bFrameIndex %u, using default\n" , |
344 | probe->bFrameIndex); |
345 | |
346 | fmt->fmt.pix.width = frame->wWidth; |
347 | fmt->fmt.pix.height = frame->wHeight; |
348 | fmt->fmt.pix.field = V4L2_FIELD_NONE; |
349 | fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame); |
350 | fmt->fmt.pix.sizeimage = probe->dwMaxVideoFrameSize; |
351 | fmt->fmt.pix.pixelformat = format->fcc; |
352 | fmt->fmt.pix.colorspace = format->colorspace; |
353 | fmt->fmt.pix.xfer_func = format->xfer_func; |
354 | fmt->fmt.pix.ycbcr_enc = format->ycbcr_enc; |
355 | |
356 | if (uvc_format != NULL) |
357 | *uvc_format = format; |
358 | if (uvc_frame != NULL) |
359 | *uvc_frame = frame; |
360 | |
361 | return ret; |
362 | } |
363 | |
364 | static int uvc_v4l2_get_format(struct uvc_streaming *stream, |
365 | struct v4l2_format *fmt) |
366 | { |
367 | const struct uvc_format *format; |
368 | const struct uvc_frame *frame; |
369 | int ret = 0; |
370 | |
371 | if (fmt->type != stream->type) |
372 | return -EINVAL; |
373 | |
374 | mutex_lock(&stream->mutex); |
375 | format = stream->cur_format; |
376 | frame = stream->cur_frame; |
377 | |
378 | if (format == NULL || frame == NULL) { |
379 | ret = -EINVAL; |
380 | goto done; |
381 | } |
382 | |
383 | fmt->fmt.pix.pixelformat = format->fcc; |
384 | fmt->fmt.pix.width = frame->wWidth; |
385 | fmt->fmt.pix.height = frame->wHeight; |
386 | fmt->fmt.pix.field = V4L2_FIELD_NONE; |
387 | fmt->fmt.pix.bytesperline = uvc_v4l2_get_bytesperline(format, frame); |
388 | fmt->fmt.pix.sizeimage = stream->ctrl.dwMaxVideoFrameSize; |
389 | fmt->fmt.pix.colorspace = format->colorspace; |
390 | fmt->fmt.pix.xfer_func = format->xfer_func; |
391 | fmt->fmt.pix.ycbcr_enc = format->ycbcr_enc; |
392 | |
393 | done: |
394 | mutex_unlock(lock: &stream->mutex); |
395 | return ret; |
396 | } |
397 | |
398 | static int uvc_v4l2_set_format(struct uvc_streaming *stream, |
399 | struct v4l2_format *fmt) |
400 | { |
401 | struct uvc_streaming_control probe; |
402 | const struct uvc_format *format; |
403 | const struct uvc_frame *frame; |
404 | int ret; |
405 | |
406 | if (fmt->type != stream->type) |
407 | return -EINVAL; |
408 | |
409 | ret = uvc_v4l2_try_format(stream, fmt, probe: &probe, uvc_format: &format, uvc_frame: &frame); |
410 | if (ret < 0) |
411 | return ret; |
412 | |
413 | mutex_lock(&stream->mutex); |
414 | |
415 | if (uvc_queue_allocated(queue: &stream->queue)) { |
416 | ret = -EBUSY; |
417 | goto done; |
418 | } |
419 | |
420 | stream->ctrl = probe; |
421 | stream->cur_format = format; |
422 | stream->cur_frame = frame; |
423 | |
424 | done: |
425 | mutex_unlock(lock: &stream->mutex); |
426 | return ret; |
427 | } |
428 | |
429 | static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream, |
430 | struct v4l2_streamparm *parm) |
431 | { |
432 | u32 numerator, denominator; |
433 | |
434 | if (parm->type != stream->type) |
435 | return -EINVAL; |
436 | |
437 | mutex_lock(&stream->mutex); |
438 | numerator = stream->ctrl.dwFrameInterval; |
439 | mutex_unlock(lock: &stream->mutex); |
440 | |
441 | denominator = 10000000; |
442 | v4l2_simplify_fraction(numerator: &numerator, denominator: &denominator, n_terms: 8, threshold: 333); |
443 | |
444 | memset(parm, 0, sizeof(*parm)); |
445 | parm->type = stream->type; |
446 | |
447 | if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
448 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; |
449 | parm->parm.capture.capturemode = 0; |
450 | parm->parm.capture.timeperframe.numerator = numerator; |
451 | parm->parm.capture.timeperframe.denominator = denominator; |
452 | parm->parm.capture.extendedmode = 0; |
453 | parm->parm.capture.readbuffers = 0; |
454 | } else { |
455 | parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; |
456 | parm->parm.output.outputmode = 0; |
457 | parm->parm.output.timeperframe.numerator = numerator; |
458 | parm->parm.output.timeperframe.denominator = denominator; |
459 | } |
460 | |
461 | return 0; |
462 | } |
463 | |
464 | static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream, |
465 | struct v4l2_streamparm *parm) |
466 | { |
467 | struct uvc_streaming_control probe; |
468 | struct v4l2_fract timeperframe; |
469 | const struct uvc_format *format; |
470 | const struct uvc_frame *frame; |
471 | u32 interval, maxd; |
472 | unsigned int i; |
473 | int ret; |
474 | |
475 | if (parm->type != stream->type) |
476 | return -EINVAL; |
477 | |
478 | if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
479 | timeperframe = parm->parm.capture.timeperframe; |
480 | else |
481 | timeperframe = parm->parm.output.timeperframe; |
482 | |
483 | interval = v4l2_fraction_to_interval(numerator: timeperframe.numerator, |
484 | denominator: timeperframe.denominator); |
485 | uvc_dbg(stream->dev, FORMAT, "Setting frame interval to %u/%u (%u)\n" , |
486 | timeperframe.numerator, timeperframe.denominator, interval); |
487 | |
488 | mutex_lock(&stream->mutex); |
489 | |
490 | if (uvc_queue_streaming(queue: &stream->queue)) { |
491 | mutex_unlock(lock: &stream->mutex); |
492 | return -EBUSY; |
493 | } |
494 | |
495 | format = stream->cur_format; |
496 | frame = stream->cur_frame; |
497 | probe = stream->ctrl; |
498 | probe.dwFrameInterval = uvc_try_frame_interval(frame, interval); |
499 | maxd = abs((s32)probe.dwFrameInterval - interval); |
500 | |
501 | /* Try frames with matching size to find the best frame interval. */ |
502 | for (i = 0; i < format->nframes && maxd != 0; i++) { |
503 | u32 d, ival; |
504 | |
505 | if (&format->frames[i] == stream->cur_frame) |
506 | continue; |
507 | |
508 | if (format->frames[i].wWidth != stream->cur_frame->wWidth || |
509 | format->frames[i].wHeight != stream->cur_frame->wHeight) |
510 | continue; |
511 | |
512 | ival = uvc_try_frame_interval(frame: &format->frames[i], interval); |
513 | d = abs((s32)ival - interval); |
514 | if (d >= maxd) |
515 | continue; |
516 | |
517 | frame = &format->frames[i]; |
518 | probe.bFrameIndex = frame->bFrameIndex; |
519 | probe.dwFrameInterval = ival; |
520 | maxd = d; |
521 | } |
522 | |
523 | /* Probe the device with the new settings. */ |
524 | ret = uvc_probe_video(stream, probe: &probe); |
525 | if (ret < 0) { |
526 | mutex_unlock(lock: &stream->mutex); |
527 | return ret; |
528 | } |
529 | |
530 | stream->ctrl = probe; |
531 | stream->cur_frame = frame; |
532 | mutex_unlock(lock: &stream->mutex); |
533 | |
534 | /* Return the actual frame period. */ |
535 | timeperframe.numerator = probe.dwFrameInterval; |
536 | timeperframe.denominator = 10000000; |
537 | v4l2_simplify_fraction(numerator: &timeperframe.numerator, |
538 | denominator: &timeperframe.denominator, n_terms: 8, threshold: 333); |
539 | |
540 | if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
541 | parm->parm.capture.timeperframe = timeperframe; |
542 | parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; |
543 | } else { |
544 | parm->parm.output.timeperframe = timeperframe; |
545 | parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME; |
546 | } |
547 | |
548 | return 0; |
549 | } |
550 | |
551 | /* ------------------------------------------------------------------------ |
552 | * Privilege management |
553 | */ |
554 | |
555 | /* |
556 | * Privilege management is the multiple-open implementation basis. The current |
557 | * implementation is completely transparent for the end-user and doesn't |
558 | * require explicit use of the VIDIOC_G_PRIORITY and VIDIOC_S_PRIORITY ioctls. |
559 | * Those ioctls enable finer control on the device (by making possible for a |
560 | * user to request exclusive access to a device), but are not mature yet. |
561 | * Switching to the V4L2 priority mechanism might be considered in the future |
562 | * if this situation changes. |
563 | * |
564 | * Each open instance of a UVC device can either be in a privileged or |
565 | * unprivileged state. Only a single instance can be in a privileged state at |
566 | * a given time. Trying to perform an operation that requires privileges will |
567 | * automatically acquire the required privileges if possible, or return -EBUSY |
568 | * otherwise. Privileges are dismissed when closing the instance or when |
569 | * freeing the video buffers using VIDIOC_REQBUFS. |
570 | * |
571 | * Operations that require privileges are: |
572 | * |
573 | * - VIDIOC_S_INPUT |
574 | * - VIDIOC_S_PARM |
575 | * - VIDIOC_S_FMT |
576 | * - VIDIOC_REQBUFS |
577 | */ |
578 | static int uvc_acquire_privileges(struct uvc_fh *handle) |
579 | { |
580 | /* Always succeed if the handle is already privileged. */ |
581 | if (handle->state == UVC_HANDLE_ACTIVE) |
582 | return 0; |
583 | |
584 | /* Check if the device already has a privileged handle. */ |
585 | if (atomic_inc_return(v: &handle->stream->active) != 1) { |
586 | atomic_dec(v: &handle->stream->active); |
587 | return -EBUSY; |
588 | } |
589 | |
590 | handle->state = UVC_HANDLE_ACTIVE; |
591 | return 0; |
592 | } |
593 | |
594 | static void uvc_dismiss_privileges(struct uvc_fh *handle) |
595 | { |
596 | if (handle->state == UVC_HANDLE_ACTIVE) |
597 | atomic_dec(v: &handle->stream->active); |
598 | |
599 | handle->state = UVC_HANDLE_PASSIVE; |
600 | } |
601 | |
602 | static int uvc_has_privileges(struct uvc_fh *handle) |
603 | { |
604 | return handle->state == UVC_HANDLE_ACTIVE; |
605 | } |
606 | |
607 | /* ------------------------------------------------------------------------ |
608 | * V4L2 file operations |
609 | */ |
610 | |
611 | static int uvc_v4l2_open(struct file *file) |
612 | { |
613 | struct uvc_streaming *stream; |
614 | struct uvc_fh *handle; |
615 | int ret = 0; |
616 | |
617 | stream = video_drvdata(file); |
618 | uvc_dbg(stream->dev, CALLS, "%s\n" , __func__); |
619 | |
620 | ret = usb_autopm_get_interface(intf: stream->dev->intf); |
621 | if (ret < 0) |
622 | return ret; |
623 | |
624 | /* Create the device handle. */ |
625 | handle = kzalloc(size: sizeof(*handle), GFP_KERNEL); |
626 | if (handle == NULL) { |
627 | usb_autopm_put_interface(intf: stream->dev->intf); |
628 | return -ENOMEM; |
629 | } |
630 | |
631 | mutex_lock(&stream->dev->lock); |
632 | if (stream->dev->users == 0) { |
633 | ret = uvc_status_start(dev: stream->dev, GFP_KERNEL); |
634 | if (ret < 0) { |
635 | mutex_unlock(lock: &stream->dev->lock); |
636 | usb_autopm_put_interface(intf: stream->dev->intf); |
637 | kfree(objp: handle); |
638 | return ret; |
639 | } |
640 | } |
641 | |
642 | stream->dev->users++; |
643 | mutex_unlock(lock: &stream->dev->lock); |
644 | |
645 | v4l2_fh_init(fh: &handle->vfh, vdev: &stream->vdev); |
646 | v4l2_fh_add(fh: &handle->vfh); |
647 | handle->chain = stream->chain; |
648 | handle->stream = stream; |
649 | handle->state = UVC_HANDLE_PASSIVE; |
650 | file->private_data = handle; |
651 | |
652 | return 0; |
653 | } |
654 | |
655 | static int uvc_v4l2_release(struct file *file) |
656 | { |
657 | struct uvc_fh *handle = file->private_data; |
658 | struct uvc_streaming *stream = handle->stream; |
659 | |
660 | uvc_dbg(stream->dev, CALLS, "%s\n" , __func__); |
661 | |
662 | /* Only free resources if this is a privileged handle. */ |
663 | if (uvc_has_privileges(handle)) |
664 | uvc_queue_release(queue: &stream->queue); |
665 | |
666 | /* Release the file handle. */ |
667 | uvc_dismiss_privileges(handle); |
668 | v4l2_fh_del(fh: &handle->vfh); |
669 | v4l2_fh_exit(fh: &handle->vfh); |
670 | kfree(objp: handle); |
671 | file->private_data = NULL; |
672 | |
673 | mutex_lock(&stream->dev->lock); |
674 | if (--stream->dev->users == 0) |
675 | uvc_status_stop(dev: stream->dev); |
676 | mutex_unlock(lock: &stream->dev->lock); |
677 | |
678 | usb_autopm_put_interface(intf: stream->dev->intf); |
679 | return 0; |
680 | } |
681 | |
682 | static int uvc_ioctl_querycap(struct file *file, void *fh, |
683 | struct v4l2_capability *cap) |
684 | { |
685 | struct uvc_fh *handle = file->private_data; |
686 | struct uvc_video_chain *chain = handle->chain; |
687 | struct uvc_streaming *stream = handle->stream; |
688 | |
689 | strscpy(cap->driver, "uvcvideo" , sizeof(cap->driver)); |
690 | strscpy(cap->card, handle->stream->dev->name, sizeof(cap->card)); |
691 | usb_make_path(dev: stream->dev->udev, buf: cap->bus_info, size: sizeof(cap->bus_info)); |
692 | cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING |
693 | | chain->caps; |
694 | |
695 | return 0; |
696 | } |
697 | |
698 | static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream, |
699 | struct v4l2_fmtdesc *fmt) |
700 | { |
701 | const struct uvc_format *format; |
702 | enum v4l2_buf_type type = fmt->type; |
703 | u32 index = fmt->index; |
704 | |
705 | if (fmt->type != stream->type || fmt->index >= stream->nformats) |
706 | return -EINVAL; |
707 | |
708 | memset(fmt, 0, sizeof(*fmt)); |
709 | fmt->index = index; |
710 | fmt->type = type; |
711 | |
712 | format = &stream->formats[fmt->index]; |
713 | fmt->flags = 0; |
714 | if (format->flags & UVC_FMT_FLAG_COMPRESSED) |
715 | fmt->flags |= V4L2_FMT_FLAG_COMPRESSED; |
716 | fmt->pixelformat = format->fcc; |
717 | return 0; |
718 | } |
719 | |
720 | static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh, |
721 | struct v4l2_fmtdesc *fmt) |
722 | { |
723 | struct uvc_fh *handle = fh; |
724 | struct uvc_streaming *stream = handle->stream; |
725 | |
726 | return uvc_ioctl_enum_fmt(stream, fmt); |
727 | } |
728 | |
729 | static int uvc_ioctl_enum_fmt_vid_out(struct file *file, void *fh, |
730 | struct v4l2_fmtdesc *fmt) |
731 | { |
732 | struct uvc_fh *handle = fh; |
733 | struct uvc_streaming *stream = handle->stream; |
734 | |
735 | return uvc_ioctl_enum_fmt(stream, fmt); |
736 | } |
737 | |
738 | static int uvc_ioctl_g_fmt_vid_cap(struct file *file, void *fh, |
739 | struct v4l2_format *fmt) |
740 | { |
741 | struct uvc_fh *handle = fh; |
742 | struct uvc_streaming *stream = handle->stream; |
743 | |
744 | return uvc_v4l2_get_format(stream, fmt); |
745 | } |
746 | |
747 | static int uvc_ioctl_g_fmt_vid_out(struct file *file, void *fh, |
748 | struct v4l2_format *fmt) |
749 | { |
750 | struct uvc_fh *handle = fh; |
751 | struct uvc_streaming *stream = handle->stream; |
752 | |
753 | return uvc_v4l2_get_format(stream, fmt); |
754 | } |
755 | |
756 | static int uvc_ioctl_s_fmt_vid_cap(struct file *file, void *fh, |
757 | struct v4l2_format *fmt) |
758 | { |
759 | struct uvc_fh *handle = fh; |
760 | struct uvc_streaming *stream = handle->stream; |
761 | int ret; |
762 | |
763 | ret = uvc_acquire_privileges(handle); |
764 | if (ret < 0) |
765 | return ret; |
766 | |
767 | return uvc_v4l2_set_format(stream, fmt); |
768 | } |
769 | |
770 | static int uvc_ioctl_s_fmt_vid_out(struct file *file, void *fh, |
771 | struct v4l2_format *fmt) |
772 | { |
773 | struct uvc_fh *handle = fh; |
774 | struct uvc_streaming *stream = handle->stream; |
775 | int ret; |
776 | |
777 | ret = uvc_acquire_privileges(handle); |
778 | if (ret < 0) |
779 | return ret; |
780 | |
781 | return uvc_v4l2_set_format(stream, fmt); |
782 | } |
783 | |
784 | static int uvc_ioctl_try_fmt_vid_cap(struct file *file, void *fh, |
785 | struct v4l2_format *fmt) |
786 | { |
787 | struct uvc_fh *handle = fh; |
788 | struct uvc_streaming *stream = handle->stream; |
789 | struct uvc_streaming_control probe; |
790 | |
791 | return uvc_v4l2_try_format(stream, fmt, probe: &probe, NULL, NULL); |
792 | } |
793 | |
794 | static int uvc_ioctl_try_fmt_vid_out(struct file *file, void *fh, |
795 | struct v4l2_format *fmt) |
796 | { |
797 | struct uvc_fh *handle = fh; |
798 | struct uvc_streaming *stream = handle->stream; |
799 | struct uvc_streaming_control probe; |
800 | |
801 | return uvc_v4l2_try_format(stream, fmt, probe: &probe, NULL, NULL); |
802 | } |
803 | |
804 | static int uvc_ioctl_reqbufs(struct file *file, void *fh, |
805 | struct v4l2_requestbuffers *rb) |
806 | { |
807 | struct uvc_fh *handle = fh; |
808 | struct uvc_streaming *stream = handle->stream; |
809 | int ret; |
810 | |
811 | ret = uvc_acquire_privileges(handle); |
812 | if (ret < 0) |
813 | return ret; |
814 | |
815 | mutex_lock(&stream->mutex); |
816 | ret = uvc_request_buffers(queue: &stream->queue, rb); |
817 | mutex_unlock(lock: &stream->mutex); |
818 | if (ret < 0) |
819 | return ret; |
820 | |
821 | if (ret == 0) |
822 | uvc_dismiss_privileges(handle); |
823 | |
824 | return 0; |
825 | } |
826 | |
827 | static int uvc_ioctl_querybuf(struct file *file, void *fh, |
828 | struct v4l2_buffer *buf) |
829 | { |
830 | struct uvc_fh *handle = fh; |
831 | struct uvc_streaming *stream = handle->stream; |
832 | |
833 | if (!uvc_has_privileges(handle)) |
834 | return -EBUSY; |
835 | |
836 | return uvc_query_buffer(queue: &stream->queue, v4l2_buf: buf); |
837 | } |
838 | |
839 | static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) |
840 | { |
841 | struct uvc_fh *handle = fh; |
842 | struct uvc_streaming *stream = handle->stream; |
843 | |
844 | if (!uvc_has_privileges(handle)) |
845 | return -EBUSY; |
846 | |
847 | return uvc_queue_buffer(queue: &stream->queue, |
848 | mdev: stream->vdev.v4l2_dev->mdev, v4l2_buf: buf); |
849 | } |
850 | |
851 | static int uvc_ioctl_expbuf(struct file *file, void *fh, |
852 | struct v4l2_exportbuffer *exp) |
853 | { |
854 | struct uvc_fh *handle = fh; |
855 | struct uvc_streaming *stream = handle->stream; |
856 | |
857 | if (!uvc_has_privileges(handle)) |
858 | return -EBUSY; |
859 | |
860 | return uvc_export_buffer(queue: &stream->queue, exp); |
861 | } |
862 | |
863 | static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) |
864 | { |
865 | struct uvc_fh *handle = fh; |
866 | struct uvc_streaming *stream = handle->stream; |
867 | |
868 | if (!uvc_has_privileges(handle)) |
869 | return -EBUSY; |
870 | |
871 | return uvc_dequeue_buffer(queue: &stream->queue, v4l2_buf: buf, |
872 | nonblocking: file->f_flags & O_NONBLOCK); |
873 | } |
874 | |
875 | static int uvc_ioctl_create_bufs(struct file *file, void *fh, |
876 | struct v4l2_create_buffers *cb) |
877 | { |
878 | struct uvc_fh *handle = fh; |
879 | struct uvc_streaming *stream = handle->stream; |
880 | int ret; |
881 | |
882 | ret = uvc_acquire_privileges(handle); |
883 | if (ret < 0) |
884 | return ret; |
885 | |
886 | return uvc_create_buffers(queue: &stream->queue, v4l2_cb: cb); |
887 | } |
888 | |
889 | static int uvc_ioctl_streamon(struct file *file, void *fh, |
890 | enum v4l2_buf_type type) |
891 | { |
892 | struct uvc_fh *handle = fh; |
893 | struct uvc_streaming *stream = handle->stream; |
894 | int ret; |
895 | |
896 | if (!uvc_has_privileges(handle)) |
897 | return -EBUSY; |
898 | |
899 | mutex_lock(&stream->mutex); |
900 | ret = uvc_queue_streamon(queue: &stream->queue, type); |
901 | mutex_unlock(lock: &stream->mutex); |
902 | |
903 | return ret; |
904 | } |
905 | |
906 | static int uvc_ioctl_streamoff(struct file *file, void *fh, |
907 | enum v4l2_buf_type type) |
908 | { |
909 | struct uvc_fh *handle = fh; |
910 | struct uvc_streaming *stream = handle->stream; |
911 | |
912 | if (!uvc_has_privileges(handle)) |
913 | return -EBUSY; |
914 | |
915 | mutex_lock(&stream->mutex); |
916 | uvc_queue_streamoff(queue: &stream->queue, type); |
917 | mutex_unlock(lock: &stream->mutex); |
918 | |
919 | return 0; |
920 | } |
921 | |
922 | static int uvc_ioctl_enum_input(struct file *file, void *fh, |
923 | struct v4l2_input *input) |
924 | { |
925 | struct uvc_fh *handle = fh; |
926 | struct uvc_video_chain *chain = handle->chain; |
927 | const struct uvc_entity *selector = chain->selector; |
928 | struct uvc_entity *iterm = NULL; |
929 | struct uvc_entity *it; |
930 | u32 index = input->index; |
931 | |
932 | if (selector == NULL || |
933 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { |
934 | if (index != 0) |
935 | return -EINVAL; |
936 | list_for_each_entry(it, &chain->entities, chain) { |
937 | if (UVC_ENTITY_IS_ITERM(it)) { |
938 | iterm = it; |
939 | break; |
940 | } |
941 | } |
942 | } else if (index < selector->bNrInPins) { |
943 | list_for_each_entry(it, &chain->entities, chain) { |
944 | if (!UVC_ENTITY_IS_ITERM(it)) |
945 | continue; |
946 | if (it->id == selector->baSourceID[index]) { |
947 | iterm = it; |
948 | break; |
949 | } |
950 | } |
951 | } |
952 | |
953 | if (iterm == NULL) |
954 | return -EINVAL; |
955 | |
956 | memset(input, 0, sizeof(*input)); |
957 | input->index = index; |
958 | strscpy(input->name, iterm->name, sizeof(input->name)); |
959 | if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA) |
960 | input->type = V4L2_INPUT_TYPE_CAMERA; |
961 | |
962 | return 0; |
963 | } |
964 | |
965 | static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input) |
966 | { |
967 | struct uvc_fh *handle = fh; |
968 | struct uvc_video_chain *chain = handle->chain; |
969 | u8 *buf; |
970 | int ret; |
971 | |
972 | if (chain->selector == NULL || |
973 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { |
974 | *input = 0; |
975 | return 0; |
976 | } |
977 | |
978 | buf = kmalloc(size: 1, GFP_KERNEL); |
979 | if (!buf) |
980 | return -ENOMEM; |
981 | |
982 | ret = uvc_query_ctrl(dev: chain->dev, UVC_GET_CUR, unit: chain->selector->id, |
983 | intfnum: chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, |
984 | data: buf, size: 1); |
985 | if (!ret) |
986 | *input = *buf - 1; |
987 | |
988 | kfree(objp: buf); |
989 | |
990 | return ret; |
991 | } |
992 | |
993 | static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input) |
994 | { |
995 | struct uvc_fh *handle = fh; |
996 | struct uvc_video_chain *chain = handle->chain; |
997 | u8 *buf; |
998 | int ret; |
999 | |
1000 | ret = uvc_acquire_privileges(handle); |
1001 | if (ret < 0) |
1002 | return ret; |
1003 | |
1004 | if (chain->selector == NULL || |
1005 | (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) { |
1006 | if (input) |
1007 | return -EINVAL; |
1008 | return 0; |
1009 | } |
1010 | |
1011 | if (input >= chain->selector->bNrInPins) |
1012 | return -EINVAL; |
1013 | |
1014 | buf = kmalloc(size: 1, GFP_KERNEL); |
1015 | if (!buf) |
1016 | return -ENOMEM; |
1017 | |
1018 | *buf = input + 1; |
1019 | ret = uvc_query_ctrl(dev: chain->dev, UVC_SET_CUR, unit: chain->selector->id, |
1020 | intfnum: chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL, |
1021 | data: buf, size: 1); |
1022 | kfree(objp: buf); |
1023 | |
1024 | return ret; |
1025 | } |
1026 | |
1027 | static int uvc_ioctl_queryctrl(struct file *file, void *fh, |
1028 | struct v4l2_queryctrl *qc) |
1029 | { |
1030 | struct uvc_fh *handle = fh; |
1031 | struct uvc_video_chain *chain = handle->chain; |
1032 | |
1033 | return uvc_query_v4l2_ctrl(chain, v4l2_ctrl: qc); |
1034 | } |
1035 | |
1036 | static int uvc_ioctl_query_ext_ctrl(struct file *file, void *fh, |
1037 | struct v4l2_query_ext_ctrl *qec) |
1038 | { |
1039 | struct uvc_fh *handle = fh; |
1040 | struct uvc_video_chain *chain = handle->chain; |
1041 | struct v4l2_queryctrl qc = { qec->id }; |
1042 | int ret; |
1043 | |
1044 | ret = uvc_query_v4l2_ctrl(chain, v4l2_ctrl: &qc); |
1045 | if (ret) |
1046 | return ret; |
1047 | |
1048 | qec->id = qc.id; |
1049 | qec->type = qc.type; |
1050 | strscpy(qec->name, qc.name, sizeof(qec->name)); |
1051 | qec->minimum = qc.minimum; |
1052 | qec->maximum = qc.maximum; |
1053 | qec->step = qc.step; |
1054 | qec->default_value = qc.default_value; |
1055 | qec->flags = qc.flags; |
1056 | qec->elem_size = 4; |
1057 | qec->elems = 1; |
1058 | qec->nr_of_dims = 0; |
1059 | memset(qec->dims, 0, sizeof(qec->dims)); |
1060 | memset(qec->reserved, 0, sizeof(qec->reserved)); |
1061 | |
1062 | return 0; |
1063 | } |
1064 | |
1065 | static int uvc_ctrl_check_access(struct uvc_video_chain *chain, |
1066 | struct v4l2_ext_controls *ctrls, |
1067 | unsigned long ioctl) |
1068 | { |
1069 | struct v4l2_ext_control *ctrl = ctrls->controls; |
1070 | unsigned int i; |
1071 | int ret = 0; |
1072 | |
1073 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { |
1074 | ret = uvc_ctrl_is_accessible(chain, v4l2_id: ctrl->id, ctrls, ioctl); |
1075 | if (ret) |
1076 | break; |
1077 | } |
1078 | |
1079 | ctrls->error_idx = ioctl == VIDIOC_TRY_EXT_CTRLS ? i : ctrls->count; |
1080 | |
1081 | return ret; |
1082 | } |
1083 | |
1084 | static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh, |
1085 | struct v4l2_ext_controls *ctrls) |
1086 | { |
1087 | struct uvc_fh *handle = fh; |
1088 | struct uvc_video_chain *chain = handle->chain; |
1089 | struct v4l2_ext_control *ctrl = ctrls->controls; |
1090 | unsigned int i; |
1091 | int ret; |
1092 | |
1093 | ret = uvc_ctrl_check_access(chain, ctrls, VIDIOC_G_EXT_CTRLS); |
1094 | if (ret < 0) |
1095 | return ret; |
1096 | |
1097 | if (ctrls->which == V4L2_CTRL_WHICH_DEF_VAL) { |
1098 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { |
1099 | struct v4l2_queryctrl qc = { .id = ctrl->id }; |
1100 | |
1101 | ret = uvc_query_v4l2_ctrl(chain, v4l2_ctrl: &qc); |
1102 | if (ret < 0) { |
1103 | ctrls->error_idx = i; |
1104 | return ret; |
1105 | } |
1106 | |
1107 | ctrl->value = qc.default_value; |
1108 | } |
1109 | |
1110 | return 0; |
1111 | } |
1112 | |
1113 | ret = uvc_ctrl_begin(chain); |
1114 | if (ret < 0) |
1115 | return ret; |
1116 | |
1117 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { |
1118 | ret = uvc_ctrl_get(chain, xctrl: ctrl); |
1119 | if (ret < 0) { |
1120 | uvc_ctrl_rollback(handle); |
1121 | ctrls->error_idx = i; |
1122 | return ret; |
1123 | } |
1124 | } |
1125 | |
1126 | ctrls->error_idx = 0; |
1127 | |
1128 | return uvc_ctrl_rollback(handle); |
1129 | } |
1130 | |
1131 | static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle, |
1132 | struct v4l2_ext_controls *ctrls, |
1133 | unsigned long ioctl) |
1134 | { |
1135 | struct v4l2_ext_control *ctrl = ctrls->controls; |
1136 | struct uvc_video_chain *chain = handle->chain; |
1137 | unsigned int i; |
1138 | int ret; |
1139 | |
1140 | ret = uvc_ctrl_check_access(chain, ctrls, ioctl); |
1141 | if (ret < 0) |
1142 | return ret; |
1143 | |
1144 | ret = uvc_ctrl_begin(chain); |
1145 | if (ret < 0) |
1146 | return ret; |
1147 | |
1148 | for (i = 0; i < ctrls->count; ++ctrl, ++i) { |
1149 | ret = uvc_ctrl_set(handle, xctrl: ctrl); |
1150 | if (ret < 0) { |
1151 | uvc_ctrl_rollback(handle); |
1152 | ctrls->error_idx = ioctl == VIDIOC_S_EXT_CTRLS ? |
1153 | ctrls->count : i; |
1154 | return ret; |
1155 | } |
1156 | } |
1157 | |
1158 | ctrls->error_idx = 0; |
1159 | |
1160 | if (ioctl == VIDIOC_S_EXT_CTRLS) |
1161 | return uvc_ctrl_commit(handle, ctrls); |
1162 | else |
1163 | return uvc_ctrl_rollback(handle); |
1164 | } |
1165 | |
1166 | static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh, |
1167 | struct v4l2_ext_controls *ctrls) |
1168 | { |
1169 | struct uvc_fh *handle = fh; |
1170 | |
1171 | return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, VIDIOC_S_EXT_CTRLS); |
1172 | } |
1173 | |
1174 | static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh, |
1175 | struct v4l2_ext_controls *ctrls) |
1176 | { |
1177 | struct uvc_fh *handle = fh; |
1178 | |
1179 | return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, VIDIOC_TRY_EXT_CTRLS); |
1180 | } |
1181 | |
1182 | static int (struct file *file, void *fh, |
1183 | struct v4l2_querymenu *qm) |
1184 | { |
1185 | struct uvc_fh *handle = fh; |
1186 | struct uvc_video_chain *chain = handle->chain; |
1187 | |
1188 | return uvc_query_v4l2_menu(chain, query_menu: qm); |
1189 | } |
1190 | |
1191 | static int uvc_ioctl_g_selection(struct file *file, void *fh, |
1192 | struct v4l2_selection *sel) |
1193 | { |
1194 | struct uvc_fh *handle = fh; |
1195 | struct uvc_streaming *stream = handle->stream; |
1196 | |
1197 | if (sel->type != stream->type) |
1198 | return -EINVAL; |
1199 | |
1200 | switch (sel->target) { |
1201 | case V4L2_SEL_TGT_CROP_DEFAULT: |
1202 | case V4L2_SEL_TGT_CROP_BOUNDS: |
1203 | if (stream->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1204 | return -EINVAL; |
1205 | break; |
1206 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: |
1207 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: |
1208 | if (stream->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) |
1209 | return -EINVAL; |
1210 | break; |
1211 | default: |
1212 | return -EINVAL; |
1213 | } |
1214 | |
1215 | sel->r.left = 0; |
1216 | sel->r.top = 0; |
1217 | mutex_lock(&stream->mutex); |
1218 | sel->r.width = stream->cur_frame->wWidth; |
1219 | sel->r.height = stream->cur_frame->wHeight; |
1220 | mutex_unlock(lock: &stream->mutex); |
1221 | |
1222 | return 0; |
1223 | } |
1224 | |
1225 | static int uvc_ioctl_g_parm(struct file *file, void *fh, |
1226 | struct v4l2_streamparm *parm) |
1227 | { |
1228 | struct uvc_fh *handle = fh; |
1229 | struct uvc_streaming *stream = handle->stream; |
1230 | |
1231 | return uvc_v4l2_get_streamparm(stream, parm); |
1232 | } |
1233 | |
1234 | static int uvc_ioctl_s_parm(struct file *file, void *fh, |
1235 | struct v4l2_streamparm *parm) |
1236 | { |
1237 | struct uvc_fh *handle = fh; |
1238 | struct uvc_streaming *stream = handle->stream; |
1239 | int ret; |
1240 | |
1241 | ret = uvc_acquire_privileges(handle); |
1242 | if (ret < 0) |
1243 | return ret; |
1244 | |
1245 | return uvc_v4l2_set_streamparm(stream, parm); |
1246 | } |
1247 | |
1248 | static int uvc_ioctl_enum_framesizes(struct file *file, void *fh, |
1249 | struct v4l2_frmsizeenum *fsize) |
1250 | { |
1251 | struct uvc_fh *handle = fh; |
1252 | struct uvc_streaming *stream = handle->stream; |
1253 | const struct uvc_format *format = NULL; |
1254 | const struct uvc_frame *frame = NULL; |
1255 | unsigned int index; |
1256 | unsigned int i; |
1257 | |
1258 | /* Look for the given pixel format */ |
1259 | for (i = 0; i < stream->nformats; i++) { |
1260 | if (stream->formats[i].fcc == fsize->pixel_format) { |
1261 | format = &stream->formats[i]; |
1262 | break; |
1263 | } |
1264 | } |
1265 | if (format == NULL) |
1266 | return -EINVAL; |
1267 | |
1268 | /* Skip duplicate frame sizes */ |
1269 | for (i = 0, index = 0; i < format->nframes; i++) { |
1270 | if (frame && frame->wWidth == format->frames[i].wWidth && |
1271 | frame->wHeight == format->frames[i].wHeight) |
1272 | continue; |
1273 | frame = &format->frames[i]; |
1274 | if (index == fsize->index) |
1275 | break; |
1276 | index++; |
1277 | } |
1278 | |
1279 | if (i == format->nframes) |
1280 | return -EINVAL; |
1281 | |
1282 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; |
1283 | fsize->discrete.width = frame->wWidth; |
1284 | fsize->discrete.height = frame->wHeight; |
1285 | return 0; |
1286 | } |
1287 | |
1288 | static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh, |
1289 | struct v4l2_frmivalenum *fival) |
1290 | { |
1291 | struct uvc_fh *handle = fh; |
1292 | struct uvc_streaming *stream = handle->stream; |
1293 | const struct uvc_format *format = NULL; |
1294 | const struct uvc_frame *frame = NULL; |
1295 | unsigned int nintervals; |
1296 | unsigned int index; |
1297 | unsigned int i; |
1298 | |
1299 | /* Look for the given pixel format and frame size */ |
1300 | for (i = 0; i < stream->nformats; i++) { |
1301 | if (stream->formats[i].fcc == fival->pixel_format) { |
1302 | format = &stream->formats[i]; |
1303 | break; |
1304 | } |
1305 | } |
1306 | if (format == NULL) |
1307 | return -EINVAL; |
1308 | |
1309 | index = fival->index; |
1310 | for (i = 0; i < format->nframes; i++) { |
1311 | if (format->frames[i].wWidth == fival->width && |
1312 | format->frames[i].wHeight == fival->height) { |
1313 | frame = &format->frames[i]; |
1314 | nintervals = frame->bFrameIntervalType ?: 1; |
1315 | if (index < nintervals) |
1316 | break; |
1317 | index -= nintervals; |
1318 | } |
1319 | } |
1320 | if (i == format->nframes) |
1321 | return -EINVAL; |
1322 | |
1323 | if (frame->bFrameIntervalType) { |
1324 | fival->type = V4L2_FRMIVAL_TYPE_DISCRETE; |
1325 | fival->discrete.numerator = |
1326 | frame->dwFrameInterval[index]; |
1327 | fival->discrete.denominator = 10000000; |
1328 | v4l2_simplify_fraction(numerator: &fival->discrete.numerator, |
1329 | denominator: &fival->discrete.denominator, n_terms: 8, threshold: 333); |
1330 | } else { |
1331 | fival->type = V4L2_FRMIVAL_TYPE_STEPWISE; |
1332 | fival->stepwise.min.numerator = frame->dwFrameInterval[0]; |
1333 | fival->stepwise.min.denominator = 10000000; |
1334 | fival->stepwise.max.numerator = frame->dwFrameInterval[1]; |
1335 | fival->stepwise.max.denominator = 10000000; |
1336 | fival->stepwise.step.numerator = frame->dwFrameInterval[2]; |
1337 | fival->stepwise.step.denominator = 10000000; |
1338 | v4l2_simplify_fraction(numerator: &fival->stepwise.min.numerator, |
1339 | denominator: &fival->stepwise.min.denominator, n_terms: 8, threshold: 333); |
1340 | v4l2_simplify_fraction(numerator: &fival->stepwise.max.numerator, |
1341 | denominator: &fival->stepwise.max.denominator, n_terms: 8, threshold: 333); |
1342 | v4l2_simplify_fraction(numerator: &fival->stepwise.step.numerator, |
1343 | denominator: &fival->stepwise.step.denominator, n_terms: 8, threshold: 333); |
1344 | } |
1345 | |
1346 | return 0; |
1347 | } |
1348 | |
1349 | static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh, |
1350 | const struct v4l2_event_subscription *sub) |
1351 | { |
1352 | switch (sub->type) { |
1353 | case V4L2_EVENT_CTRL: |
1354 | return v4l2_event_subscribe(fh, sub, elems: 0, ops: &uvc_ctrl_sub_ev_ops); |
1355 | default: |
1356 | return -EINVAL; |
1357 | } |
1358 | } |
1359 | |
1360 | static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio, |
1361 | unsigned int cmd, void *arg) |
1362 | { |
1363 | struct uvc_fh *handle = fh; |
1364 | struct uvc_video_chain *chain = handle->chain; |
1365 | |
1366 | switch (cmd) { |
1367 | /* Dynamic controls. */ |
1368 | case UVCIOC_CTRL_MAP: |
1369 | return uvc_ioctl_xu_ctrl_map(chain, xmap: arg); |
1370 | |
1371 | case UVCIOC_CTRL_QUERY: |
1372 | return uvc_xu_ctrl_query(chain, xqry: arg); |
1373 | |
1374 | default: |
1375 | return -ENOTTY; |
1376 | } |
1377 | } |
1378 | |
1379 | #ifdef CONFIG_COMPAT |
1380 | struct uvc_xu_control_mapping32 { |
1381 | u32 id; |
1382 | u8 name[32]; |
1383 | u8 entity[16]; |
1384 | u8 selector; |
1385 | |
1386 | u8 size; |
1387 | u8 offset; |
1388 | u32 v4l2_type; |
1389 | u32 data_type; |
1390 | |
1391 | compat_caddr_t ; |
1392 | u32 ; |
1393 | |
1394 | u32 reserved[4]; |
1395 | }; |
1396 | |
1397 | static int uvc_v4l2_get_xu_mapping(struct uvc_xu_control_mapping *kp, |
1398 | const struct uvc_xu_control_mapping32 __user *up) |
1399 | { |
1400 | struct uvc_xu_control_mapping32 *p = (void *)kp; |
1401 | compat_caddr_t info; |
1402 | u32 count; |
1403 | |
1404 | if (copy_from_user(to: p, from: up, n: sizeof(*p))) |
1405 | return -EFAULT; |
1406 | |
1407 | count = p->menu_count; |
1408 | info = p->menu_info; |
1409 | |
1410 | memset(kp->reserved, 0, sizeof(kp->reserved)); |
1411 | kp->menu_info = count ? compat_ptr(uptr: info) : NULL; |
1412 | kp->menu_count = count; |
1413 | return 0; |
1414 | } |
1415 | |
1416 | static int uvc_v4l2_put_xu_mapping(const struct uvc_xu_control_mapping *kp, |
1417 | struct uvc_xu_control_mapping32 __user *up) |
1418 | { |
1419 | if (copy_to_user(to: up, from: kp, offsetof(typeof(*up), menu_info)) || |
1420 | put_user(kp->menu_count, &up->menu_count)) |
1421 | return -EFAULT; |
1422 | |
1423 | if (clear_user(to: up->reserved, n: sizeof(up->reserved))) |
1424 | return -EFAULT; |
1425 | |
1426 | return 0; |
1427 | } |
1428 | |
1429 | struct uvc_xu_control_query32 { |
1430 | u8 unit; |
1431 | u8 selector; |
1432 | u8 query; |
1433 | u16 size; |
1434 | compat_caddr_t data; |
1435 | }; |
1436 | |
1437 | static int uvc_v4l2_get_xu_query(struct uvc_xu_control_query *kp, |
1438 | const struct uvc_xu_control_query32 __user *up) |
1439 | { |
1440 | struct uvc_xu_control_query32 v; |
1441 | |
1442 | if (copy_from_user(to: &v, from: up, n: sizeof(v))) |
1443 | return -EFAULT; |
1444 | |
1445 | *kp = (struct uvc_xu_control_query){ |
1446 | .unit = v.unit, |
1447 | .selector = v.selector, |
1448 | .query = v.query, |
1449 | .size = v.size, |
1450 | .data = v.size ? compat_ptr(uptr: v.data) : NULL |
1451 | }; |
1452 | return 0; |
1453 | } |
1454 | |
1455 | static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp, |
1456 | struct uvc_xu_control_query32 __user *up) |
1457 | { |
1458 | if (copy_to_user(to: up, from: kp, offsetof(typeof(*up), data))) |
1459 | return -EFAULT; |
1460 | return 0; |
1461 | } |
1462 | |
1463 | #define UVCIOC_CTRL_MAP32 _IOWR('u', 0x20, struct uvc_xu_control_mapping32) |
1464 | #define UVCIOC_CTRL_QUERY32 _IOWR('u', 0x21, struct uvc_xu_control_query32) |
1465 | |
1466 | static long uvc_v4l2_compat_ioctl32(struct file *file, |
1467 | unsigned int cmd, unsigned long arg) |
1468 | { |
1469 | struct uvc_fh *handle = file->private_data; |
1470 | union { |
1471 | struct uvc_xu_control_mapping xmap; |
1472 | struct uvc_xu_control_query xqry; |
1473 | } karg; |
1474 | void __user *up = compat_ptr(uptr: arg); |
1475 | long ret; |
1476 | |
1477 | switch (cmd) { |
1478 | case UVCIOC_CTRL_MAP32: |
1479 | ret = uvc_v4l2_get_xu_mapping(kp: &karg.xmap, up); |
1480 | if (ret) |
1481 | return ret; |
1482 | ret = uvc_ioctl_xu_ctrl_map(chain: handle->chain, xmap: &karg.xmap); |
1483 | if (ret) |
1484 | return ret; |
1485 | ret = uvc_v4l2_put_xu_mapping(kp: &karg.xmap, up); |
1486 | if (ret) |
1487 | return ret; |
1488 | |
1489 | break; |
1490 | |
1491 | case UVCIOC_CTRL_QUERY32: |
1492 | ret = uvc_v4l2_get_xu_query(kp: &karg.xqry, up); |
1493 | if (ret) |
1494 | return ret; |
1495 | ret = uvc_xu_ctrl_query(chain: handle->chain, xqry: &karg.xqry); |
1496 | if (ret) |
1497 | return ret; |
1498 | ret = uvc_v4l2_put_xu_query(kp: &karg.xqry, up); |
1499 | if (ret) |
1500 | return ret; |
1501 | break; |
1502 | |
1503 | default: |
1504 | return -ENOIOCTLCMD; |
1505 | } |
1506 | |
1507 | return ret; |
1508 | } |
1509 | #endif |
1510 | |
1511 | static ssize_t uvc_v4l2_read(struct file *file, char __user *data, |
1512 | size_t count, loff_t *ppos) |
1513 | { |
1514 | struct uvc_fh *handle = file->private_data; |
1515 | struct uvc_streaming *stream = handle->stream; |
1516 | |
1517 | uvc_dbg(stream->dev, CALLS, "%s: not implemented\n" , __func__); |
1518 | return -EINVAL; |
1519 | } |
1520 | |
1521 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) |
1522 | { |
1523 | struct uvc_fh *handle = file->private_data; |
1524 | struct uvc_streaming *stream = handle->stream; |
1525 | |
1526 | uvc_dbg(stream->dev, CALLS, "%s\n" , __func__); |
1527 | |
1528 | return uvc_queue_mmap(queue: &stream->queue, vma); |
1529 | } |
1530 | |
1531 | static __poll_t uvc_v4l2_poll(struct file *file, poll_table *wait) |
1532 | { |
1533 | struct uvc_fh *handle = file->private_data; |
1534 | struct uvc_streaming *stream = handle->stream; |
1535 | |
1536 | uvc_dbg(stream->dev, CALLS, "%s\n" , __func__); |
1537 | |
1538 | return uvc_queue_poll(queue: &stream->queue, file, wait); |
1539 | } |
1540 | |
1541 | #ifndef CONFIG_MMU |
1542 | static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, |
1543 | unsigned long addr, unsigned long len, unsigned long pgoff, |
1544 | unsigned long flags) |
1545 | { |
1546 | struct uvc_fh *handle = file->private_data; |
1547 | struct uvc_streaming *stream = handle->stream; |
1548 | |
1549 | uvc_dbg(stream->dev, CALLS, "%s\n" , __func__); |
1550 | |
1551 | return uvc_queue_get_unmapped_area(&stream->queue, pgoff); |
1552 | } |
1553 | #endif |
1554 | |
1555 | const struct v4l2_ioctl_ops uvc_ioctl_ops = { |
1556 | .vidioc_querycap = uvc_ioctl_querycap, |
1557 | .vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap, |
1558 | .vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out, |
1559 | .vidioc_g_fmt_vid_cap = uvc_ioctl_g_fmt_vid_cap, |
1560 | .vidioc_g_fmt_vid_out = uvc_ioctl_g_fmt_vid_out, |
1561 | .vidioc_s_fmt_vid_cap = uvc_ioctl_s_fmt_vid_cap, |
1562 | .vidioc_s_fmt_vid_out = uvc_ioctl_s_fmt_vid_out, |
1563 | .vidioc_try_fmt_vid_cap = uvc_ioctl_try_fmt_vid_cap, |
1564 | .vidioc_try_fmt_vid_out = uvc_ioctl_try_fmt_vid_out, |
1565 | .vidioc_reqbufs = uvc_ioctl_reqbufs, |
1566 | .vidioc_querybuf = uvc_ioctl_querybuf, |
1567 | .vidioc_qbuf = uvc_ioctl_qbuf, |
1568 | .vidioc_expbuf = uvc_ioctl_expbuf, |
1569 | .vidioc_dqbuf = uvc_ioctl_dqbuf, |
1570 | .vidioc_create_bufs = uvc_ioctl_create_bufs, |
1571 | .vidioc_streamon = uvc_ioctl_streamon, |
1572 | .vidioc_streamoff = uvc_ioctl_streamoff, |
1573 | .vidioc_enum_input = uvc_ioctl_enum_input, |
1574 | .vidioc_g_input = uvc_ioctl_g_input, |
1575 | .vidioc_s_input = uvc_ioctl_s_input, |
1576 | .vidioc_queryctrl = uvc_ioctl_queryctrl, |
1577 | .vidioc_query_ext_ctrl = uvc_ioctl_query_ext_ctrl, |
1578 | .vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls, |
1579 | .vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls, |
1580 | .vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls, |
1581 | .vidioc_querymenu = uvc_ioctl_querymenu, |
1582 | .vidioc_g_selection = uvc_ioctl_g_selection, |
1583 | .vidioc_g_parm = uvc_ioctl_g_parm, |
1584 | .vidioc_s_parm = uvc_ioctl_s_parm, |
1585 | .vidioc_enum_framesizes = uvc_ioctl_enum_framesizes, |
1586 | .vidioc_enum_frameintervals = uvc_ioctl_enum_frameintervals, |
1587 | .vidioc_subscribe_event = uvc_ioctl_subscribe_event, |
1588 | .vidioc_unsubscribe_event = v4l2_event_unsubscribe, |
1589 | .vidioc_default = uvc_ioctl_default, |
1590 | }; |
1591 | |
1592 | const struct v4l2_file_operations uvc_fops = { |
1593 | .owner = THIS_MODULE, |
1594 | .open = uvc_v4l2_open, |
1595 | .release = uvc_v4l2_release, |
1596 | .unlocked_ioctl = video_ioctl2, |
1597 | #ifdef CONFIG_COMPAT |
1598 | .compat_ioctl32 = uvc_v4l2_compat_ioctl32, |
1599 | #endif |
1600 | .read = uvc_v4l2_read, |
1601 | .mmap = uvc_v4l2_mmap, |
1602 | .poll = uvc_v4l2_poll, |
1603 | #ifndef CONFIG_MMU |
1604 | .get_unmapped_area = uvc_v4l2_get_unmapped_area, |
1605 | #endif |
1606 | }; |
1607 | |
1608 | |