Add doxygen documentation to all functions in microdia-usb.c
[microdia.git] / microdia-v4l.c
blobe6865f329417360c20aab214278f6f87cb5850c8
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 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
46 #define V4L2_CID_AUTOEXPOSURE (V4L2_CID_PRIVATE_BASE + 1)
48 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
49 #include <media/v4l2-ioctl.h>
50 #endif
52 static struct file_operations v4l_microdia_fops;
54 /**
55 * format list
58 #define NUM_V4L2_FORMATS 4
60 struct v4l2_pix_format microdia_fmts[] = {
62 .width = 640,
63 .height = 480,
64 .pixelformat = V4L2_PIX_FMT_YUV420,
65 .field = V4L2_FIELD_NONE,
66 .bytesperline = 960,
67 .sizeimage = 460800,
68 .colorspace = V4L2_COLORSPACE_SRGB,
69 .priv = 0
72 .width = 640,
73 .height = 480,
74 .pixelformat = V4L2_PIX_FMT_BGR24,
75 .field = V4L2_FIELD_NONE,
76 .bytesperline = 1920,
77 .sizeimage = 921600,
78 .colorspace = V4L2_COLORSPACE_SRGB,
79 .priv = 0
82 .width = 640,
83 .height = 480,
84 .pixelformat = V4L2_PIX_FMT_RGB24,
85 .field = V4L2_FIELD_NONE,
86 .bytesperline = 1920,
87 .sizeimage = 921600,
88 .colorspace = V4L2_COLORSPACE_SRGB,
89 .priv = 0
92 .width = 640,
93 .height = 480,
94 .pixelformat = V4L2_PIX_FMT_YUYV,
95 .field = V4L2_FIELD_NONE,
96 .bytesperline = 1280,
97 .sizeimage = 614400,
98 .colorspace = V4L2_COLORSPACE_SRGB,
99 .priv = 0
104 * @param dev
105 * @param fmt v4l2 fmt id
107 * @returns index of requested format
109 * @brief check if v4l2 forat is supported by device.
111 * This function permits to check if v4l2 format is supported.
113 int v4l2_format_supported(struct usb_microdia *dev, __u32 fmt)
115 int i;
116 for (i = 0; i < sizeof(dev->supported_fmts) * 8; i++) {
117 if (i > (ARRAY_SIZE(microdia_fmts) - 1))
118 break;
119 if (dev->supported_fmts & (1 << i) &&
120 microdia_fmts[i].pixelformat == fmt)
121 return i;
123 return -EINVAL;
127 * @param dev
128 * @param index format index
130 * @returns reference to format structure
132 * @brief enumerate supported formats
134 * This function will enumerate all supported formats.
136 struct v4l2_pix_format *v4l2_enum_supported_formats(struct usb_microdia *dev,
137 __u8 index)
139 int i, bit = 0;
140 for (i = 0; i < sizeof(dev->supported_fmts) * 8; i++) {
141 if (i > (ARRAY_SIZE(microdia_fmts) - 1))
142 break;
143 if (dev->supported_fmts & (1 << i)) {
144 if (bit == index)
145 return &microdia_fmts[i];
146 bit++;
149 return NULL;
153 * @var microdia_controls
154 * List of all V4Lv2 controls supported by the driver
156 static struct v4l2_queryctrl microdia_controls[] = {
158 .id = V4L2_CID_BRIGHTNESS,
159 .type = V4L2_CTRL_TYPE_INTEGER,
160 .name = "Brightness",
161 .minimum = 0,
162 .maximum = 0xff00,
163 .step = 1,
164 .default_value = 0x7f00,
167 .id = V4L2_CID_WHITENESS,
168 .type = V4L2_CTRL_TYPE_INTEGER,
169 .name = "Whiteness",
170 .minimum = 0,
171 .maximum = 0xff00,
172 .step = 1,
173 .default_value = 0x7f00,
177 .id = V4L2_CID_SATURATION,
178 .type = V4L2_CTRL_TYPE_INTEGER,
179 .name = "Saturation",
180 .minimum = 0,
181 .maximum = 0xff00,
182 .step = 1,
183 .default_value = 0x7f00,
187 .id = V4L2_CID_CONTRAST,
188 .type = V4L2_CTRL_TYPE_INTEGER,
189 .name = "Contrast",
190 .minimum = 0,
191 .maximum = 0xff00,
192 .step = 1,
193 .default_value = 0x0000,
196 .id = V4L2_CID_EXPOSURE,
197 .type = V4L2_CTRL_TYPE_INTEGER,
198 .name = "Exposure",
199 .minimum = 0,
200 .maximum = 0xff00,
201 .step = 1,
202 .default_value = 0x1000,
205 .id = V4L2_CID_HFLIP,
206 .type = V4L2_CTRL_TYPE_BOOLEAN,
207 .name = "Horizontal flip",
208 .minimum = 0,
209 .maximum = 1,
210 .step = 1,
211 .default_value = 0,
214 .id = V4L2_CID_VFLIP,
215 .type = V4L2_CTRL_TYPE_BOOLEAN,
216 .name = "Vertical flip",
217 .minimum = 0,
218 .maximum = 1,
219 .step = 1,
220 .default_value = 0,
223 .id = V4L2_CID_SHARPNESS,
224 .type = V4L2_CTRL_TYPE_INTEGER,
225 .name = "Sharpness",
226 .minimum = 0,
227 .maximum = 0x3f,
228 .step = 1,
229 .default_value = 0x1f,
232 .id = V4L2_CID_RED_BALANCE,
233 .type = V4L2_CTRL_TYPE_INTEGER,
234 .name = "Red Balance",
235 .minimum = 0,
236 .maximum = 0x7f,
237 .step = 1,
238 .default_value = 0x20,
241 .id = V4L2_CID_BLUE_BALANCE,
242 .type = V4L2_CTRL_TYPE_INTEGER,
243 .name = "Blue Balance",
244 .minimum = 0,
245 .maximum = 0x7f,
246 .step = 1,
247 .default_value = 0x20,
250 .id = V4L2_CID_AUTOEXPOSURE,
251 .type = V4L2_CTRL_TYPE_BOOLEAN,
252 .name = "Automatic exposure control",
253 .minimum = 0,
254 .maximum = 1,
255 .step = 1,
256 .default_value = 0,
259 .id = V4L2_CID_AUTO_WHITE_BALANCE,
260 .type = V4L2_CTRL_TYPE_BOOLEAN,
261 .name = "Automatic whitbalance control",
262 .minimum = 0,
263 .maximum = 1,
264 .step = 1,
265 .default_value = 0,
270 * @brief Get V4L privileges
272 * @param file
274 * @return 0 or negative error code
277 int v4l_get_privileges(struct file *file)
279 struct usb_microdia *dev;
280 int ret = 0;
282 dev = video_get_drvdata(video_devdata(file));
284 if (dev->owner == file)
285 return 0;
287 mutex_lock(&open_lock);
288 if (dev->owner != NULL) {
289 ret = -EBUSY;
290 goto done;
292 dev->owner = file;
293 done:
294 mutex_unlock(&open_lock);
295 return ret;
299 * @brief Check whether there are V4L privileges
301 * @param file
303 * @return 0 or 1
306 int v4l_has_privileges(struct file *file)
308 struct usb_microdia *dev;
309 int ret = 0;
311 dev = video_get_drvdata(video_devdata(file));
313 if (dev->owner == file)
314 ret = 1;
316 return ret;
320 * @brief Drop V4L privileges
322 * @param file
325 void v4l_drop_privileges(struct file *file)
327 struct usb_microdia *dev;
329 dev = video_get_drvdata(video_devdata(file));
331 if (dev->owner == file)
332 dev->owner = NULL;
336 * @brief Enable video stream
338 * @param dev Pointer to device structure
339 * @param mode Mode for video stream
341 * @returns 0 or negative error value
344 int v4l2_enable_video(struct usb_microdia *dev, int mode)
346 int ret;
348 if (mode == MICRODIA_MODE_IDLE) {
349 dev_microdia_stop_stream(dev);
350 usb_microdia_isoc_cleanup(dev);
351 dev_microdia_camera_off(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 dev_microdia_camera_on(dev);
364 ret = usb_microdia_isoc_init(dev);
366 if (ret)
367 return ret;
369 dev_microdia_start_stream(dev);
370 dev_microdia_camera_settings(dev);
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 MICRODIA_FRAME_SIZE);
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;
499 microdia_decompress(dev, &buffer);
500 dev->queue.read_buffer = &dev->queue.buffer[buffer.index];
501 } else {
502 buffer = dev->queue.read_buffer->buf;
505 count = min((size_t)(buffer.bytesused - *f_pos), count);
506 if (copy_to_user(buf, dev->queue.mem + buffer.m.offset + *f_pos, count))
507 return -EFAULT;
509 *f_pos += count;
510 if (*f_pos >= buffer.bytesused) {
511 dev->queue.read_buffer = NULL;
512 microdia_queue_buffer(&dev->queue, &buffer);
513 *f_pos = 0;
515 return count;
520 * @param fp File pointer
521 * @param wait
523 * @returns 0 if all is OK
525 * @brief Polling function
527 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
529 struct usb_microdia *dev;
530 struct video_device *vdev;
532 vdev = video_devdata(fp);
533 dev = video_get_drvdata(video_devdata(fp));
535 UDIA_STREAM("Poll\n");
537 if (vdev == NULL || dev == NULL)
538 return -EFAULT;
540 return microdia_queue_poll(&dev->queue, fp, wait);
544 * @param vma
547 static void microdia_vm_open(struct vm_area_struct *vma)
549 struct microdia_buffer *buffer = vma->vm_private_data;
550 buffer->vma_use_count++;
555 * @param vma
558 static void microdia_vm_close(struct vm_area_struct *vma)
560 struct microdia_buffer *buffer = vma->vm_private_data;
561 buffer->vma_use_count--;
564 struct vm_operations_struct microdia_vm_ops = {
565 .open = microdia_vm_open,
566 .close = microdia_vm_close
570 * @param fp File pointer
571 * @param vma VMA structure
573 * @returns 0 if all is OK
575 * @brief Memory map
577 * This function permits to map a memory space.
579 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
581 struct page *page;
582 unsigned long addr, start, size;
583 unsigned int i;
584 int ret = 0;
586 struct usb_microdia *dev;
587 struct video_device *vdev;
588 struct microdia_buffer *buffer = NULL;
590 vdev = video_devdata(fp);
591 dev = video_get_drvdata(video_devdata(fp));
593 UDIA_STREAM("mmap\n");
595 start = vma->vm_start;
596 size = vma->vm_end - vma->vm_start;
598 mutex_lock(&dev->queue.mutex);
600 for (i = 0; i < dev->queue.count; ++i) {
601 buffer = &dev->queue.buffer[i];
602 if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
603 break;
606 if (i == dev->queue.count || size != dev->queue.buf_size) {
607 ret = -EINVAL;
608 goto done;
611 vma->vm_flags |= VM_IO;
613 addr = (unsigned long)dev->queue.mem + buffer->buf.m.offset;
614 while (size > 0) {
615 page = vmalloc_to_page((void *)addr);
616 ret = vm_insert_page(vma, start, page);
617 if (ret < 0)
618 goto done;
620 start += PAGE_SIZE;
621 addr += PAGE_SIZE;
622 size -= PAGE_SIZE;
625 vma->vm_ops = &microdia_vm_ops;
626 vma->vm_private_data = buffer;
627 microdia_vm_open(vma);
628 done:
629 mutex_unlock(&dev->queue.mutex);
630 return ret;
634 * @param file
635 * @param priv
636 * @param cap
638 * @return 0
641 int microdia_vidioc_querycap(struct file *file, void *priv,
642 struct v4l2_capability *cap)
644 struct usb_microdia *dev;
646 dev = video_get_drvdata(priv);
648 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
650 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
651 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
652 | V4L2_CAP_READWRITE;
653 cap->version = (__u32) DRIVER_VERSION_NUM,
654 strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
656 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
657 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
658 return 0;
662 * @param file
663 * @param priv
664 * @param input
666 * @return 0 or negative error code
669 int microdia_vidioc_enum_input(struct file *file, void *priv,
670 struct v4l2_input *input)
672 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", input->index);
674 if (input->index)
675 return -EINVAL;
677 strlcpy(input->name, "Webcam", sizeof(input->name));
678 input->type = V4L2_INPUT_TYPE_CAMERA;
679 input->std = 0;
681 return 0;
685 * @param file
686 * @param priv
687 * @param index
689 * @return 0 or negative error code
692 int microdia_vidioc_g_input(struct file *file, void *priv, unsigned int *index)
694 UDIA_DEBUG("GET INPUT %d\n", *index);
696 if (index)
697 return -EINVAL;
699 return 0;
703 * @param file
704 * @param priv
705 * @param index
707 * @return 0 or negative error code
710 int microdia_vidioc_s_input(struct file *file, void *priv, unsigned int index)
712 UDIA_DEBUG("SET INPUT %d\n", index);
714 if (v4l_get_privileges(file) < 0)
715 return -EBUSY;
717 if (index != 0)
718 return -EINVAL;
720 return 0;
724 * @param file
725 * @param priv
726 * @param ctrl
728 * @return 0 or negative error code
731 int microdia_vidioc_queryctrl(struct file *file, void *priv,
732 struct v4l2_queryctrl *ctrl)
734 int i;
735 int nbr;
737 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl->id);
739 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
741 for (i = 0; i < nbr; i++) {
742 if (microdia_controls[i].id == ctrl->id) {
743 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
744 memcpy(ctrl, &microdia_controls[i],
745 sizeof(struct v4l2_queryctrl));
746 break;
750 if (i >= nbr)
751 return -EINVAL;
753 return 0;
757 * @param file
758 * @param priv
759 * @param ctrl
761 * @return 0 or negative error code
764 int microdia_vidioc_g_ctrl(struct file *file, void *priv,
765 struct v4l2_control *ctrl)
767 struct usb_microdia *dev;
769 dev = video_get_drvdata(priv);
771 UDIA_DEBUG("GET CTRL id=%d\n", ctrl->id);
773 switch (ctrl->id) {
774 case V4L2_CID_BRIGHTNESS:
775 ctrl->value = dev->vsettings.brightness;
776 break;
778 case V4L2_CID_EXPOSURE:
779 ctrl->value = dev->vsettings.exposure;
780 break;
782 case V4L2_CID_WHITENESS:
783 ctrl->value = dev->vsettings.whiteness;
784 break;
786 case V4L2_CID_SATURATION:
787 ctrl->value = dev->vsettings.colour;
788 break;
790 case V4L2_CID_CONTRAST:
791 ctrl->value = dev->vsettings.contrast;
792 break;
794 case V4L2_CID_HFLIP:
795 ctrl->value = dev->vsettings.hflip;
796 break;
798 case V4L2_CID_VFLIP:
799 ctrl->value = dev->vsettings.vflip;
800 break;
802 case V4L2_CID_SHARPNESS:
803 ctrl->value = dev->vsettings.sharpness;
804 break;
806 case V4L2_CID_RED_BALANCE:
807 ctrl->value = dev->vsettings.rgb_gain[0];
808 break;
810 case V4L2_CID_BLUE_BALANCE:
811 ctrl->value = dev->vsettings.rgb_gain[3];
812 break;
814 case V4L2_CID_AUTOEXPOSURE:
815 ctrl->value = dev->vsettings.auto_exposure;
816 break;
818 case V4L2_CID_AUTO_WHITE_BALANCE:
819 ctrl->value = dev->vsettings.auto_whitebalance;
820 break;
822 default:
823 return -EINVAL;
825 return 0;
829 * @brief Apply v4l2 settings on camera
831 * @param file
832 * @param priv
833 * @param ctrl V4L2 control structure
835 * @returns 0 or negative error value
838 int microdia_vidioc_s_ctrl(struct file *file, void *priv,
839 struct v4l2_control *ctrl)
841 struct usb_microdia *dev;
843 dev = video_get_drvdata(priv);
845 UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl->id, ctrl->value);
847 switch (ctrl->id) {
848 case V4L2_CID_BRIGHTNESS:
849 dev->vsettings.brightness = (0xff00 & ctrl->value);
850 dev_microdia_camera_set_brightness(dev);
851 break;
853 case V4L2_CID_EXPOSURE:
854 dev->vsettings.exposure = (0xff00 & ctrl->value);
855 dev_microdia_camera_set_exposure(dev);
856 break;
858 case V4L2_CID_WHITENESS:
859 dev->vsettings.whiteness = (0xff00 & ctrl->value);
860 dev_microdia_camera_set_gamma(dev);
861 break;
863 case V4L2_CID_SATURATION:
864 dev->vsettings.colour = (0xff00 & ctrl->value);
865 break;
867 case V4L2_CID_CONTRAST:
868 dev->vsettings.contrast = (0xff00 & ctrl->value);
869 dev_microdia_camera_set_contrast(dev);
870 break;
872 case V4L2_CID_HFLIP:
873 dev->vsettings.hflip = ctrl->value;
874 dev_microdia_camera_set_hvflip(dev);
875 break;
877 case V4L2_CID_VFLIP:
878 dev->vsettings.vflip = ctrl->value;
879 dev_microdia_camera_set_hvflip(dev);
880 break;
882 case V4L2_CID_SHARPNESS:
883 dev->vsettings.sharpness = ctrl->value;
884 dev_microdia_camera_set_sharpness(dev);
885 break;
887 case V4L2_CID_RED_BALANCE:
888 dev->vsettings.rgb_gain[0] = ctrl->value;
889 dev_microdia_camera_set_rgb_gain(dev);
890 break;
892 case V4L2_CID_BLUE_BALANCE:
893 dev->vsettings.rgb_gain[3] = ctrl->value;
894 dev_microdia_camera_set_rgb_gain(dev);
895 break;
897 case V4L2_CID_AUTOEXPOSURE:
898 dev->vsettings.auto_exposure = ctrl->value;
899 dev_microdia_camera_set_auto_exposure(dev);
900 break;
902 case V4L2_CID_AUTO_WHITE_BALANCE:
903 dev->vsettings.auto_whitebalance = ctrl->value;
904 dev_microdia_camera_set_auto_whitebalance(dev);
905 break;
907 default:
908 return -EINVAL;
911 return 0;
915 * @param file
916 * @param priv
917 * @param fmt
919 * @return 0 or negative error code
922 int microdia_vidioc_enum_fmt_cap(struct file *file, void *priv,
923 struct v4l2_fmtdesc *fmt)
925 struct usb_microdia *dev;
926 struct v4l2_pix_format *format;
928 dev = video_get_drvdata(priv);
930 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmt->index);
932 format = v4l2_enum_supported_formats(dev, fmt->index);
933 if (format == NULL)
934 return -EINVAL;
936 fmt->flags = 0;
937 fmt->pixelformat = format->pixelformat;
938 fmt->description[0] = fmt->pixelformat & 0xFF;
939 fmt->description[1] = (fmt->pixelformat >> 8) & 0xFF;
940 fmt->description[2] = (fmt->pixelformat >> 16) & 0xFF;
941 fmt->description[3] = fmt->pixelformat >> 24;
942 fmt->description[4] = 0;
944 return 0;
948 * @param file
949 * @param priv
950 * @param fmt
952 * @return 0 or negative error code
955 int microdia_vidioc_try_fmt_cap(struct file *file, void *priv,
956 struct v4l2_format *fmt)
958 struct usb_microdia *dev;
960 dev = video_get_drvdata(priv);
961 UDIA_DEBUG("TRY FMT %d\n", fmt->type);
963 /* when this code is used prevents mplayer from setting outfmt
964 if(fmt->fmt.pix.field != V4L2_FIELD_NONE)
965 return -EINVAL;
968 if (v4l2_format_supported(dev, fmt->fmt.pix.pixelformat) < 0)
969 return -EINVAL;
971 sn9c20x_get_closest_resolution(&fmt->fmt.pix.width,
972 &fmt->fmt.pix.height);
974 switch (fmt->fmt.pix.pixelformat) {
975 case V4L2_PIX_FMT_YUV420:
976 fmt->fmt.pix.bytesperline = (fmt->fmt.pix.width * 3)/2;
977 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
978 fmt->fmt.pix.bytesperline;
979 break;
980 case V4L2_PIX_FMT_RGB24:
981 case V4L2_PIX_FMT_BGR24:
982 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
983 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
984 fmt->fmt.pix.bytesperline;
985 break;
986 case V4L2_PIX_FMT_YUYV:
987 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 2;
988 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
989 fmt->fmt.pix.bytesperline;
990 break;
991 default:
992 return -EINVAL;
995 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
996 fmt->fmt.pix.priv = 0;
998 return 0;
1002 * @param file
1003 * @param priv
1004 * @param fmt
1006 * @return 0
1009 int microdia_vidioc_g_fmt_cap(struct file *file, void *priv,
1010 struct v4l2_format *fmt)
1012 struct usb_microdia *dev;
1014 dev = video_get_drvdata(priv);
1016 UDIA_DEBUG("GET FMT %d\n", fmt->type);
1018 memcpy(&(fmt->fmt.pix), &(dev->vsettings.format), sizeof(fmt->fmt.pix));
1021 return 0;
1025 * @param file
1026 * @param priv
1027 * @param fmt
1029 * @return 0 or negative error code
1032 int microdia_vidioc_s_fmt_cap(struct file *file, void *priv,
1033 struct v4l2_format *fmt)
1035 struct usb_microdia *dev;
1036 int ret;
1038 dev = video_get_drvdata(priv);
1040 UDIA_DEBUG("SET FMT %d : %d\n", fmt->type, fmt->fmt.pix.pixelformat);
1042 if (v4l_get_privileges(file) < 0)
1043 return -EBUSY;
1045 if (dev->queue.streaming)
1046 return -EBUSY;
1048 ret = microdia_vidioc_try_fmt_cap(file, priv, fmt);
1049 if (ret)
1050 return -EINVAL;
1052 sn9c20x_set_resolution(dev, fmt->fmt.pix.width, fmt->fmt.pix.height);
1054 memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix));
1056 return 0;
1060 * @param file
1061 * @param priv
1062 * @param request
1064 * @return 0 or negative error code
1067 int microdia_vidioc_reqbufs(struct file *file, void *priv,
1068 struct v4l2_requestbuffers *request)
1070 int ret = 0;
1071 struct usb_microdia *dev;
1073 dev = video_get_drvdata(priv);
1075 if (v4l_get_privileges(file) < 0) {
1076 ret = -EBUSY;
1077 goto done;
1080 if (request->memory != V4L2_MEMORY_MMAP ||
1081 request->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1082 ret = -EINVAL;
1083 goto done;
1086 if (dev->queue.streaming) {
1087 ret = -EBUSY;
1088 goto done;
1091 ret = microdia_alloc_buffers(&dev->queue, request->count,
1092 MICRODIA_FRAME_SIZE);
1093 if (ret < 0)
1094 goto done;
1096 dev->queue.drop_incomplete = 1;
1098 request->count = ret;
1099 ret = 0;
1100 UDIA_INFO("Buffers Allocated %d\n", request->count);
1101 done:
1102 return ret;
1106 * @param file
1107 * @param priv
1108 * @param buffer
1110 * @return 0 or negative error code
1113 int microdia_vidioc_querybuf(struct file *file, void *priv,
1114 struct v4l2_buffer *buffer)
1116 struct usb_microdia *dev;
1118 dev = video_get_drvdata(priv);
1120 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buffer->index, dev->queue.count);
1122 if (buffer->memory != V4L2_MEMORY_MMAP ||
1123 buffer->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1124 return -EINVAL;
1126 if (!v4l_has_privileges(file))
1127 return -EBUSY;
1129 return microdia_query_buffer(&dev->queue, buffer);
1133 * @param file
1134 * @param priv
1135 * @param buffer
1137 * @return 0 or negative error code
1140 int microdia_vidioc_qbuf(struct file *file, void *priv,
1141 struct v4l2_buffer *buffer)
1143 struct usb_microdia *dev;
1145 dev = video_get_drvdata(priv);
1147 UDIA_DEBUG("VIDIOC_QBUF\n");
1149 if (!v4l_has_privileges(file))
1150 return -EBUSY;
1152 return microdia_queue_buffer(&dev->queue, buffer);
1156 * @param file
1157 * @param priv
1158 * @param buffer
1160 * @return 0 or negative error code
1163 int microdia_vidioc_dqbuf(struct file *file, void *priv,
1164 struct v4l2_buffer *buffer)
1166 struct usb_microdia *dev;
1167 int ret = 0;
1169 dev = video_get_drvdata(priv);
1171 UDIA_DEBUG("VIDIOC_DQBUF\n");
1173 if (!v4l_has_privileges(file))
1174 return -EBUSY;
1176 ret = microdia_dequeue_buffer(&dev->queue, buffer,
1177 file->f_flags & O_NONBLOCK);
1178 if (ret < 0)
1179 return ret;
1181 microdia_decompress(dev, buffer);
1183 return ret;
1187 * @param file
1188 * @param priv
1189 * @param type
1191 * @return 0 or negative error code
1194 int microdia_vidioc_streamon(struct file *file, void *priv,
1195 enum v4l2_buf_type type)
1197 struct usb_microdia *dev;
1199 dev = video_get_drvdata(priv);
1201 UDIA_DEBUG("VIDIOC_STREAMON\n");
1203 if (!v4l_has_privileges(file))
1204 return -EBUSY;
1206 if (dev->mode != MICRODIA_MODE_IDLE)
1207 return -EBUSY;
1209 return v4l2_enable_video(dev, MICRODIA_MODE_STREAM);
1213 * @param file
1214 * @param priv
1215 * @param type
1217 * @return 0 or negative error code
1220 int microdia_vidioc_streamoff(struct file *file, void *priv,
1221 enum v4l2_buf_type type)
1223 struct usb_microdia *dev;
1225 dev = video_get_drvdata(priv);
1227 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1229 if (!v4l_has_privileges(file))
1230 return -EBUSY;
1232 return v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
1236 * @param file
1237 * @param priv
1238 * @param param
1240 * @return 0 or negative error code
1243 int microdia_vidioc_g_param(struct file *file, void *priv,
1244 struct v4l2_streamparm *param)
1246 struct usb_microdia *dev;
1249 dev = video_get_drvdata(priv);
1251 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1252 return -EINVAL;
1254 param->parm.capture.capability = 0;
1255 param->parm.capture.capturemode = 0;
1256 param->parm.capture.timeperframe.numerator = 1;
1257 param->parm.capture.timeperframe.denominator = 30;
1258 param->parm.capture.readbuffers = 2;
1259 param->parm.capture.extendedmode = 0;
1261 return 0;
1265 * @param file
1266 * @param priv
1267 * @param param
1269 * @return 0 or negative error code
1272 int microdia_vidioc_s_param(struct file *file, void *priv,
1273 struct v4l2_streamparm *param)
1275 struct usb_microdia *dev;
1277 dev = video_get_drvdata(priv);
1279 if (v4l_get_privileges(file))
1280 return -EBUSY;
1282 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1283 return -EINVAL;
1285 return 0;
1289 * @param inode Inode pointer
1290 * @param fp File pointer
1291 * @param cmd Command
1292 * @param arg Arguements of the command
1294 * @returns 0 if all is OK
1296 * @brief Manage IOCTL
1298 * This function permits to manage all the IOCTL from the application.
1300 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1301 unsigned int cmd, unsigned long arg)
1303 int err;
1304 struct usb_microdia *dev;
1305 struct video_device *vdev;
1307 vdev = video_devdata(fp);
1308 dev = video_get_drvdata(video_devdata(fp));
1310 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1312 if (dev == NULL || vdev == NULL)
1313 return -EFAULT;
1315 err = video_ioctl2(inode, fp, cmd, arg);
1317 return err;
1321 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
1322 static const struct v4l2_ioctl_ops microdia_v4l2_ioctl_ops = {
1323 .vidioc_querycap = microdia_vidioc_querycap,
1324 .vidioc_enum_fmt_vid_cap = microdia_vidioc_enum_fmt_cap,
1325 .vidioc_try_fmt_vid_cap = microdia_vidioc_try_fmt_cap,
1326 .vidioc_s_fmt_vid_cap = microdia_vidioc_s_fmt_cap,
1327 .vidioc_g_fmt_vid_cap = microdia_vidioc_g_fmt_cap,
1328 .vidioc_enum_input = microdia_vidioc_enum_input,
1329 .vidioc_g_input = microdia_vidioc_g_input,
1330 .vidioc_s_input = microdia_vidioc_s_input,
1331 .vidioc_streamon = microdia_vidioc_streamon,
1332 .vidioc_streamoff = microdia_vidioc_streamoff,
1333 .vidioc_queryctrl = microdia_vidioc_queryctrl,
1334 .vidioc_g_ctrl = microdia_vidioc_g_ctrl,
1335 .vidioc_s_ctrl = microdia_vidioc_s_ctrl,
1336 .vidioc_g_parm = microdia_vidioc_g_param,
1337 .vidioc_s_parm = microdia_vidioc_s_param,
1338 .vidioc_reqbufs = microdia_vidioc_reqbufs,
1339 .vidioc_qbuf = microdia_vidioc_qbuf,
1340 .vidioc_dqbuf = microdia_vidioc_dqbuf,
1341 .vidioc_querybuf = microdia_vidioc_querybuf,
1343 #endif
1346 * @param dev Device structure
1348 * @returns 0 if all is OK
1350 * @brief Register the video device
1352 * This function permits to register the USB device to the video device.
1354 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1356 int err;
1358 strcpy(dev->vdev->name, DRIVER_DESC);
1360 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
1361 dev->vdev->dev = &dev->interface->dev;
1362 dev->vdev->owner = THIS_MODULE;
1363 dev->vdev->type = VID_TYPE_CAPTURE;
1364 #else
1365 dev->vdev->dev = dev->interface->dev;
1366 #endif
1367 dev->vdev->current_norm = 0;
1368 dev->vdev->tvnorms = 0;
1369 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1370 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1371 #endif
1372 dev->vdev->fops = &v4l_microdia_fops;
1373 dev->vdev->release = video_device_release;
1374 dev->vdev->minor = -1;
1376 if (log_level & MICRODIA_DEBUG)
1377 dev->vdev->debug = V4L2_DEBUG_IOCTL_ARG;
1379 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
1380 dev->vdev->vidioc_querycap = microdia_vidioc_querycap;
1381 dev->vdev->vidioc_enum_fmt_cap = microdia_vidioc_enum_fmt_cap;
1382 dev->vdev->vidioc_try_fmt_cap = microdia_vidioc_try_fmt_cap;
1383 dev->vdev->vidioc_s_fmt_cap = microdia_vidioc_s_fmt_cap;
1384 dev->vdev->vidioc_g_fmt_cap = microdia_vidioc_g_fmt_cap;
1385 dev->vdev->vidioc_enum_input = microdia_vidioc_enum_input;
1386 dev->vdev->vidioc_g_input = microdia_vidioc_g_input;
1387 dev->vdev->vidioc_s_input = microdia_vidioc_s_input;
1388 dev->vdev->vidioc_streamon = microdia_vidioc_streamon;
1389 dev->vdev->vidioc_streamoff = microdia_vidioc_streamoff;
1390 dev->vdev->vidioc_queryctrl = microdia_vidioc_queryctrl;
1391 dev->vdev->vidioc_g_ctrl = microdia_vidioc_g_ctrl;
1392 dev->vdev->vidioc_s_ctrl = microdia_vidioc_s_ctrl;
1393 dev->vdev->vidioc_g_parm = microdia_vidioc_g_param;
1394 dev->vdev->vidioc_s_parm = microdia_vidioc_s_param;
1395 dev->vdev->vidioc_reqbufs = microdia_vidioc_reqbufs;
1396 dev->vdev->vidioc_qbuf = microdia_vidioc_qbuf;
1397 dev->vdev->vidioc_dqbuf = microdia_vidioc_dqbuf;
1398 dev->vdev->vidioc_querybuf = microdia_vidioc_querybuf;
1399 #else
1400 dev->vdev->ioctl_ops = &microdia_v4l2_ioctl_ops;
1401 #endif
1403 video_set_drvdata(dev->vdev, dev);
1405 microdia_queue_init(&dev->queue);
1407 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1409 if (err)
1410 UDIA_ERROR("Video register fail !\n");
1411 else
1412 UDIA_INFO("Microdia USB 2.0 Webcam is now controlling "
1413 "video device /dev/video%d\n",
1414 dev->vdev->minor);
1416 return err;
1421 * @param dev Device structure
1423 * @returns 0 if all is OK
1425 * @brief Unregister the video device
1427 * This function permits to unregister the video device.
1429 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1431 UDIA_INFO("Microdia USB 2.0 Webcam releases control of video "
1432 "device /dev/video%d\n", dev->vdev->minor);
1434 video_set_drvdata(dev->vdev, NULL);
1435 video_unregister_device(dev->vdev);
1437 return 0;
1442 * @var v4l_microdia_fops
1444 * This variable contains some callback
1446 static struct file_operations v4l_microdia_fops = {
1447 .owner = THIS_MODULE,
1448 .open = v4l_microdia_open,
1449 .release = v4l_microdia_release,
1450 .read = v4l_microdia_read,
1451 .poll = v4l_microdia_poll,
1452 .mmap = v4l_microdia_mmap,
1453 .ioctl = v4l_microdia_ioctl,
1454 #ifdef CONFIG_COMPAT
1455 .compat_ioctl = v4l_compat_ioctl32,
1456 #endif
1457 .llseek = no_llseek