Correcting code style for the rest
[microdia.git] / microdia-v4l.c
blobd8b35df3cef3f34f7fe0667aa56080e895565bae
1 /**
2 * @file microdia-v4l.c
3 * @author Nicolas VIVIEN
4 * @date 2008-02-01
5 * @version v0.0.0
7 * @brief Driver for Microdia USB video camera
9 * @note Copyright (C) Nicolas VIVIEN
11 * @par Licences
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/version.h>
32 #include <linux/errno.h>
33 #include <linux/slab.h>
34 #include <linux/kref.h>
35 #include <linux/vmalloc.h>
36 #include <linux/usb.h>
37 #include <media/v4l2-common.h>
39 #include "microdia.h"
42 // USER DEFINED V4L2-CONTROLS:
43 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE)
46 static struct file_operations v4l_microdia_fops;
49 /**
50 * @var microdia_image_sizes
51 * List of all resolutions supported by the driver
53 const struct microdia_coord microdia_image_sizes[MICRODIA_NBR_SIZES] = {
54 { 80, 60 },
55 /*{ 128, 96 },*/
56 { 160, 120 },
57 /*{ 213, 160 }, */
58 { 320, 240 },
59 { 640, 480 },
60 { 800, 600 },
61 { 1024, 768 },
62 { 1280, 1024 }
65 /**
66 * format list
69 #define NUM_V4L2_FORMATS 4
71 struct v4l2_pix_format microdia_fmts[] = {
73 .width = 640,
74 .height = 480,
75 .pixelformat = V4L2_PIX_FMT_YUV420,
76 .field = V4L2_FIELD_NONE,
77 .bytesperline = 960,
78 .sizeimage = 460800,
79 .colorspace = V4L2_COLORSPACE_SRGB,
80 .priv = 0
83 .width = 640,
84 .height = 480,
85 .pixelformat = V4L2_PIX_FMT_BGR24,
86 .field = V4L2_FIELD_NONE,
87 .bytesperline = 1920,
88 .sizeimage = 921600,
89 .colorspace = V4L2_COLORSPACE_SRGB,
90 .priv = 0
93 .width = 640,
94 .height = 480,
95 .pixelformat = V4L2_PIX_FMT_RGB24,
96 .field = V4L2_FIELD_NONE,
97 .bytesperline = 1920,
98 .sizeimage = 921600,
99 .colorspace = V4L2_COLORSPACE_SRGB,
100 .priv = 0
103 .width = 640,
104 .height = 480,
105 .pixelformat = V4L2_PIX_FMT_YUYV,
106 .field = V4L2_FIELD_NONE,
107 .bytesperline = 1280,
108 .sizeimage = 614400,
109 .colorspace = V4L2_COLORSPACE_SRGB,
110 .priv = 0
115 * @param dev
116 * @param fmt v4l2 fmt id
118 * @returns index of requested format
120 * @brief check if v4l2 forat is supported by device.
122 * This function permits to check if v4l2 format is supported.
124 int v4l2_format_supported(struct usb_microdia *dev, __u32 fmt)
126 int i;
127 for (i = 0; i < sizeof(dev->supported_fmts) * 8; i++) {
128 if (i > (ARRAY_SIZE(microdia_fmts) - 1))
129 break;
130 if (dev->supported_fmts & (1 << i) &&
131 microdia_fmts[i].pixelformat == fmt)
132 return i;
134 return -EINVAL;
138 * @param dev
139 * @param index format index
141 * @returns reference to format structure
143 * @brief enumerate supported formats
145 * This function will enumerate all supported formats.
147 struct v4l2_pix_format *v4l2_enum_supported_formats(struct usb_microdia *dev,
148 __u8 index)
150 int i, bit = 0;
151 for (i = 0; i < sizeof(dev->supported_fmts) * 8; i++) {
152 if (i > (ARRAY_SIZE(microdia_fmts) - 1))
153 break;
154 if (dev->supported_fmts & (1 << i)) {
155 if (bit == index)
156 return &microdia_fmts[i];
157 bit++;
160 return NULL;
164 * @var microdia_controls
165 * List of all V4Lv2 controls supported by the driver
167 static struct v4l2_queryctrl microdia_controls[] = {
169 .id = V4L2_CID_BRIGHTNESS,
170 .type = V4L2_CTRL_TYPE_INTEGER,
171 .name = "Brightness",
172 .minimum = 0,
173 .maximum = 0xff00,
174 .step = 1,
175 .default_value = 0x7f00,
178 .id = V4L2_CID_WHITENESS,
179 .type = V4L2_CTRL_TYPE_INTEGER,
180 .name = "Whiteness",
181 .minimum = 0,
182 .maximum = 0xff00,
183 .step = 1,
184 .default_value = 0x7f00,
188 .id = V4L2_CID_SATURATION,
189 .type = V4L2_CTRL_TYPE_INTEGER,
190 .name = "Saturation",
191 .minimum = 0,
192 .maximum = 0xff00,
193 .step = 1,
194 .default_value = 0x7f00,
198 .id = V4L2_CID_CONTRAST,
199 .type = V4L2_CTRL_TYPE_INTEGER,
200 .name = "Contrast",
201 .minimum = 0,
202 .maximum = 0xff00,
203 .step = 1,
204 .default_value = 0x0000,
207 .id = V4L2_CID_EXPOSURE,
208 .type = V4L2_CTRL_TYPE_INTEGER,
209 .name = "Exposure",
210 .minimum = 0,
211 .maximum = 0xff00,
212 .step = 1,
213 .default_value = 0x1000,
216 .id = V4L2_CID_HFLIP,
217 .type = V4L2_CTRL_TYPE_BOOLEAN,
218 .name = "Horizontal flip",
219 .minimum = 0,
220 .maximum = 1,
221 .step = 1,
222 .default_value = 0,
225 .id = V4L2_CID_VFLIP,
226 .type = V4L2_CTRL_TYPE_BOOLEAN,
227 .name = "Vertical flip",
228 .minimum = 0,
229 .maximum = 1,
230 .step = 1,
231 .default_value = 0,
234 .id = V4L2_CID_SHARPNESS,
235 .type = V4L2_CTRL_TYPE_INTEGER,
236 .name = "Sharpness",
237 .minimum = 0,
238 .maximum = 0x3f,
239 .step = 1,
240 .default_value = 0x1f,
243 .id = V4L2_CID_RED_BALANCE,
244 .type = V4L2_CTRL_TYPE_INTEGER,
245 .name = "Red Balance",
246 .minimum = 0,
247 .maximum = 0x7f,
248 .step = 1,
249 .default_value = 0x20,
252 .id = V4L2_CID_BLUE_BALANCE,
253 .type = V4L2_CTRL_TYPE_INTEGER,
254 .name = "Blue Balance",
255 .minimum = 0,
256 .maximum = 0x7f,
257 .step = 1,
258 .default_value = 0x20,
261 .id = V4L2_CID_AUTOGAIN,
262 .type = V4L2_CTRL_TYPE_BOOLEAN,
263 .name = "Automatic exposure control",
264 .minimum = 0,
265 .maximum = 1,
266 .step = 1,
267 .default_value = 0,
270 .id = V4L2_CID_AUTO_WHITE_BALANCE,
271 .type = V4L2_CTRL_TYPE_BOOLEAN,
272 .name = "Automatic whitbalance control",
273 .minimum = 0,
274 .maximum = 1,
275 .step = 1,
276 .default_value = 0,
281 * The following three functions are used to get, test and drop v4l privleges.
283 int v4l_get_privileges(struct file *file)
285 struct usb_microdia *dev;
286 int ret = 0;
288 dev = video_get_drvdata(video_devdata(file));
290 if (dev->owner == file)
291 return 0;
293 mutex_lock(&open_lock);
294 if (dev->owner != NULL) {
295 ret = -EBUSY;
296 goto done;
298 dev->owner = file;
299 done:
300 mutex_unlock(&open_lock);
301 return ret;
304 int v4l_has_privileges(struct file *file)
306 struct usb_microdia *dev;
307 int ret = 0;
309 dev = video_get_drvdata(video_devdata(file));
311 if (dev->owner == file)
312 ret = 1;
314 return ret;
317 void v4l_drop_privileges(struct file *file)
319 struct usb_microdia *dev;
321 dev = video_get_drvdata(video_devdata(file));
323 if (dev->owner == file)
324 dev->owner = NULL;
327 int v4l2_enable_video(struct usb_microdia *dev, int mode)
329 int ret;
331 if (mode == MICRODIA_MODE_IDLE) {
332 dev_microdia_stop_stream(dev);
333 usb_microdia_isoc_cleanup(dev);
334 dev_microdia_camera_off(dev);
335 microdia_queue_enable(&dev->queue, 0);
336 dev->mode = mode;
337 return 0;
340 if (dev->mode != MICRODIA_MODE_IDLE)
341 return -EBUSY;
343 if (microdia_queue_enable(&dev->queue, 1) < 0)
344 return -EBUSY;
346 dev_microdia_camera_on(dev);
347 ret = usb_microdia_isoc_init(dev);
349 if (ret)
350 return ret;
352 dev_microdia_start_stream(dev);
353 dev_microdia_camera_settings(dev);
354 dev->mode = mode;
356 return 0;
359 int v4l_microdia_find_resolution(struct usb_microdia *dev,
360 int *width, int *height)
362 int i, max_res;
363 int find = 0;
365 if ((*width < microdia_image_sizes[0].x)
366 || (*height < microdia_image_sizes[0].y)) {
367 *width = microdia_image_sizes[0].x;
368 *height = microdia_image_sizes[0].y;
371 switch (dev->webcam_type) {
372 case MICRODIA_SXGA:
373 max_res = MICRODIA_NBR_SIZES-1;
374 if ((*width > microdia_image_sizes[max_res].x)
375 || (*height > microdia_image_sizes[max_res].y)) {
376 *width = microdia_image_sizes[max_res].x;
377 *height = microdia_image_sizes[max_res].y;
380 for (i = 0, find = 0; i < MICRODIA_NBR_SIZES; i++) {
381 if (microdia_image_sizes[i].x <= *width &&
382 microdia_image_sizes[i].y <= *height)
383 find = i;
385 break;
387 case MICRODIA_VGA:
388 max_res = MICRODIA_NBR_SIZES-4;
389 if ((*width > microdia_image_sizes[max_res].x)
390 || (*height > microdia_image_sizes[max_res].y)) {
391 *width = microdia_image_sizes[max_res].x;
392 *height = microdia_image_sizes[max_res].y;
395 for (i = 0, find = 0; i < MICRODIA_NBR_SIZES-3; i++) {
396 if (microdia_image_sizes[i].x <= *width &&
397 microdia_image_sizes[i].y <= *height)
398 find = i;
400 break;
403 *width = microdia_image_sizes[find].x;
404 *height = microdia_image_sizes[find].y;
406 return find;
411 * @param dev
412 * @param resolution Driver resolution
414 * @returns 0 if all is OK
416 * @brief Select a video mode
418 * This function permits to select a video mode.
420 int v4l_microdia_select_video_mode(struct usb_microdia *dev, int resolution)
422 dev->resolution = resolution;
424 UDIA_DEBUG("Set mode %d [%dx%d]\n", dev->resolution,
425 microdia_image_sizes[dev->resolution].x,
426 microdia_image_sizes[dev->resolution].y);
428 dev->view.x = microdia_image_sizes[dev->resolution].x;
429 dev->view.y = microdia_image_sizes[dev->resolution].y;
433 * Calculate the frame size
435 switch (dev->resolution) {
436 case MICRODIA_80x60:
437 case MICRODIA_160x120:
438 case MICRODIA_320x240:
439 case MICRODIA_640x480:
440 dev->image.x = microdia_image_sizes[MICRODIA_640x480].x;
441 dev->image.y = microdia_image_sizes[MICRODIA_640x480].y;
442 break;
444 case MICRODIA_800x600:
445 case MICRODIA_1024x768:
446 case MICRODIA_1280x1024:
447 dev->image.x = microdia_image_sizes[MICRODIA_1280x1024].x;
448 dev->image.y = microdia_image_sizes[MICRODIA_1280x1024].y;
449 break;
452 * queue.frame_size is only ever used in isoc_handler
453 * to test if the ISOC data is the correct size
454 * This modificate pre calculates this rather
455 * than doing the calculating in the isoc_handler
457 dev->queue.frame_size = dev->image.x * dev->image.y +
458 (dev->image.x * dev->image.y) / dev->frame_size_divisor;
460 return 0;
465 * @param inode Pointer on an inode
466 * @param fp File pointer
468 * @returns 0 if all is OK
470 * @brief Open the video device
472 * This function permits to open a video device (/dev/videoX)
474 static int v4l_microdia_open(struct inode *inode, struct file *fp)
476 int ret = 0;
478 struct usb_microdia *dev;
479 struct video_device *vdev;
481 mutex_lock(&open_lock);
483 vdev = video_devdata(fp);
484 dev = video_get_drvdata(video_devdata(fp));
486 fp->private_data = vdev;
488 kref_get(&dev->vopen);
490 mutex_unlock(&open_lock);
491 return ret;
496 * @param inode Pointer on inode
497 * @param fp File pointer
499 * @returns 0 if all is OK
501 * @brief Release an opened file.
503 * This function permits to release an opened file with the 'open' method.
505 static int v4l_microdia_release(struct inode *inode, struct file *fp)
507 struct usb_microdia *dev;
508 struct video_device *vdev;
510 mutex_lock(&open_lock);
512 vdev = video_devdata(fp);
513 dev = video_get_drvdata(video_devdata(fp));
515 if (v4l_has_privileges(fp)) {
516 v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
518 mutex_lock(&dev->queue.mutex);
519 microdia_free_buffers(&dev->queue);
520 mutex_unlock(&dev->queue.mutex);
523 v4l_drop_privileges(fp);
525 kref_put(&dev->vopen, usb_microdia_delete);
527 mutex_unlock(&open_lock);
528 return 0;
533 * @param fp File pointer
535 * @retval buf Buffer in user space
536 * @retval count
537 * @retval f_pos
539 * @returns Count value
541 * @brief Read the video device
543 * This function is called by the application is reading the video device.
545 static ssize_t v4l_microdia_read(struct file *fp, char __user *buf,
546 size_t count, loff_t *f_pos)
548 int i, ret;
549 int nbuffers;
550 struct v4l2_buffer buffer;
551 struct usb_microdia *dev;
553 dev = video_get_drvdata(video_devdata(fp));
555 ret = v4l_get_privileges(fp);
556 if (ret < 0)
557 return ret;
559 if (dev->mode != MICRODIA_MODE_IDLE &&
560 dev->mode != MICRODIA_MODE_READ)
561 return -EBUSY;
563 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
564 buffer.memory = V4L2_MEMORY_MMAP;
565 if (dev->mode == MICRODIA_MODE_IDLE) {
566 nbuffers = microdia_alloc_buffers(&dev->queue, 2,
567 MICRODIA_FRAME_SIZE);
568 if (nbuffers < 0)
569 return nbuffers;
571 for (i = 0; i < nbuffers; i++) {
572 buffer = dev->queue.buffer[i].buf;
573 microdia_queue_buffer(&dev->queue, &buffer);
576 ret = v4l2_enable_video(dev, MICRODIA_MODE_READ);
577 if (ret < 0)
578 return ret;
581 if (dev->queue.read_buffer == NULL) {
582 ret = microdia_dequeue_buffer(&dev->queue, &buffer,
583 fp->f_flags & O_NONBLOCK);
584 if (ret < 0)
585 return ret;
587 microdia_decompress(dev, &buffer);
588 dev->queue.read_buffer = &dev->queue.buffer[buffer.index];
589 } else {
590 buffer = dev->queue.read_buffer->buf;
593 count = min((size_t)(buffer.bytesused - *f_pos), count);
594 if (copy_to_user(buf, dev->queue.mem + buffer.m.offset + *f_pos, count))
595 return -EFAULT;
597 *f_pos += count;
598 if (*f_pos >= buffer.bytesused) {
599 dev->queue.read_buffer = NULL;
600 microdia_queue_buffer(&dev->queue, &buffer);
601 *f_pos = 0;
603 return count;
608 * @param fp File pointer
609 * @param wait
611 * @returns 0 if all is OK
613 * @brief Polling function
615 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
617 struct usb_microdia *dev;
618 struct video_device *vdev;
620 vdev = video_devdata(fp);
621 dev = video_get_drvdata(video_devdata(fp));
623 UDIA_STREAM("Poll\n");
625 if (vdev == NULL || dev == NULL)
626 return -EFAULT;
628 return microdia_queue_poll(&dev->queue, fp, wait);
631 static void microdia_vm_open(struct vm_area_struct *vma)
633 struct microdia_buffer *buffer = vma->vm_private_data;
634 buffer->vma_use_count++;
638 static void microdia_vm_close(struct vm_area_struct *vma)
640 struct microdia_buffer *buffer = vma->vm_private_data;
641 buffer->vma_use_count--;
644 struct vm_operations_struct microdia_vm_ops = {
645 .open = microdia_vm_open,
646 .close = microdia_vm_close
650 * @param fp File pointer
651 * @param vma VMA structure
653 * @returns 0 if all is OK
655 * @brief Memory map
657 * This function permits to map a memory space.
659 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
661 struct page *page;
662 unsigned long addr, start, size;
663 unsigned int i;
664 int ret = 0;
666 struct usb_microdia *dev;
667 struct video_device *vdev;
668 struct microdia_buffer *buffer = NULL;
670 vdev = video_devdata(fp);
671 dev = video_get_drvdata(video_devdata(fp));
673 UDIA_STREAM("mmap\n");
675 start = vma->vm_start;
676 size = vma->vm_end - vma->vm_start;
678 mutex_lock(&dev->queue.mutex);
680 for (i = 0; i < dev->queue.count; ++i) {
681 buffer = &dev->queue.buffer[i];
682 if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
683 break;
686 if (i == dev->queue.count || size != dev->queue.buf_size) {
687 ret = -EINVAL;
688 goto done;
691 vma->vm_flags |= VM_IO;
693 addr = (unsigned long)dev->queue.mem + buffer->buf.m.offset;
694 while (size > 0) {
695 page = vmalloc_to_page((void *)addr);
696 ret = vm_insert_page(vma, start, page);
697 if (ret < 0)
698 goto done;
700 start += PAGE_SIZE;
701 addr += PAGE_SIZE;
702 size -= PAGE_SIZE;
705 vma->vm_ops = &microdia_vm_ops;
706 vma->vm_private_data = buffer;
707 microdia_vm_open(vma);
708 done:
709 mutex_unlock(&dev->queue.mutex);
710 return ret;
713 int microdia_vidioc_querycap(struct file *file, void *priv,
714 struct v4l2_capability *cap)
716 struct usb_microdia *dev;
718 dev = video_get_drvdata(priv);
720 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
722 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
723 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
724 | V4L2_CAP_READWRITE;
725 cap->version = (__u32) DRIVER_VERSION_NUM,
726 strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
728 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
729 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
730 return 0;
733 int microdia_vidioc_enum_input(struct file *file, void *priv,
734 struct v4l2_input *input)
736 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", input->index);
738 if (input->index)
739 return -EINVAL;
741 strlcpy(input->name, "Webcam", sizeof(input->name));
742 input->type = V4L2_INPUT_TYPE_CAMERA;
743 input->std = 0;
745 return 0;
748 int microdia_vidioc_g_input(struct file *file, void *priv, unsigned int *index)
750 UDIA_DEBUG("GET INPUT %d\n", *index);
752 if (index)
753 return -EINVAL;
755 return 0;
758 int microdia_vidioc_s_input(struct file *file, void *priv, unsigned int index)
760 UDIA_DEBUG("SET INPUT %d\n", index);
762 if (v4l_get_privileges(file) < 0)
763 return -EBUSY;
765 if (index != 0)
766 return -EINVAL;
768 return 0;
771 int microdia_vidioc_queryctrl(struct file *file, void *priv,
772 struct v4l2_queryctrl *ctrl)
774 int i;
775 int nbr;
777 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl->id);
779 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
781 for (i = 0; i < nbr; i++) {
782 if (microdia_controls[i].id == ctrl->id) {
783 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
784 memcpy(ctrl, &microdia_controls[i],
785 sizeof(struct v4l2_queryctrl));
786 break;
790 if (i >= nbr)
791 return -EINVAL;
793 return 0;
796 int microdia_vidioc_g_ctrl(struct file *file, void *priv,
797 struct v4l2_control *ctrl)
799 struct usb_microdia *dev;
801 dev = video_get_drvdata(priv);
803 UDIA_DEBUG("GET CTRL id=%d\n", ctrl->id);
805 switch (ctrl->id) {
806 case V4L2_CID_BRIGHTNESS:
807 ctrl->value = dev->vsettings.brightness;
808 break;
810 case V4L2_CID_EXPOSURE:
811 ctrl->value = dev->vsettings.exposure;
812 break;
814 case V4L2_CID_WHITENESS:
815 ctrl->value = dev->vsettings.whiteness;
816 break;
818 case V4L2_CID_SATURATION:
819 ctrl->value = dev->vsettings.colour;
820 break;
822 case V4L2_CID_CONTRAST:
823 ctrl->value = dev->vsettings.contrast;
824 break;
826 case V4L2_CID_HFLIP:
827 ctrl->value = dev->vsettings.hflip;
828 break;
830 case V4L2_CID_VFLIP:
831 ctrl->value = dev->vsettings.vflip;
832 break;
834 case V4L2_CID_SHARPNESS:
835 ctrl->value = dev->vsettings.sharpness;
836 break;
838 case V4L2_CID_RED_BALANCE:
839 ctrl->value = dev->vsettings.rgb_gain[0];
840 break;
842 case V4L2_CID_BLUE_BALANCE:
843 ctrl->value = dev->vsettings.rgb_gain[3];
844 break;
846 case V4L2_CID_AUTOGAIN:
847 ctrl->value = dev->vsettings.auto_exposure;
848 break;
850 case V4L2_CID_AUTO_WHITE_BALANCE:
851 ctrl->value = dev->vsettings.auto_whitebalance;
852 break;
854 default:
855 return -EINVAL;
857 return 0;
860 int microdia_vidioc_s_ctrl(struct file *file, void *priv,
861 struct v4l2_control *ctrl)
863 struct usb_microdia *dev;
865 dev = video_get_drvdata(priv);
867 UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl->id, ctrl->value);
869 switch (ctrl->id) {
870 case V4L2_CID_BRIGHTNESS:
871 dev->vsettings.brightness = (0xff00 & ctrl->value);
872 dev_microdia_camera_set_brightness(dev);
873 break;
875 case V4L2_CID_EXPOSURE:
876 dev->vsettings.exposure = (0xff00 & ctrl->value);
877 dev_microdia_camera_set_exposure(dev);
878 break;
880 case V4L2_CID_WHITENESS:
881 dev->vsettings.whiteness = (0xff00 & ctrl->value);
882 dev_microdia_camera_set_gamma(dev);
883 break;
885 case V4L2_CID_SATURATION:
886 dev->vsettings.colour = (0xff00 & ctrl->value);
887 break;
889 case V4L2_CID_CONTRAST:
890 dev->vsettings.contrast = (0xff00 & ctrl->value);
891 dev_microdia_camera_set_contrast(dev);
892 break;
894 case V4L2_CID_HFLIP:
895 dev->vsettings.hflip = ctrl->value;
896 dev_microdia_camera_set_hvflip(dev);
897 break;
899 case V4L2_CID_VFLIP:
900 dev->vsettings.vflip = ctrl->value;
901 dev_microdia_camera_set_hvflip(dev);
902 break;
904 case V4L2_CID_SHARPNESS:
905 dev->vsettings.sharpness = ctrl->value;
906 dev_microdia_camera_set_sharpness(dev);
907 break;
909 case V4L2_CID_RED_BALANCE:
910 dev->vsettings.rgb_gain[0] = ctrl->value;
911 dev_microdia_camera_set_rgb_gain(dev);
912 break;
914 case V4L2_CID_BLUE_BALANCE:
915 dev->vsettings.rgb_gain[3] = ctrl->value;
916 dev_microdia_camera_set_rgb_gain(dev);
917 break;
919 case V4L2_CID_AUTOGAIN:
920 dev->vsettings.auto_exposure = ctrl->value;
921 dev_microdia_camera_set_auto_exposure(dev);
922 break;
924 case V4L2_CID_AUTO_WHITE_BALANCE:
925 dev->vsettings.auto_whitebalance = ctrl->value;
926 dev_microdia_camera_set_auto_whitebalance(dev);
927 break;
929 default:
930 return -EINVAL;
933 return 0;
936 int microdia_vidioc_enum_fmt_cap(struct file *file, void *priv,
937 struct v4l2_fmtdesc *fmt)
939 struct usb_microdia *dev;
940 struct v4l2_pix_format *format;
942 dev = video_get_drvdata(priv);
944 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmt->index);
946 format = v4l2_enum_supported_formats(dev, fmt->index);
947 if (format == NULL)
948 return -EINVAL;
950 fmt->flags = 0;
951 fmt->pixelformat = format->pixelformat;
952 fmt->description[0] = fmt->pixelformat & 0xFF;
953 fmt->description[1] = (fmt->pixelformat >> 8) & 0xFF;
954 fmt->description[2] = (fmt->pixelformat >> 16) & 0xFF;
955 fmt->description[3] = fmt->pixelformat >> 24;
956 fmt->description[4] = 0;
958 return 0;
961 int microdia_vidioc_try_fmt_cap(struct file *file, void *priv,
962 struct v4l2_format *fmt)
964 struct usb_microdia *dev;
966 dev = video_get_drvdata(priv);
967 UDIA_DEBUG("TRY FMT %d\n", fmt->type);
969 /* when this code is used prevents mplayer from setting outfmt
970 if(fmt->fmt.pix.field != V4L2_FIELD_NONE)
971 return -EINVAL;
974 if (v4l2_format_supported(dev, fmt->fmt.pix.pixelformat) < 0)
975 return -EINVAL;
977 v4l_microdia_find_resolution(dev, &fmt->fmt.pix.width,
978 &fmt->fmt.pix.height);
980 switch (fmt->fmt.pix.pixelformat) {
981 case V4L2_PIX_FMT_YUV420:
982 fmt->fmt.pix.bytesperline = (fmt->fmt.pix.width * 3)/2;
983 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
984 fmt->fmt.pix.bytesperline;
985 break;
986 case V4L2_PIX_FMT_RGB24:
987 case V4L2_PIX_FMT_BGR24:
988 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
989 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
990 fmt->fmt.pix.bytesperline;
991 break;
992 case V4L2_PIX_FMT_YUYV:
993 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 2;
994 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
995 fmt->fmt.pix.bytesperline;
996 break;
997 default:
998 return -EINVAL;
1001 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
1002 fmt->fmt.pix.priv = 0;
1004 return 0;
1007 int microdia_vidioc_g_fmt_cap(struct file *file, void *priv,
1008 struct v4l2_format *fmt)
1010 struct usb_microdia *dev;
1012 dev = video_get_drvdata(priv);
1014 UDIA_DEBUG("GET FMT %d\n", fmt->type);
1016 memcpy(&(fmt->fmt.pix), &(dev->vsettings.format), sizeof(fmt->fmt.pix));
1019 return 0;
1022 int microdia_vidioc_s_fmt_cap(struct file *file, void *priv,
1023 struct v4l2_format *fmt)
1025 struct usb_microdia *dev;
1026 int ret;
1028 dev = video_get_drvdata(priv);
1030 UDIA_DEBUG("SET FMT %d : %d\n", fmt->type, fmt->fmt.pix.pixelformat);
1032 if (v4l_get_privileges(file) < 0)
1033 return -EBUSY;
1035 if (dev->queue.streaming)
1036 return -EBUSY;
1038 ret = microdia_vidioc_try_fmt_cap(file, priv, fmt);
1039 if (ret)
1040 return -EINVAL;
1042 UDIA_DEBUG("Set width=%d, height=%d\n",
1043 fmt->fmt.pix.width,
1044 fmt->fmt.pix.height);
1046 ret = v4l_microdia_find_resolution(dev, &fmt->fmt.pix.width,
1047 &fmt->fmt.pix.height);
1049 v4l_microdia_select_video_mode(dev, ret);
1051 memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix));
1053 return 0;
1056 int microdia_vidioc_reqbufs(struct file *file, void *priv,
1057 struct v4l2_requestbuffers *request)
1059 int ret = 0;
1060 struct usb_microdia *dev;
1062 dev = video_get_drvdata(priv);
1064 if (v4l_get_privileges(file) < 0) {
1065 ret = -EBUSY;
1066 goto done;
1069 if (request->memory != V4L2_MEMORY_MMAP ||
1070 request->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1071 ret = -EINVAL;
1072 goto done;
1075 if (dev->queue.streaming) {
1076 ret = -EBUSY;
1077 goto done;
1080 ret = microdia_alloc_buffers(&dev->queue, request->count,
1081 MICRODIA_FRAME_SIZE);
1082 if (ret < 0)
1083 goto done;
1085 dev->queue.drop_incomplete = 1;
1087 request->count = ret;
1088 ret = 0;
1089 UDIA_INFO("Buffers Allocated %d\n", request->count);
1090 done:
1091 return ret;
1094 int microdia_vidioc_querybuf(struct file *file, void *priv,
1095 struct v4l2_buffer *buffer)
1097 struct usb_microdia *dev;
1099 dev = video_get_drvdata(priv);
1101 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buffer->index, dev->queue.count);
1103 if (buffer->memory != V4L2_MEMORY_MMAP ||
1104 buffer->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1105 return -EINVAL;
1107 if (!v4l_has_privileges(file))
1108 return -EBUSY;
1110 return microdia_query_buffer(&dev->queue, buffer);
1113 int microdia_vidioc_qbuf(struct file *file, void *priv,
1114 struct v4l2_buffer *buffer)
1116 struct usb_microdia *dev;
1118 dev = video_get_drvdata(priv);
1120 UDIA_DEBUG("VIDIOC_QBUF\n");
1122 if (!v4l_has_privileges(file)) {
1123 return -EBUSY;
1126 return microdia_queue_buffer(&dev->queue, buffer);
1129 int microdia_vidioc_dqbuf(struct file *file, void *priv,
1130 struct v4l2_buffer *buffer)
1132 struct usb_microdia *dev;
1133 int ret = 0;
1135 dev = video_get_drvdata(priv);
1137 UDIA_DEBUG("VIDIOC_DQBUF\n");
1139 if (!v4l_has_privileges(file))
1140 return -EBUSY;
1142 ret = microdia_dequeue_buffer(&dev->queue, buffer,
1143 file->f_flags & O_NONBLOCK);
1144 if (ret < 0)
1145 return ret;
1147 microdia_decompress(dev, buffer);
1149 return ret;
1152 int microdia_vidioc_streamon(struct file *file, void *priv,
1153 enum v4l2_buf_type type)
1155 struct usb_microdia *dev;
1157 dev = video_get_drvdata(priv);
1159 UDIA_DEBUG("VIDIOC_STREAMON\n");
1161 if (!v4l_has_privileges(file))
1162 return -EBUSY;
1164 if (dev->mode != MICRODIA_MODE_IDLE)
1165 return -EBUSY;
1167 return v4l2_enable_video(dev, MICRODIA_MODE_STREAM);
1170 int microdia_vidioc_streamoff(struct file *file, void *priv,
1171 enum v4l2_buf_type type)
1173 struct usb_microdia *dev;
1175 dev = video_get_drvdata(priv);
1177 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1179 if (!v4l_has_privileges(file))
1180 return -EBUSY;
1182 return v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
1185 int microdia_vidioc_g_param(struct file *file, void *priv,
1186 struct v4l2_streamparm *param)
1188 struct usb_microdia *dev;
1191 dev = video_get_drvdata(priv);
1193 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1194 return -EINVAL;
1196 param->parm.capture.capability = 0;
1197 param->parm.capture.capturemode = 0;
1198 param->parm.capture.timeperframe.numerator = 1;
1199 param->parm.capture.timeperframe.denominator = 30;
1200 param->parm.capture.readbuffers = 2;
1201 param->parm.capture.extendedmode = 0;
1203 return 0;
1206 int microdia_vidioc_s_param(struct file *file, void *priv,
1207 struct v4l2_streamparm *param)
1209 struct usb_microdia *dev;
1211 dev = video_get_drvdata(priv);
1213 if (v4l_get_privileges(file))
1214 return -EBUSY;
1216 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1217 return -EINVAL;
1219 return 0;
1223 * @param inode Inode pointer
1224 * @param fp File pointer
1225 * @param cmd Command
1226 * @param arg Arguements of the command
1228 * @returns 0 if all is OK
1230 * @brief Manage IOCTL
1232 * This function permits to manage all the IOCTL from the application.
1234 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1235 unsigned int cmd, unsigned long arg)
1237 int err;
1238 struct usb_microdia *dev;
1239 struct video_device *vdev;
1241 vdev = video_devdata(fp);
1242 dev = video_get_drvdata(video_devdata(fp));
1244 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1246 if (dev == NULL || vdev == NULL)
1247 return -EFAULT;
1249 err = video_ioctl2(inode, fp, cmd, arg);
1251 return err;
1256 * @param dev Device structure
1258 * @returns 0 if all is OK
1260 * @brief Register the video device
1262 * This function permits to register the USB device to the video device.
1264 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1266 int err;
1268 strcpy(dev->vdev->name, DRIVER_DESC);
1270 dev->vdev->dev = &dev->interface->dev;
1271 dev->vdev->owner = THIS_MODULE;
1272 dev->vdev->type = VID_TYPE_CAPTURE;
1273 dev->vdev->current_norm = 0;
1274 dev->vdev->tvnorms = 0;
1275 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1276 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1277 #endif
1278 dev->vdev->fops = &v4l_microdia_fops;
1279 dev->vdev->release = video_device_release;
1280 dev->vdev->minor = -1;
1281 #if CONFIG_MICRODIA_DEBUG
1282 dev->vdev->debug = V4L2_DEBUG_IOCTL_ARG;
1283 #endif
1284 dev->vdev->vidioc_querycap = microdia_vidioc_querycap;
1285 dev->vdev->vidioc_enum_fmt_cap = microdia_vidioc_enum_fmt_cap;
1286 dev->vdev->vidioc_try_fmt_cap = microdia_vidioc_try_fmt_cap;
1287 dev->vdev->vidioc_s_fmt_cap = microdia_vidioc_s_fmt_cap;
1288 dev->vdev->vidioc_g_fmt_cap = microdia_vidioc_g_fmt_cap;
1289 dev->vdev->vidioc_enum_input = microdia_vidioc_enum_input;
1290 dev->vdev->vidioc_g_input = microdia_vidioc_g_input;
1291 dev->vdev->vidioc_s_input = microdia_vidioc_s_input;
1292 dev->vdev->vidioc_streamon = microdia_vidioc_streamon;
1293 dev->vdev->vidioc_streamoff = microdia_vidioc_streamoff;
1294 dev->vdev->vidioc_queryctrl = microdia_vidioc_queryctrl;
1295 dev->vdev->vidioc_g_ctrl = microdia_vidioc_g_ctrl;
1296 dev->vdev->vidioc_s_ctrl = microdia_vidioc_s_ctrl;
1297 dev->vdev->vidioc_g_parm = microdia_vidioc_g_param;
1298 dev->vdev->vidioc_s_parm = microdia_vidioc_s_param;
1299 dev->vdev->vidioc_reqbufs = microdia_vidioc_reqbufs;
1300 dev->vdev->vidioc_qbuf = microdia_vidioc_qbuf;
1301 dev->vdev->vidioc_dqbuf = microdia_vidioc_dqbuf;
1302 dev->vdev->vidioc_querybuf = microdia_vidioc_querybuf;
1304 video_set_drvdata(dev->vdev, dev);
1306 microdia_queue_init(&dev->queue);
1308 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1310 if (err)
1311 UDIA_ERROR("Video register fail !\n");
1312 else
1313 UDIA_INFO("Microdia USB2.0 Camera is now controlling "
1314 "video device /dev/video%d\n",
1315 dev->vdev->minor);
1317 return err;
1322 * @param dev Device structure
1324 * @returns 0 if all is OK
1326 * @brief Unregister the video device
1328 * This function permits to unregister the video device.
1330 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1332 UDIA_INFO("Microdia USB2.0 Camera release resources video "
1333 "device /dev/video%d\n", dev->vdev->minor);
1335 video_set_drvdata(dev->vdev, NULL);
1336 video_unregister_device(dev->vdev);
1338 return 0;
1343 * @var v4l_microdia_fops
1345 * This variable contains some callback
1347 static struct file_operations v4l_microdia_fops = {
1348 .owner = THIS_MODULE,
1349 .open = v4l_microdia_open,
1350 .release = v4l_microdia_release,
1351 .read = v4l_microdia_read,
1352 .poll = v4l_microdia_poll,
1353 .mmap = v4l_microdia_mmap,
1354 .ioctl = v4l_microdia_ioctl,
1355 #ifdef CONFIG_COMPAT
1356 .compat_ioctl = v4l_compat_ioctl32,
1357 #endif
1358 .llseek = no_llseek