Merge ov966x.c, ov7670.c and ov7660.c into omnivision.c
[microdia.git] / microdia-v4l.c
blob936ca84958ea4fe9dd40166d139c73272123ee71
1 /**
2 * @file microdia-v4l.c
3 * @author Nicolas VIVIEN
4 * @date 2008-02-01
6 * @brief V4L2 interface and functions
8 * @note Copyright (C) Nicolas VIVIEN
10 * @par Licences
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
15 * any later version.
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>
36 #include <linux/mm.h>
37 #include <media/v4l2-common.h>
40 #include "microdia.h"
41 #include "sn9c20x.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)
47 #else
48 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
49 #define V4L2_CID_AUTOEXPOSURE (V4L2_CID_PRIVATE_BASE + 1)
50 #endif
52 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
53 #include <media/v4l2-ioctl.h>
54 #endif
56 static struct file_operations v4l_microdia_fops;
57 /**
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,
65 .name = "Brightness",
66 .minimum = 0,
67 .maximum = 0xff00,
68 .step = 1,
69 .default_value = 0x7f00,
72 .id = V4L2_CID_WHITENESS,
73 .type = V4L2_CTRL_TYPE_INTEGER,
74 .name = "Whiteness",
75 .minimum = 0,
76 .maximum = 0xff00,
77 .step = 1,
78 .default_value = 0x7f00,
82 .id = V4L2_CID_SATURATION,
83 .type = V4L2_CTRL_TYPE_INTEGER,
84 .name = "Saturation",
85 .minimum = 0,
86 .maximum = 0xff00,
87 .step = 1,
88 .default_value = 0x7f00,
92 .id = V4L2_CID_CONTRAST,
93 .type = V4L2_CTRL_TYPE_INTEGER,
94 .name = "Contrast",
95 .minimum = 0,
96 .maximum = 0xff00,
97 .step = 1,
98 .default_value = 0x0000,
101 .id = V4L2_CID_EXPOSURE,
102 .type = V4L2_CTRL_TYPE_INTEGER,
103 .name = "Exposure",
104 .minimum = 0,
105 .maximum = 0xff00,
106 .step = 1,
107 .default_value = 0x1000,
110 .id = V4L2_CID_HFLIP,
111 .type = V4L2_CTRL_TYPE_BOOLEAN,
112 .name = "Horizontal flip",
113 .minimum = 0,
114 .maximum = 1,
115 .step = 1,
116 .default_value = 0,
119 .id = V4L2_CID_VFLIP,
120 .type = V4L2_CTRL_TYPE_BOOLEAN,
121 .name = "Vertical flip",
122 .minimum = 0,
123 .maximum = 1,
124 .step = 1,
125 .default_value = 0,
128 .id = V4L2_CID_SHARPNESS,
129 .type = V4L2_CTRL_TYPE_INTEGER,
130 .name = "Sharpness",
131 .minimum = 0,
132 .maximum = 0x3f,
133 .step = 1,
134 .default_value = 0x1f,
137 .id = V4L2_CID_RED_BALANCE,
138 .type = V4L2_CTRL_TYPE_INTEGER,
139 .name = "Red Balance",
140 .minimum = 0,
141 .maximum = 0x7f,
142 .step = 1,
143 .default_value = 0x20,
146 .id = V4L2_CID_BLUE_BALANCE,
147 .type = V4L2_CTRL_TYPE_INTEGER,
148 .name = "Blue Balance",
149 .minimum = 0,
150 .maximum = 0x7f,
151 .step = 1,
152 .default_value = 0x20,
155 .id = V4L2_CID_AUTOEXPOSURE,
156 .type = V4L2_CTRL_TYPE_BOOLEAN,
157 .name = "Automatic exposure control",
158 .minimum = 0,
159 .maximum = 1,
160 .step = 1,
161 .default_value = 0,
164 .id = V4L2_CID_AUTO_WHITE_BALANCE,
165 .type = V4L2_CTRL_TYPE_BOOLEAN,
166 .name = "Automatic whitbalance control",
167 .minimum = 0,
168 .maximum = 1,
169 .step = 1,
170 .default_value = 0,
174 void v4l_add_jpegheader(struct usb_microdia *dev, __u8 *buffer,
175 __u32 buffer_size)
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
273 * @param file
275 * @return 0 or negative error code
278 int v4l_get_privileges(struct file *file)
280 struct usb_microdia *dev;
281 int ret = 0;
283 dev = video_get_drvdata(video_devdata(file));
285 if (dev->owner == file)
286 return 0;
288 mutex_lock(&open_lock);
289 if (dev->owner != NULL) {
290 ret = -EBUSY;
291 goto done;
293 dev->owner = file;
294 done:
295 mutex_unlock(&open_lock);
296 return ret;
300 * @brief Check whether there are V4L privileges
302 * @param file
304 * @return 0 or 1
307 int v4l_has_privileges(struct file *file)
309 struct usb_microdia *dev;
310 int ret = 0;
312 dev = video_get_drvdata(video_devdata(file));
314 if (dev->owner == file)
315 ret = 1;
317 return ret;
321 * @brief Drop V4L privileges
323 * @param file
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)
333 dev->owner = NULL;
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)
347 int ret;
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);
353 dev->mode = mode;
354 return 0;
357 if (dev->mode != MICRODIA_MODE_IDLE)
358 return -EBUSY;
360 if (microdia_queue_enable(&dev->queue, 1) < 0)
361 return -EBUSY;
363 ret = usb_microdia_init_urbs(dev);
365 if (ret)
366 return ret;
368 dev_microdia_enable_video(dev, 1);
369 dev_microdia_camera_settings(dev);
370 dev->queue.flags &= ~MICRODIA_QUEUE_DROP_INCOMPLETE;
371 dev->mode = mode;
373 return 0;
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)
388 int ret = 0;
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);
403 return ret;
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);
440 return 0;
445 * @param fp File pointer
447 * @retval buf Buffer in user space
448 * @retval count
449 * @retval f_pos
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)
460 int i, ret;
461 int nbuffers;
462 struct v4l2_buffer buffer;
463 struct usb_microdia *dev;
465 dev = video_get_drvdata(video_devdata(fp));
467 ret = v4l_get_privileges(fp);
468 if (ret < 0)
469 return ret;
471 if (dev->mode != MICRODIA_MODE_IDLE &&
472 dev->mode != MICRODIA_MODE_READ)
473 return -EBUSY;
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);
480 if (nbuffers < 0)
481 return nbuffers;
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);
489 if (ret < 0)
490 return ret;
493 if (dev->queue.read_buffer == NULL) {
494 ret = microdia_dequeue_buffer(&dev->queue, &buffer,
495 fp->f_flags & O_NONBLOCK);
496 if (ret < 0)
497 return ret;
498 dev->queue.read_buffer = &dev->queue.buffer[buffer.index];
499 } else {
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))
505 return -EFAULT;
507 *f_pos += count;
508 if (*f_pos >= buffer.bytesused) {
509 dev->queue.read_buffer = NULL;
510 microdia_queue_buffer(&dev->queue, &buffer);
511 *f_pos = 0;
513 return count;
518 * @param fp File pointer
519 * @param wait
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)
536 return -EFAULT;
538 return microdia_queue_poll(&dev->queue, fp, wait);
542 * @param vma
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++;
553 * @param vma
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
573 * @brief Memory map
575 * This function permits to map a memory space.
577 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
579 struct page *page;
580 unsigned long addr, start, size;
581 unsigned int i;
582 int ret = 0;
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)
601 break;
604 if (i == dev->queue.count || size != dev->queue.buf_size) {
605 ret = -EINVAL;
606 goto done;
609 vma->vm_flags |= VM_IO;
611 addr = (unsigned long)dev->queue.mem + buffer->buf.m.offset;
612 while (size > 0) {
613 page = vmalloc_to_page((void *)addr);
614 ret = vm_insert_page(vma, start, page);
615 if (ret < 0)
616 goto done;
618 start += PAGE_SIZE;
619 addr += PAGE_SIZE;
620 size -= PAGE_SIZE;
623 vma->vm_ops = &microdia_vm_ops;
624 vma->vm_private_data = buffer;
625 microdia_vm_open(vma);
626 done:
627 mutex_unlock(&dev->queue.mutex);
628 return ret;
632 * @param file
633 * @param priv
634 * @param cap
636 * @return 0
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));
656 return 0;
660 * @param file
661 * @param priv
662 * @param input
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);
672 if (input->index)
673 return -EINVAL;
675 strlcpy(input->name, "Webcam", sizeof(input->name));
676 input->type = V4L2_INPUT_TYPE_CAMERA;
677 input->std = 0;
679 return 0;
683 * @param file
684 * @param priv
685 * @param index
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);
694 if (index)
695 return -EINVAL;
697 return 0;
701 * @param file
702 * @param priv
703 * @param 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)
713 return -EBUSY;
715 if (index != 0)
716 return -EINVAL;
718 return 0;
722 * @param file
723 * @param priv
724 * @param ctrl
726 * @return 0 or negative error code
729 int microdia_vidioc_queryctrl(struct file *file, void *priv,
730 struct v4l2_queryctrl *ctrl)
732 int i;
733 int nbr;
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, &microdia_controls[i],
743 sizeof(struct v4l2_queryctrl));
744 break;
748 if (i >= nbr)
749 return -EINVAL;
751 return 0;
755 * @param file
756 * @param priv
757 * @param ctrl
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);
771 switch (ctrl->id) {
772 case V4L2_CID_BRIGHTNESS:
773 ctrl->value = dev->vsettings.brightness;
774 break;
776 case V4L2_CID_EXPOSURE:
777 ctrl->value = dev->vsettings.exposure;
778 break;
780 case V4L2_CID_WHITENESS:
781 ctrl->value = dev->vsettings.whiteness;
782 break;
784 case V4L2_CID_SATURATION:
785 ctrl->value = dev->vsettings.colour;
786 break;
788 case V4L2_CID_CONTRAST:
789 ctrl->value = dev->vsettings.contrast;
790 break;
792 case V4L2_CID_HFLIP:
793 ctrl->value = dev->vsettings.hflip;
794 break;
796 case V4L2_CID_VFLIP:
797 ctrl->value = dev->vsettings.vflip;
798 break;
800 case V4L2_CID_SHARPNESS:
801 ctrl->value = dev->vsettings.sharpness;
802 break;
804 case V4L2_CID_RED_BALANCE:
805 ctrl->value = dev->vsettings.rgb_gain[0];
806 break;
808 case V4L2_CID_BLUE_BALANCE:
809 ctrl->value = dev->vsettings.rgb_gain[3];
810 break;
812 case V4L2_CID_AUTOEXPOSURE:
813 ctrl->value = dev->vsettings.auto_exposure;
814 break;
816 case V4L2_CID_AUTO_WHITE_BALANCE:
817 ctrl->value = dev->vsettings.auto_whitebalance;
818 break;
820 default:
821 return -EINVAL;
823 return 0;
827 * @brief Apply v4l2 settings on camera
829 * @param file
830 * @param priv
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);
845 switch (ctrl->id) {
846 case V4L2_CID_BRIGHTNESS:
847 dev->vsettings.brightness = (0xff00 & ctrl->value);
848 dev_microdia_camera_set_brightness(dev);
849 break;
851 case V4L2_CID_EXPOSURE:
852 dev->vsettings.exposure = (0xff00 & ctrl->value);
853 dev_microdia_camera_set_exposure(dev);
854 break;
856 case V4L2_CID_WHITENESS:
857 dev->vsettings.whiteness = (0xff00 & ctrl->value);
858 dev_microdia_camera_set_gamma(dev);
859 break;
861 case V4L2_CID_SATURATION:
862 dev->vsettings.colour = (0xff00 & ctrl->value);
863 break;
865 case V4L2_CID_CONTRAST:
866 dev->vsettings.contrast = (0xff00 & ctrl->value);
867 dev_microdia_camera_set_contrast(dev);
868 break;
870 case V4L2_CID_HFLIP:
871 dev->vsettings.hflip = ctrl->value;
872 dev_microdia_camera_set_hvflip(dev);
873 break;
875 case V4L2_CID_VFLIP:
876 dev->vsettings.vflip = ctrl->value;
877 dev_microdia_camera_set_hvflip(dev);
878 break;
880 case V4L2_CID_SHARPNESS:
881 dev->vsettings.sharpness = ctrl->value;
882 dev_microdia_camera_set_sharpness(dev);
883 break;
885 case V4L2_CID_RED_BALANCE:
886 dev->vsettings.rgb_gain[0] = ctrl->value;
887 dev_microdia_camera_set_rgb_gain(dev);
888 break;
890 case V4L2_CID_BLUE_BALANCE:
891 dev->vsettings.rgb_gain[3] = ctrl->value;
892 dev_microdia_camera_set_rgb_gain(dev);
893 break;
895 case V4L2_CID_AUTOEXPOSURE:
896 dev->vsettings.auto_exposure = ctrl->value;
897 dev_microdia_camera_set_auto_exposure(dev);
898 break;
900 case V4L2_CID_AUTO_WHITE_BALANCE:
901 dev->vsettings.auto_whitebalance = ctrl->value;
902 dev_microdia_camera_set_auto_whitebalance(dev);
903 break;
905 default:
906 return -EINVAL;
909 return 0;
913 * @param file
914 * @param priv
915 * @param fmt
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)
930 return -EINVAL;
932 fmt->flags = 0;
933 fmt->pixelformat = dev->camera.fmts[fmt->index].pix_fmt;
934 memcpy(fmt->description, dev->camera.fmts[fmt->index].desc, 32);
936 return 0;
940 * @param file
941 * @param priv
942 * @param fmt
944 * @return 0 or negative error code
947 int microdia_vidioc_try_fmt_cap(struct file *file, void *priv,
948 struct v4l2_format *fmt)
950 int index;
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)
958 return -EINVAL;
961 for (index = 0; index < dev->camera.nfmts; index++)
962 if (dev->camera.fmts[index].pix_fmt == fmt->fmt.pix.pixelformat)
963 break;
965 if (index >= dev->camera.nfmts)
966 return -EINVAL;
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;
980 return 0;
984 * @param file
985 * @param priv
986 * @param fmt
988 * @return 0
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));
1003 return 0;
1007 * @param file
1008 * @param priv
1009 * @param fmt
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;
1018 int ret;
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)
1025 return -EBUSY;
1027 if (microdia_queue_streaming(&dev->queue))
1028 return -EBUSY;
1030 ret = microdia_vidioc_try_fmt_cap(file, priv, fmt);
1031 if (ret)
1032 return -EINVAL;
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));
1038 return 0;
1042 * @param file
1043 * @param priv
1044 * @param request
1046 * @return 0 or negative error code
1049 int microdia_vidioc_reqbufs(struct file *file, void *priv,
1050 struct v4l2_requestbuffers *request)
1052 int ret = 0;
1053 struct usb_microdia *dev;
1055 dev = video_get_drvdata(priv);
1057 if (v4l_get_privileges(file) < 0) {
1058 ret = -EBUSY;
1059 goto done;
1062 if (request->memory != V4L2_MEMORY_MMAP ||
1063 request->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1064 ret = -EINVAL;
1065 goto done;
1068 if (microdia_queue_streaming(&dev->queue)) {
1069 ret = -EBUSY;
1070 goto done;
1073 ret = microdia_alloc_buffers(&dev->queue, request->count,
1074 dev->vsettings.format.sizeimage);
1075 if (ret < 0)
1076 goto done;
1078 request->count = ret;
1079 ret = 0;
1080 UDIA_INFO("Buffers Allocated %d\n", request->count);
1081 done:
1082 return ret;
1086 * @param file
1087 * @param priv
1088 * @param buffer
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)
1104 return -EINVAL;
1106 if (!v4l_has_privileges(file))
1107 return -EBUSY;
1109 return microdia_query_buffer(&dev->queue, buffer);
1113 * @param file
1114 * @param priv
1115 * @param 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))
1130 return -EBUSY;
1132 return microdia_queue_buffer(&dev->queue, buffer);
1136 * @param file
1137 * @param priv
1138 * @param 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;
1147 int ret = 0;
1149 dev = video_get_drvdata(priv);
1151 UDIA_DEBUG("VIDIOC_DQBUF\n");
1153 if (!v4l_has_privileges(file))
1154 return -EBUSY;
1156 ret = microdia_dequeue_buffer(&dev->queue, buffer,
1157 file->f_flags & O_NONBLOCK);
1158 if (ret < 0)
1159 return ret;
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,
1164 buffer->bytesused);
1165 buffer->bytesused += 589;
1168 return ret;
1172 * @param file
1173 * @param priv
1174 * @param type
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))
1189 return -EBUSY;
1191 if (dev->mode != MICRODIA_MODE_IDLE)
1192 return -EBUSY;
1194 return v4l2_enable_video(dev, MICRODIA_MODE_STREAM);
1198 * @param file
1199 * @param priv
1200 * @param type
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))
1215 return -EBUSY;
1217 return v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
1221 * @param file
1222 * @param priv
1223 * @param param
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)
1237 return -EINVAL;
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;
1246 return 0;
1250 * @param file
1251 * @param priv
1252 * @param param
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))
1265 return -EBUSY;
1267 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1268 return -EINVAL;
1270 return 0;
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)
1288 int err;
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)
1298 return -EFAULT;
1300 err = video_ioctl2(inode, fp, cmd, arg);
1302 return err;
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,
1328 #endif
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)
1341 int err;
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;
1349 #else
1350 dev->vdev->dev = dev->interface->dev;
1351 #endif
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;
1356 #endif
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;
1384 #else
1385 dev->vdev->ioctl_ops = &microdia_v4l2_ioctl_ops;
1386 #endif
1388 video_set_drvdata(dev->vdev, dev);
1390 microdia_queue_init(&dev->queue);
1392 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1394 if (err)
1395 UDIA_ERROR("Video register fail !\n");
1396 else
1397 UDIA_INFO("Microdia USB 2.0 Webcam is now controlling "
1398 "video device /dev/video%d\n",
1399 dev->vdev->minor);
1401 return err;
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);
1422 return 0;
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,
1441 #endif
1442 .llseek = no_llseek