3 * @author Nicolas VIVIEN
6 * @brief V4L2 interface and functions
8 * @note Copyright (C) Nicolas VIVIEN
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/kernel.h>
30 #include <linux/version.h>
31 #include <linux/errno.h>
32 #include <linux/slab.h>
33 #include <linux/kref.h>
34 #include <linux/vmalloc.h>
35 #include <linux/usb.h>
37 #include <media/v4l2-common.h>
44 /* USER DEFINED V4L2-CONTROLS: */
45 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
46 #define V4L2_CID_AUTOEXPOSURE (V4L2_CID_PRIVATE_BASE + 0)
48 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
49 #define V4L2_CID_AUTOEXPOSURE (V4L2_CID_PRIVATE_BASE + 1)
52 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
53 #include <media/v4l2-ioctl.h>
56 static struct file_operations v4l_microdia_fops
;
58 * @var microdia_controls
59 * List of all V4Lv2 controls supported by the driver
61 static struct v4l2_queryctrl microdia_controls
[] = {
63 .id
= V4L2_CID_BRIGHTNESS
,
64 .type
= V4L2_CTRL_TYPE_INTEGER
,
69 .default_value
= 0x7f00,
72 .id
= V4L2_CID_WHITENESS
,
73 .type
= V4L2_CTRL_TYPE_INTEGER
,
78 .default_value
= 0x7f00,
82 .id = V4L2_CID_SATURATION,
83 .type = V4L2_CTRL_TYPE_INTEGER,
88 .default_value = 0x7f00,
92 .id
= V4L2_CID_CONTRAST
,
93 .type
= V4L2_CTRL_TYPE_INTEGER
,
98 .default_value
= 0x0000,
101 .id
= V4L2_CID_EXPOSURE
,
102 .type
= V4L2_CTRL_TYPE_INTEGER
,
107 .default_value
= 0x1000,
110 .id
= V4L2_CID_HFLIP
,
111 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
112 .name
= "Horizontal flip",
119 .id
= V4L2_CID_VFLIP
,
120 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
121 .name
= "Vertical flip",
128 .id
= V4L2_CID_SHARPNESS
,
129 .type
= V4L2_CTRL_TYPE_INTEGER
,
134 .default_value
= 0x1f,
137 .id
= V4L2_CID_RED_BALANCE
,
138 .type
= V4L2_CTRL_TYPE_INTEGER
,
139 .name
= "Red Balance",
143 .default_value
= 0x20,
146 .id
= V4L2_CID_BLUE_BALANCE
,
147 .type
= V4L2_CTRL_TYPE_INTEGER
,
148 .name
= "Blue Balance",
152 .default_value
= 0x20,
155 .id
= V4L2_CID_AUTOEXPOSURE
,
156 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
157 .name
= "Automatic exposure control",
164 .id
= V4L2_CID_AUTO_WHITE_BALANCE
,
165 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
166 .name
= "Automatic whitbalance control",
174 void v4l_add_jpegheader(struct usb_microdia
*dev
, __u8
*buffer
,
177 __u8 jpeg_header
[589] = {
178 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
179 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
180 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
181 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
182 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
183 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
184 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
185 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
186 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
187 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
188 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
189 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
190 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
191 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
192 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
194 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
195 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
196 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
197 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
198 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
199 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
200 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
201 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
202 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
203 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
204 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
205 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
206 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
207 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
208 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
209 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
210 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
211 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
212 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
213 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
214 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
215 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
216 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
217 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
218 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
219 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
220 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
221 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
222 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
223 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
224 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
225 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
226 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
227 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
228 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
229 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
230 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
231 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
232 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
233 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
234 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
235 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
236 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
238 __u8 qtable1
[128] = {
239 0x0d, 0x08, 0x08, 0x0d, 0x08, 0x08, 0x0d, 0x0d,
240 0x0d, 0x0d, 0x11, 0x0d, 0x0d, 0x11, 0x15, 0x21,
241 0x15, 0x15, 0x11, 0x11, 0x15, 0x2a, 0x1d, 0x1d,
242 0x19, 0x21, 0x32, 0x2a, 0x32, 0x32, 0x2e, 0x2a,
243 0x2e, 0x2e, 0x36, 0x3a, 0x4b, 0x43, 0x36, 0x3a,
244 0x47, 0x3a, 0x2e, 0x2e, 0x43, 0x5c, 0x43, 0x47,
245 0x4f, 0x54, 0x58, 0x58, 0x58, 0x32, 0x3f, 0x60,
246 0x64, 0x5c, 0x54, 0x64, 0x4b, 0x54, 0x58, 0x54,
247 0x0d, 0x11, 0x11, 0x15, 0x11, 0x15, 0x26, 0x15,
248 0x15, 0x26, 0x54, 0x36, 0x2e, 0x36, 0x54, 0x54,
249 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
250 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
251 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
252 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
253 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
254 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54
257 jpeg_header
[6] = 0x00;
258 jpeg_header
[71] = 0x01;
259 memcpy(jpeg_header
+ 7, qtable1
, 64);
260 memcpy(jpeg_header
+ 8 + 64, qtable1
+64, 64);
261 jpeg_header
[564] = dev
->vsettings
.format
.width
& 0xFF;
262 jpeg_header
[563] = (dev
->vsettings
.format
.width
>> 8) & 0xFF;
263 jpeg_header
[562] = dev
->vsettings
.format
.height
& 0xFF;
264 jpeg_header
[561] = (dev
->vsettings
.format
.height
>> 8) & 0xFF;
265 jpeg_header
[567] = 0x21;
267 memmove(buffer
+589, buffer
, buffer_size
);
268 memcpy(buffer
, jpeg_header
, 589);
271 * @brief Get V4L privileges
275 * @return 0 or negative error code
278 int v4l_get_privileges(struct file
*file
)
280 struct usb_microdia
*dev
;
283 dev
= video_get_drvdata(video_devdata(file
));
285 if (dev
->owner
== file
)
288 mutex_lock(&open_lock
);
289 if (dev
->owner
!= NULL
) {
295 mutex_unlock(&open_lock
);
300 * @brief Check whether there are V4L privileges
307 int v4l_has_privileges(struct file
*file
)
309 struct usb_microdia
*dev
;
312 dev
= video_get_drvdata(video_devdata(file
));
314 if (dev
->owner
== file
)
321 * @brief Drop V4L privileges
326 void v4l_drop_privileges(struct file
*file
)
328 struct usb_microdia
*dev
;
330 dev
= video_get_drvdata(video_devdata(file
));
332 if (dev
->owner
== file
)
337 * @brief Enable video stream
339 * @param dev Pointer to device structure
340 * @param mode Mode for video stream
342 * @returns 0 or negative error value
345 int v4l2_enable_video(struct usb_microdia
*dev
, int mode
)
349 if (mode
== MICRODIA_MODE_IDLE
) {
350 dev_microdia_enable_video(dev
, 0);
351 usb_microdia_uninit_urbs(dev
);
352 microdia_queue_enable(&dev
->queue
, 0);
357 if (dev
->mode
!= MICRODIA_MODE_IDLE
)
360 if (microdia_queue_enable(&dev
->queue
, 1) < 0)
363 ret
= usb_microdia_init_urbs(dev
);
368 dev_microdia_enable_video(dev
, 1);
369 dev_microdia_camera_settings(dev
);
370 dev
->queue
.flags
&= ~MICRODIA_QUEUE_DROP_INCOMPLETE
;
377 * @param inode Pointer on an inode
378 * @param fp File pointer
380 * @returns 0 if all is OK
382 * @brief Open the video device
384 * This function permits to open a video device (/dev/videoX)
386 static int v4l_microdia_open(struct inode
*inode
, struct file
*fp
)
390 struct usb_microdia
*dev
;
391 struct video_device
*vdev
;
393 mutex_lock(&open_lock
);
395 vdev
= video_devdata(fp
);
396 dev
= video_get_drvdata(video_devdata(fp
));
398 fp
->private_data
= vdev
;
400 kref_get(&dev
->vopen
);
402 mutex_unlock(&open_lock
);
408 * @param inode Pointer on inode
409 * @param fp File pointer
411 * @returns 0 if all is OK
413 * @brief Release an opened file.
415 * This function permits to release an opened file with the 'open' method.
417 static int v4l_microdia_release(struct inode
*inode
, struct file
*fp
)
419 struct usb_microdia
*dev
;
420 struct video_device
*vdev
;
422 mutex_lock(&open_lock
);
424 vdev
= video_devdata(fp
);
425 dev
= video_get_drvdata(video_devdata(fp
));
427 if (v4l_has_privileges(fp
)) {
428 v4l2_enable_video(dev
, MICRODIA_MODE_IDLE
);
430 mutex_lock(&dev
->queue
.mutex
);
431 microdia_free_buffers(&dev
->queue
);
432 mutex_unlock(&dev
->queue
.mutex
);
435 v4l_drop_privileges(fp
);
437 kref_put(&dev
->vopen
, usb_microdia_delete
);
439 mutex_unlock(&open_lock
);
445 * @param fp File pointer
447 * @retval buf Buffer in user space
451 * @returns Count value
453 * @brief Read the video device
455 * This function is called by the application is reading the video device.
457 static ssize_t
v4l_microdia_read(struct file
*fp
, char __user
*buf
,
458 size_t count
, loff_t
*f_pos
)
462 struct v4l2_buffer buffer
;
463 struct usb_microdia
*dev
;
465 dev
= video_get_drvdata(video_devdata(fp
));
467 ret
= v4l_get_privileges(fp
);
471 if (dev
->mode
!= MICRODIA_MODE_IDLE
&&
472 dev
->mode
!= MICRODIA_MODE_READ
)
475 buffer
.type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
476 buffer
.memory
= V4L2_MEMORY_MMAP
;
477 if (dev
->mode
== MICRODIA_MODE_IDLE
) {
478 nbuffers
= microdia_alloc_buffers(&dev
->queue
, 2,
479 dev
->vsettings
.format
.sizeimage
);
483 for (i
= 0; i
< nbuffers
; i
++) {
484 buffer
= dev
->queue
.buffer
[i
].buf
;
485 microdia_queue_buffer(&dev
->queue
, &buffer
);
488 ret
= v4l2_enable_video(dev
, MICRODIA_MODE_READ
);
493 if (dev
->queue
.read_buffer
== NULL
) {
494 ret
= microdia_dequeue_buffer(&dev
->queue
, &buffer
,
495 fp
->f_flags
& O_NONBLOCK
);
498 dev
->queue
.read_buffer
= &dev
->queue
.buffer
[buffer
.index
];
500 buffer
= dev
->queue
.read_buffer
->buf
;
503 count
= min((size_t)(buffer
.bytesused
- *f_pos
), count
);
504 if (copy_to_user(buf
, dev
->queue
.mem
+ buffer
.m
.offset
+ *f_pos
, count
))
508 if (*f_pos
>= buffer
.bytesused
) {
509 dev
->queue
.read_buffer
= NULL
;
510 microdia_queue_buffer(&dev
->queue
, &buffer
);
518 * @param fp File pointer
521 * @returns 0 if all is OK
523 * @brief Polling function
525 static unsigned int v4l_microdia_poll(struct file
*fp
, poll_table
*wait
)
527 struct usb_microdia
*dev
;
528 struct video_device
*vdev
;
530 vdev
= video_devdata(fp
);
531 dev
= video_get_drvdata(video_devdata(fp
));
533 UDIA_STREAM("Poll\n");
535 if (vdev
== NULL
|| dev
== NULL
)
538 return microdia_queue_poll(&dev
->queue
, fp
, wait
);
545 static void microdia_vm_open(struct vm_area_struct
*vma
)
547 struct microdia_buffer
*buffer
= vma
->vm_private_data
;
548 buffer
->vma_use_count
++;
556 static void microdia_vm_close(struct vm_area_struct
*vma
)
558 struct microdia_buffer
*buffer
= vma
->vm_private_data
;
559 buffer
->vma_use_count
--;
562 struct vm_operations_struct microdia_vm_ops
= {
563 .open
= microdia_vm_open
,
564 .close
= microdia_vm_close
568 * @param fp File pointer
569 * @param vma VMA structure
571 * @returns 0 if all is OK
575 * This function permits to map a memory space.
577 static int v4l_microdia_mmap(struct file
*fp
, struct vm_area_struct
*vma
)
580 unsigned long addr
, start
, size
;
584 struct usb_microdia
*dev
;
585 struct video_device
*vdev
;
586 struct microdia_buffer
*buffer
= NULL
;
588 vdev
= video_devdata(fp
);
589 dev
= video_get_drvdata(video_devdata(fp
));
591 UDIA_STREAM("mmap\n");
593 start
= vma
->vm_start
;
594 size
= vma
->vm_end
- vma
->vm_start
;
596 mutex_lock(&dev
->queue
.mutex
);
598 for (i
= 0; i
< dev
->queue
.count
; ++i
) {
599 buffer
= &dev
->queue
.buffer
[i
];
600 if ((buffer
->buf
.m
.offset
>> PAGE_SHIFT
) == vma
->vm_pgoff
)
604 if (i
== dev
->queue
.count
|| size
!= dev
->queue
.buf_size
) {
609 vma
->vm_flags
|= VM_IO
;
611 addr
= (unsigned long)dev
->queue
.mem
+ buffer
->buf
.m
.offset
;
613 page
= vmalloc_to_page((void *)addr
);
614 ret
= vm_insert_page(vma
, start
, page
);
623 vma
->vm_ops
= µdia_vm_ops
;
624 vma
->vm_private_data
= buffer
;
625 microdia_vm_open(vma
);
627 mutex_unlock(&dev
->queue
.mutex
);
639 int microdia_vidioc_querycap(struct file
*file
, void *priv
,
640 struct v4l2_capability
*cap
)
642 struct usb_microdia
*dev
;
644 dev
= video_get_drvdata(priv
);
646 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
648 strlcpy(cap
->driver
, "microdia", sizeof(cap
->driver
));
649 cap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
650 | V4L2_CAP_READWRITE
;
651 cap
->version
= (__u32
) DRIVER_VERSION_NUM
,
652 strlcpy(cap
->card
, dev
->vdev
->name
, sizeof(cap
->card
));
654 if (usb_make_path(dev
->udev
, cap
->bus_info
, sizeof(cap
->bus_info
)) < 0)
655 strlcpy(cap
->bus_info
, dev
->vdev
->name
, sizeof(cap
->bus_info
));
664 * @return 0 or negative error code
667 int microdia_vidioc_enum_input(struct file
*file
, void *priv
,
668 struct v4l2_input
*input
)
670 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", input
->index
);
675 strlcpy(input
->name
, "Webcam", sizeof(input
->name
));
676 input
->type
= V4L2_INPUT_TYPE_CAMERA
;
687 * @return 0 or negative error code
690 int microdia_vidioc_g_input(struct file
*file
, void *priv
, unsigned int *index
)
692 UDIA_DEBUG("GET INPUT %d\n", *index
);
705 * @return 0 or negative error code
708 int microdia_vidioc_s_input(struct file
*file
, void *priv
, unsigned int index
)
710 UDIA_DEBUG("SET INPUT %d\n", index
);
712 if (v4l_get_privileges(file
) < 0)
726 * @return 0 or negative error code
729 int microdia_vidioc_queryctrl(struct file
*file
, void *priv
,
730 struct v4l2_queryctrl
*ctrl
)
735 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl
->id
);
737 nbr
= sizeof(microdia_controls
)/sizeof(struct v4l2_queryctrl
);
739 for (i
= 0; i
< nbr
; i
++) {
740 if (microdia_controls
[i
].id
== ctrl
->id
) {
741 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
742 memcpy(ctrl
, µdia_controls
[i
],
743 sizeof(struct v4l2_queryctrl
));
759 * @return 0 or negative error code
762 int microdia_vidioc_g_ctrl(struct file
*file
, void *priv
,
763 struct v4l2_control
*ctrl
)
765 struct usb_microdia
*dev
;
767 dev
= video_get_drvdata(priv
);
769 UDIA_DEBUG("GET CTRL id=%d\n", ctrl
->id
);
772 case V4L2_CID_BRIGHTNESS
:
773 ctrl
->value
= dev
->vsettings
.brightness
;
776 case V4L2_CID_EXPOSURE
:
777 ctrl
->value
= dev
->vsettings
.exposure
;
780 case V4L2_CID_WHITENESS
:
781 ctrl
->value
= dev
->vsettings
.whiteness
;
784 case V4L2_CID_SATURATION:
785 ctrl->value = dev->vsettings.colour;
788 case V4L2_CID_CONTRAST
:
789 ctrl
->value
= dev
->vsettings
.contrast
;
793 ctrl
->value
= dev
->vsettings
.hflip
;
797 ctrl
->value
= dev
->vsettings
.vflip
;
800 case V4L2_CID_SHARPNESS
:
801 ctrl
->value
= dev
->vsettings
.sharpness
;
804 case V4L2_CID_RED_BALANCE
:
805 ctrl
->value
= dev
->vsettings
.rgb_gain
[0];
808 case V4L2_CID_BLUE_BALANCE
:
809 ctrl
->value
= dev
->vsettings
.rgb_gain
[3];
812 case V4L2_CID_AUTOEXPOSURE
:
813 ctrl
->value
= dev
->vsettings
.auto_exposure
;
816 case V4L2_CID_AUTO_WHITE_BALANCE
:
817 ctrl
->value
= dev
->vsettings
.auto_whitebalance
;
827 * @brief Apply v4l2 settings on camera
831 * @param ctrl V4L2 control structure
833 * @returns 0 or negative error value
836 int microdia_vidioc_s_ctrl(struct file
*file
, void *priv
,
837 struct v4l2_control
*ctrl
)
839 struct usb_microdia
*dev
;
841 dev
= video_get_drvdata(priv
);
843 UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl
->id
, ctrl
->value
);
846 case V4L2_CID_BRIGHTNESS
:
847 dev
->vsettings
.brightness
= (0xff00 & ctrl
->value
);
848 dev_microdia_camera_set_brightness(dev
);
851 case V4L2_CID_EXPOSURE
:
852 dev
->vsettings
.exposure
= (0xff00 & ctrl
->value
);
853 dev_microdia_camera_set_exposure(dev
);
856 case V4L2_CID_WHITENESS
:
857 dev
->vsettings
.whiteness
= (0xff00 & ctrl
->value
);
858 dev_microdia_camera_set_gamma(dev
);
861 case V4L2_CID_SATURATION:
862 dev->vsettings.colour = (0xff00 & ctrl->value);
865 case V4L2_CID_CONTRAST
:
866 dev
->vsettings
.contrast
= (0xff00 & ctrl
->value
);
867 dev_microdia_camera_set_contrast(dev
);
871 dev
->vsettings
.hflip
= ctrl
->value
;
872 dev_microdia_camera_set_hvflip(dev
);
876 dev
->vsettings
.vflip
= ctrl
->value
;
877 dev_microdia_camera_set_hvflip(dev
);
880 case V4L2_CID_SHARPNESS
:
881 dev
->vsettings
.sharpness
= ctrl
->value
;
882 dev_microdia_camera_set_sharpness(dev
);
885 case V4L2_CID_RED_BALANCE
:
886 dev
->vsettings
.rgb_gain
[0] = ctrl
->value
;
887 dev_microdia_camera_set_rgb_gain(dev
);
890 case V4L2_CID_BLUE_BALANCE
:
891 dev
->vsettings
.rgb_gain
[3] = ctrl
->value
;
892 dev_microdia_camera_set_rgb_gain(dev
);
895 case V4L2_CID_AUTOEXPOSURE
:
896 dev
->vsettings
.auto_exposure
= ctrl
->value
;
897 dev_microdia_camera_set_auto_exposure(dev
);
900 case V4L2_CID_AUTO_WHITE_BALANCE
:
901 dev
->vsettings
.auto_whitebalance
= ctrl
->value
;
902 dev_microdia_camera_set_auto_whitebalance(dev
);
917 * @return 0 or negative error code
920 int microdia_vidioc_enum_fmt_cap(struct file
*file
, void *priv
,
921 struct v4l2_fmtdesc
*fmt
)
923 struct usb_microdia
*dev
;
925 dev
= video_get_drvdata(priv
);
927 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmt
->index
);
929 if (fmt
->index
>= dev
->camera
.nfmts
)
933 fmt
->pixelformat
= dev
->camera
.fmts
[fmt
->index
].pix_fmt
;
934 memcpy(fmt
->description
, dev
->camera
.fmts
[fmt
->index
].desc
, 32);
944 * @return 0 or negative error code
947 int microdia_vidioc_try_fmt_cap(struct file
*file
, void *priv
,
948 struct v4l2_format
*fmt
)
951 struct usb_microdia
*dev
;
953 dev
= video_get_drvdata(priv
);
954 UDIA_DEBUG("TRY FMT %d\n", fmt
->type
);
956 /* when this code is used prevents mplayer from setting outfmt
957 if(fmt->fmt.pix.field != V4L2_FIELD_NONE)
961 for (index
= 0; index
< dev
->camera
.nfmts
; index
++)
962 if (dev
->camera
.fmts
[index
].pix_fmt
== fmt
->fmt
.pix
.pixelformat
)
965 if (index
>= dev
->camera
.nfmts
)
968 sn9c20x_get_closest_resolution(dev
, &fmt
->fmt
.pix
.width
,
969 &fmt
->fmt
.pix
.height
);
971 fmt
->fmt
.pix
.bytesperline
= fmt
->fmt
.pix
.width
*
972 dev
->camera
.fmts
[index
].depth
/ 8;
974 fmt
->fmt
.pix
.sizeimage
= fmt
->fmt
.pix
.height
*
975 fmt
->fmt
.pix
.bytesperline
;
977 fmt
->fmt
.pix
.colorspace
= V4L2_COLORSPACE_SRGB
;
978 fmt
->fmt
.pix
.priv
= index
;
991 int microdia_vidioc_g_fmt_cap(struct file
*file
, void *priv
,
992 struct v4l2_format
*fmt
)
994 struct usb_microdia
*dev
;
996 dev
= video_get_drvdata(priv
);
998 UDIA_DEBUG("GET FMT %d\n", fmt
->type
);
1000 memcpy(&(fmt
->fmt
.pix
), &(dev
->vsettings
.format
), sizeof(fmt
->fmt
.pix
));
1011 * @return 0 or negative error code
1014 int microdia_vidioc_s_fmt_cap(struct file
*file
, void *priv
,
1015 struct v4l2_format
*fmt
)
1017 struct usb_microdia
*dev
;
1020 dev
= video_get_drvdata(priv
);
1022 UDIA_DEBUG("SET FMT %d : %d\n", fmt
->type
, fmt
->fmt
.pix
.pixelformat
);
1024 if (v4l_get_privileges(file
) < 0)
1027 if (microdia_queue_streaming(&dev
->queue
))
1030 ret
= microdia_vidioc_try_fmt_cap(file
, priv
, fmt
);
1034 sn9c20x_set_resolution(dev
, fmt
->fmt
.pix
.width
, fmt
->fmt
.pix
.height
);
1035 dev
->camera
.fmts
[fmt
->fmt
.pix
.priv
].set_format(dev
);
1036 memcpy(&(dev
->vsettings
.format
), &(fmt
->fmt
.pix
), sizeof(fmt
->fmt
.pix
));
1046 * @return 0 or negative error code
1049 int microdia_vidioc_reqbufs(struct file
*file
, void *priv
,
1050 struct v4l2_requestbuffers
*request
)
1053 struct usb_microdia
*dev
;
1055 dev
= video_get_drvdata(priv
);
1057 if (v4l_get_privileges(file
) < 0) {
1062 if (request
->memory
!= V4L2_MEMORY_MMAP
||
1063 request
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
) {
1068 if (microdia_queue_streaming(&dev
->queue
)) {
1073 ret
= microdia_alloc_buffers(&dev
->queue
, request
->count
,
1074 dev
->vsettings
.format
.sizeimage
);
1078 request
->count
= ret
;
1080 UDIA_INFO("Buffers Allocated %d\n", request
->count
);
1090 * @return 0 or negative error code
1093 int microdia_vidioc_querybuf(struct file
*file
, void *priv
,
1094 struct v4l2_buffer
*buffer
)
1096 struct usb_microdia
*dev
;
1098 dev
= video_get_drvdata(priv
);
1100 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buffer
->index
, dev
->queue
.count
);
1102 if (buffer
->memory
!= V4L2_MEMORY_MMAP
||
1103 buffer
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1106 if (!v4l_has_privileges(file
))
1109 return microdia_query_buffer(&dev
->queue
, buffer
);
1117 * @return 0 or negative error code
1120 int microdia_vidioc_qbuf(struct file
*file
, void *priv
,
1121 struct v4l2_buffer
*buffer
)
1123 struct usb_microdia
*dev
;
1125 dev
= video_get_drvdata(priv
);
1127 UDIA_DEBUG("VIDIOC_QBUF\n");
1129 if (!v4l_has_privileges(file
))
1132 return microdia_queue_buffer(&dev
->queue
, buffer
);
1140 * @return 0 or negative error code
1143 int microdia_vidioc_dqbuf(struct file
*file
, void *priv
,
1144 struct v4l2_buffer
*buffer
)
1146 struct usb_microdia
*dev
;
1149 dev
= video_get_drvdata(priv
);
1151 UDIA_DEBUG("VIDIOC_DQBUF\n");
1153 if (!v4l_has_privileges(file
))
1156 ret
= microdia_dequeue_buffer(&dev
->queue
, buffer
,
1157 file
->f_flags
& O_NONBLOCK
);
1161 if (dev
->vsettings
.format
.pixelformat
== V4L2_PIX_FMT_JPEG
) {
1162 UDIA_INFO("Adding JPEG Header\n");
1163 v4l_add_jpegheader(dev
, dev
->queue
.mem
+ buffer
->m
.offset
,
1165 buffer
->bytesused
+= 589;
1176 * @return 0 or negative error code
1179 int microdia_vidioc_streamon(struct file
*file
, void *priv
,
1180 enum v4l2_buf_type type
)
1182 struct usb_microdia
*dev
;
1184 dev
= video_get_drvdata(priv
);
1186 UDIA_DEBUG("VIDIOC_STREAMON\n");
1188 if (!v4l_has_privileges(file
))
1191 if (dev
->mode
!= MICRODIA_MODE_IDLE
)
1194 return v4l2_enable_video(dev
, MICRODIA_MODE_STREAM
);
1202 * @return 0 or negative error code
1205 int microdia_vidioc_streamoff(struct file
*file
, void *priv
,
1206 enum v4l2_buf_type type
)
1208 struct usb_microdia
*dev
;
1210 dev
= video_get_drvdata(priv
);
1212 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1214 if (!v4l_has_privileges(file
))
1217 return v4l2_enable_video(dev
, MICRODIA_MODE_IDLE
);
1225 * @return 0 or negative error code
1228 int microdia_vidioc_g_param(struct file
*file
, void *priv
,
1229 struct v4l2_streamparm
*param
)
1231 struct usb_microdia
*dev
;
1234 dev
= video_get_drvdata(priv
);
1236 if (param
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1239 param
->parm
.capture
.capability
= 0;
1240 param
->parm
.capture
.capturemode
= 0;
1241 param
->parm
.capture
.timeperframe
.numerator
= 1;
1242 param
->parm
.capture
.timeperframe
.denominator
= 30;
1243 param
->parm
.capture
.readbuffers
= 2;
1244 param
->parm
.capture
.extendedmode
= 0;
1254 * @return 0 or negative error code
1257 int microdia_vidioc_s_param(struct file
*file
, void *priv
,
1258 struct v4l2_streamparm
*param
)
1260 struct usb_microdia
*dev
;
1262 dev
= video_get_drvdata(priv
);
1264 if (v4l_get_privileges(file
))
1267 if (param
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1274 * @param inode Inode pointer
1275 * @param fp File pointer
1276 * @param cmd Command
1277 * @param arg Arguements of the command
1279 * @returns 0 if all is OK
1281 * @brief Manage IOCTL
1283 * This function permits to manage all the IOCTL from the application.
1285 static int v4l_microdia_ioctl(struct inode
*inode
, struct file
*fp
,
1286 unsigned int cmd
, unsigned long arg
)
1289 struct usb_microdia
*dev
;
1290 struct video_device
*vdev
;
1292 vdev
= video_devdata(fp
);
1293 dev
= video_get_drvdata(video_devdata(fp
));
1295 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd
);
1297 if (dev
== NULL
|| vdev
== NULL
)
1300 err
= video_ioctl2(inode
, fp
, cmd
, arg
);
1306 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
1307 static const struct v4l2_ioctl_ops microdia_v4l2_ioctl_ops
= {
1308 .vidioc_querycap
= microdia_vidioc_querycap
,
1309 .vidioc_enum_fmt_vid_cap
= microdia_vidioc_enum_fmt_cap
,
1310 .vidioc_try_fmt_vid_cap
= microdia_vidioc_try_fmt_cap
,
1311 .vidioc_s_fmt_vid_cap
= microdia_vidioc_s_fmt_cap
,
1312 .vidioc_g_fmt_vid_cap
= microdia_vidioc_g_fmt_cap
,
1313 .vidioc_enum_input
= microdia_vidioc_enum_input
,
1314 .vidioc_g_input
= microdia_vidioc_g_input
,
1315 .vidioc_s_input
= microdia_vidioc_s_input
,
1316 .vidioc_streamon
= microdia_vidioc_streamon
,
1317 .vidioc_streamoff
= microdia_vidioc_streamoff
,
1318 .vidioc_queryctrl
= microdia_vidioc_queryctrl
,
1319 .vidioc_g_ctrl
= microdia_vidioc_g_ctrl
,
1320 .vidioc_s_ctrl
= microdia_vidioc_s_ctrl
,
1321 .vidioc_g_parm
= microdia_vidioc_g_param
,
1322 .vidioc_s_parm
= microdia_vidioc_s_param
,
1323 .vidioc_reqbufs
= microdia_vidioc_reqbufs
,
1324 .vidioc_qbuf
= microdia_vidioc_qbuf
,
1325 .vidioc_dqbuf
= microdia_vidioc_dqbuf
,
1326 .vidioc_querybuf
= microdia_vidioc_querybuf
,
1331 * @param dev Device structure
1333 * @returns 0 if all is OK
1335 * @brief Register the video device
1337 * This function permits to register the USB device to the video device.
1339 int v4l_microdia_register_video_device(struct usb_microdia
*dev
)
1343 strcpy(dev
->vdev
->name
, DRIVER_DESC
);
1345 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
1346 dev
->vdev
->dev
= &dev
->interface
->dev
;
1347 dev
->vdev
->owner
= THIS_MODULE
;
1348 dev
->vdev
->type
= VID_TYPE_CAPTURE
;
1350 dev
->vdev
->dev
= dev
->interface
->dev
;
1352 dev
->vdev
->current_norm
= 0;
1353 dev
->vdev
->tvnorms
= 0;
1354 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1355 dev
->vdev
->hardware
= VID_HARDWARE_MICRODIA
;
1357 dev
->vdev
->fops
= &v4l_microdia_fops
;
1358 dev
->vdev
->release
= video_device_release
;
1359 dev
->vdev
->minor
= -1;
1361 if (log_level
& MICRODIA_DEBUG
)
1362 dev
->vdev
->debug
= V4L2_DEBUG_IOCTL_ARG
;
1364 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
1365 dev
->vdev
->vidioc_querycap
= microdia_vidioc_querycap
;
1366 dev
->vdev
->vidioc_enum_fmt_cap
= microdia_vidioc_enum_fmt_cap
;
1367 dev
->vdev
->vidioc_try_fmt_cap
= microdia_vidioc_try_fmt_cap
;
1368 dev
->vdev
->vidioc_s_fmt_cap
= microdia_vidioc_s_fmt_cap
;
1369 dev
->vdev
->vidioc_g_fmt_cap
= microdia_vidioc_g_fmt_cap
;
1370 dev
->vdev
->vidioc_enum_input
= microdia_vidioc_enum_input
;
1371 dev
->vdev
->vidioc_g_input
= microdia_vidioc_g_input
;
1372 dev
->vdev
->vidioc_s_input
= microdia_vidioc_s_input
;
1373 dev
->vdev
->vidioc_streamon
= microdia_vidioc_streamon
;
1374 dev
->vdev
->vidioc_streamoff
= microdia_vidioc_streamoff
;
1375 dev
->vdev
->vidioc_queryctrl
= microdia_vidioc_queryctrl
;
1376 dev
->vdev
->vidioc_g_ctrl
= microdia_vidioc_g_ctrl
;
1377 dev
->vdev
->vidioc_s_ctrl
= microdia_vidioc_s_ctrl
;
1378 dev
->vdev
->vidioc_g_parm
= microdia_vidioc_g_param
;
1379 dev
->vdev
->vidioc_s_parm
= microdia_vidioc_s_param
;
1380 dev
->vdev
->vidioc_reqbufs
= microdia_vidioc_reqbufs
;
1381 dev
->vdev
->vidioc_qbuf
= microdia_vidioc_qbuf
;
1382 dev
->vdev
->vidioc_dqbuf
= microdia_vidioc_dqbuf
;
1383 dev
->vdev
->vidioc_querybuf
= microdia_vidioc_querybuf
;
1385 dev
->vdev
->ioctl_ops
= µdia_v4l2_ioctl_ops
;
1388 video_set_drvdata(dev
->vdev
, dev
);
1390 microdia_queue_init(&dev
->queue
);
1392 err
= video_register_device(dev
->vdev
, VFL_TYPE_GRABBER
, -1);
1395 UDIA_ERROR("Video register fail !\n");
1397 UDIA_INFO("Microdia USB 2.0 Webcam is now controlling "
1398 "video device /dev/video%d\n",
1406 * @param dev Device structure
1408 * @returns 0 if all is OK
1410 * @brief Unregister the video device
1412 * This function permits to unregister the video device.
1414 int v4l_microdia_unregister_video_device(struct usb_microdia
*dev
)
1416 UDIA_INFO("Microdia USB 2.0 Webcam releases control of video "
1417 "device /dev/video%d\n", dev
->vdev
->minor
);
1419 video_set_drvdata(dev
->vdev
, NULL
);
1420 video_unregister_device(dev
->vdev
);
1427 * @var v4l_microdia_fops
1429 * This variable contains some callback
1431 static struct file_operations v4l_microdia_fops
= {
1432 .owner
= THIS_MODULE
,
1433 .open
= v4l_microdia_open
,
1434 .release
= v4l_microdia_release
,
1435 .read
= v4l_microdia_read
,
1436 .poll
= v4l_microdia_poll
,
1437 .mmap
= v4l_microdia_mmap
,
1438 .ioctl
= v4l_microdia_ioctl
,
1439 #ifdef CONFIG_COMPAT
1440 .compat_ioctl
= v4l_compat_ioctl32
,