Support for hardware resolultion change
[microdia.git] / microdia-v4l.c
blob753966a9b834834f97d79d25b99d5db2a2dd880d
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"
40 #include "sn9c20x.h"
43 /* USER DEFINED V4L2-CONTROLS: */
44 #define V4L2_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE + 0)
45 #define V4L2_CID_AUTOEXPOSURE (V4L2_CID_PRIVATE_BASE + 1)
48 static struct file_operations v4l_microdia_fops;
50 /**
51 * format list
54 #define NUM_V4L2_FORMATS 4
56 struct v4l2_pix_format microdia_fmts[] = {
58 .width = 640,
59 .height = 480,
60 .pixelformat = V4L2_PIX_FMT_YUV420,
61 .field = V4L2_FIELD_NONE,
62 .bytesperline = 960,
63 .sizeimage = 460800,
64 .colorspace = V4L2_COLORSPACE_SRGB,
65 .priv = 0
68 .width = 640,
69 .height = 480,
70 .pixelformat = V4L2_PIX_FMT_BGR24,
71 .field = V4L2_FIELD_NONE,
72 .bytesperline = 1920,
73 .sizeimage = 921600,
74 .colorspace = V4L2_COLORSPACE_SRGB,
75 .priv = 0
78 .width = 640,
79 .height = 480,
80 .pixelformat = V4L2_PIX_FMT_RGB24,
81 .field = V4L2_FIELD_NONE,
82 .bytesperline = 1920,
83 .sizeimage = 921600,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .priv = 0
88 .width = 640,
89 .height = 480,
90 .pixelformat = V4L2_PIX_FMT_YUYV,
91 .field = V4L2_FIELD_NONE,
92 .bytesperline = 1280,
93 .sizeimage = 614400,
94 .colorspace = V4L2_COLORSPACE_SRGB,
95 .priv = 0
99 /**
100 * @param dev
101 * @param fmt v4l2 fmt id
103 * @returns index of requested format
105 * @brief check if v4l2 forat is supported by device.
107 * This function permits to check if v4l2 format is supported.
109 int v4l2_format_supported(struct usb_microdia *dev, __u32 fmt)
111 int i;
112 for (i = 0; i < sizeof(dev->supported_fmts) * 8; i++) {
113 if (i > (ARRAY_SIZE(microdia_fmts) - 1))
114 break;
115 if (dev->supported_fmts & (1 << i) &&
116 microdia_fmts[i].pixelformat == fmt)
117 return i;
119 return -EINVAL;
123 * @param dev
124 * @param index format index
126 * @returns reference to format structure
128 * @brief enumerate supported formats
130 * This function will enumerate all supported formats.
132 struct v4l2_pix_format *v4l2_enum_supported_formats(struct usb_microdia *dev,
133 __u8 index)
135 int i, bit = 0;
136 for (i = 0; i < sizeof(dev->supported_fmts) * 8; i++) {
137 if (i > (ARRAY_SIZE(microdia_fmts) - 1))
138 break;
139 if (dev->supported_fmts & (1 << i)) {
140 if (bit == index)
141 return &microdia_fmts[i];
142 bit++;
145 return NULL;
149 * @var microdia_controls
150 * List of all V4Lv2 controls supported by the driver
152 static struct v4l2_queryctrl microdia_controls[] = {
154 .id = V4L2_CID_BRIGHTNESS,
155 .type = V4L2_CTRL_TYPE_INTEGER,
156 .name = "Brightness",
157 .minimum = 0,
158 .maximum = 0xff00,
159 .step = 1,
160 .default_value = 0x7f00,
163 .id = V4L2_CID_WHITENESS,
164 .type = V4L2_CTRL_TYPE_INTEGER,
165 .name = "Whiteness",
166 .minimum = 0,
167 .maximum = 0xff00,
168 .step = 1,
169 .default_value = 0x7f00,
173 .id = V4L2_CID_SATURATION,
174 .type = V4L2_CTRL_TYPE_INTEGER,
175 .name = "Saturation",
176 .minimum = 0,
177 .maximum = 0xff00,
178 .step = 1,
179 .default_value = 0x7f00,
183 .id = V4L2_CID_CONTRAST,
184 .type = V4L2_CTRL_TYPE_INTEGER,
185 .name = "Contrast",
186 .minimum = 0,
187 .maximum = 0xff00,
188 .step = 1,
189 .default_value = 0x0000,
192 .id = V4L2_CID_EXPOSURE,
193 .type = V4L2_CTRL_TYPE_INTEGER,
194 .name = "Exposure",
195 .minimum = 0,
196 .maximum = 0xff00,
197 .step = 1,
198 .default_value = 0x1000,
201 .id = V4L2_CID_HFLIP,
202 .type = V4L2_CTRL_TYPE_BOOLEAN,
203 .name = "Horizontal flip",
204 .minimum = 0,
205 .maximum = 1,
206 .step = 1,
207 .default_value = 0,
210 .id = V4L2_CID_VFLIP,
211 .type = V4L2_CTRL_TYPE_BOOLEAN,
212 .name = "Vertical flip",
213 .minimum = 0,
214 .maximum = 1,
215 .step = 1,
216 .default_value = 0,
219 .id = V4L2_CID_SHARPNESS,
220 .type = V4L2_CTRL_TYPE_INTEGER,
221 .name = "Sharpness",
222 .minimum = 0,
223 .maximum = 0x3f,
224 .step = 1,
225 .default_value = 0x1f,
228 .id = V4L2_CID_RED_BALANCE,
229 .type = V4L2_CTRL_TYPE_INTEGER,
230 .name = "Red Balance",
231 .minimum = 0,
232 .maximum = 0x7f,
233 .step = 1,
234 .default_value = 0x20,
237 .id = V4L2_CID_BLUE_BALANCE,
238 .type = V4L2_CTRL_TYPE_INTEGER,
239 .name = "Blue Balance",
240 .minimum = 0,
241 .maximum = 0x7f,
242 .step = 1,
243 .default_value = 0x20,
246 .id = V4L2_CID_AUTOEXPOSURE,
247 .type = V4L2_CTRL_TYPE_BOOLEAN,
248 .name = "Automatic exposure control",
249 .minimum = 0,
250 .maximum = 1,
251 .step = 1,
252 .default_value = 0,
255 .id = V4L2_CID_AUTO_WHITE_BALANCE,
256 .type = V4L2_CTRL_TYPE_BOOLEAN,
257 .name = "Automatic whitbalance control",
258 .minimum = 0,
259 .maximum = 1,
260 .step = 1,
261 .default_value = 0,
266 * The following three functions are used to get, test and drop v4l privleges.
268 int v4l_get_privileges(struct file *file)
270 struct usb_microdia *dev;
271 int ret = 0;
273 dev = video_get_drvdata(video_devdata(file));
275 if (dev->owner == file)
276 return 0;
278 mutex_lock(&open_lock);
279 if (dev->owner != NULL) {
280 ret = -EBUSY;
281 goto done;
283 dev->owner = file;
284 done:
285 mutex_unlock(&open_lock);
286 return ret;
289 int v4l_has_privileges(struct file *file)
291 struct usb_microdia *dev;
292 int ret = 0;
294 dev = video_get_drvdata(video_devdata(file));
296 if (dev->owner == file)
297 ret = 1;
299 return ret;
302 void v4l_drop_privileges(struct file *file)
304 struct usb_microdia *dev;
306 dev = video_get_drvdata(video_devdata(file));
308 if (dev->owner == file)
309 dev->owner = NULL;
312 int v4l2_enable_video(struct usb_microdia *dev, int mode)
314 int ret;
316 if (mode == MICRODIA_MODE_IDLE) {
317 dev_microdia_stop_stream(dev);
318 usb_microdia_isoc_cleanup(dev);
319 dev_microdia_camera_off(dev);
320 microdia_queue_enable(&dev->queue, 0);
321 dev->mode = mode;
322 return 0;
325 if (dev->mode != MICRODIA_MODE_IDLE)
326 return -EBUSY;
328 if (microdia_queue_enable(&dev->queue, 1) < 0)
329 return -EBUSY;
331 dev_microdia_camera_on(dev);
332 ret = usb_microdia_isoc_init(dev);
334 if (ret)
335 return ret;
337 dev_microdia_start_stream(dev);
338 dev_microdia_camera_settings(dev);
339 dev->mode = mode;
341 return 0;
345 * @param inode Pointer on an inode
346 * @param fp File pointer
348 * @returns 0 if all is OK
350 * @brief Open the video device
352 * This function permits to open a video device (/dev/videoX)
354 static int v4l_microdia_open(struct inode *inode, struct file *fp)
356 int ret = 0;
358 struct usb_microdia *dev;
359 struct video_device *vdev;
361 mutex_lock(&open_lock);
363 vdev = video_devdata(fp);
364 dev = video_get_drvdata(video_devdata(fp));
366 fp->private_data = vdev;
368 kref_get(&dev->vopen);
370 mutex_unlock(&open_lock);
371 return ret;
376 * @param inode Pointer on inode
377 * @param fp File pointer
379 * @returns 0 if all is OK
381 * @brief Release an opened file.
383 * This function permits to release an opened file with the 'open' method.
385 static int v4l_microdia_release(struct inode *inode, struct file *fp)
387 struct usb_microdia *dev;
388 struct video_device *vdev;
390 mutex_lock(&open_lock);
392 vdev = video_devdata(fp);
393 dev = video_get_drvdata(video_devdata(fp));
395 if (v4l_has_privileges(fp)) {
396 v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
398 mutex_lock(&dev->queue.mutex);
399 microdia_free_buffers(&dev->queue);
400 mutex_unlock(&dev->queue.mutex);
403 v4l_drop_privileges(fp);
405 kref_put(&dev->vopen, usb_microdia_delete);
407 mutex_unlock(&open_lock);
408 return 0;
413 * @param fp File pointer
415 * @retval buf Buffer in user space
416 * @retval count
417 * @retval f_pos
419 * @returns Count value
421 * @brief Read the video device
423 * This function is called by the application is reading the video device.
425 static ssize_t v4l_microdia_read(struct file *fp, char __user *buf,
426 size_t count, loff_t *f_pos)
428 int i, ret;
429 int nbuffers;
430 struct v4l2_buffer buffer;
431 struct usb_microdia *dev;
433 dev = video_get_drvdata(video_devdata(fp));
435 ret = v4l_get_privileges(fp);
436 if (ret < 0)
437 return ret;
439 if (dev->mode != MICRODIA_MODE_IDLE &&
440 dev->mode != MICRODIA_MODE_READ)
441 return -EBUSY;
443 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
444 buffer.memory = V4L2_MEMORY_MMAP;
445 if (dev->mode == MICRODIA_MODE_IDLE) {
446 nbuffers = microdia_alloc_buffers(&dev->queue, 2,
447 MICRODIA_FRAME_SIZE);
448 if (nbuffers < 0)
449 return nbuffers;
451 for (i = 0; i < nbuffers; i++) {
452 buffer = dev->queue.buffer[i].buf;
453 microdia_queue_buffer(&dev->queue, &buffer);
456 ret = v4l2_enable_video(dev, MICRODIA_MODE_READ);
457 if (ret < 0)
458 return ret;
461 if (dev->queue.read_buffer == NULL) {
462 ret = microdia_dequeue_buffer(&dev->queue, &buffer,
463 fp->f_flags & O_NONBLOCK);
464 if (ret < 0)
465 return ret;
467 microdia_decompress(dev, &buffer);
468 dev->queue.read_buffer = &dev->queue.buffer[buffer.index];
469 } else {
470 buffer = dev->queue.read_buffer->buf;
473 count = min((size_t)(buffer.bytesused - *f_pos), count);
474 if (copy_to_user(buf, dev->queue.mem + buffer.m.offset + *f_pos, count))
475 return -EFAULT;
477 *f_pos += count;
478 if (*f_pos >= buffer.bytesused) {
479 dev->queue.read_buffer = NULL;
480 microdia_queue_buffer(&dev->queue, &buffer);
481 *f_pos = 0;
483 return count;
488 * @param fp File pointer
489 * @param wait
491 * @returns 0 if all is OK
493 * @brief Polling function
495 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
497 struct usb_microdia *dev;
498 struct video_device *vdev;
500 vdev = video_devdata(fp);
501 dev = video_get_drvdata(video_devdata(fp));
503 UDIA_STREAM("Poll\n");
505 if (vdev == NULL || dev == NULL)
506 return -EFAULT;
508 return microdia_queue_poll(&dev->queue, fp, wait);
511 static void microdia_vm_open(struct vm_area_struct *vma)
513 struct microdia_buffer *buffer = vma->vm_private_data;
514 buffer->vma_use_count++;
518 static void microdia_vm_close(struct vm_area_struct *vma)
520 struct microdia_buffer *buffer = vma->vm_private_data;
521 buffer->vma_use_count--;
524 struct vm_operations_struct microdia_vm_ops = {
525 .open = microdia_vm_open,
526 .close = microdia_vm_close
530 * @param fp File pointer
531 * @param vma VMA structure
533 * @returns 0 if all is OK
535 * @brief Memory map
537 * This function permits to map a memory space.
539 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
541 struct page *page;
542 unsigned long addr, start, size;
543 unsigned int i;
544 int ret = 0;
546 struct usb_microdia *dev;
547 struct video_device *vdev;
548 struct microdia_buffer *buffer = NULL;
550 vdev = video_devdata(fp);
551 dev = video_get_drvdata(video_devdata(fp));
553 UDIA_STREAM("mmap\n");
555 start = vma->vm_start;
556 size = vma->vm_end - vma->vm_start;
558 mutex_lock(&dev->queue.mutex);
560 for (i = 0; i < dev->queue.count; ++i) {
561 buffer = &dev->queue.buffer[i];
562 if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
563 break;
566 if (i == dev->queue.count || size != dev->queue.buf_size) {
567 ret = -EINVAL;
568 goto done;
571 vma->vm_flags |= VM_IO;
573 addr = (unsigned long)dev->queue.mem + buffer->buf.m.offset;
574 while (size > 0) {
575 page = vmalloc_to_page((void *)addr);
576 ret = vm_insert_page(vma, start, page);
577 if (ret < 0)
578 goto done;
580 start += PAGE_SIZE;
581 addr += PAGE_SIZE;
582 size -= PAGE_SIZE;
585 vma->vm_ops = &microdia_vm_ops;
586 vma->vm_private_data = buffer;
587 microdia_vm_open(vma);
588 done:
589 mutex_unlock(&dev->queue.mutex);
590 return ret;
593 int microdia_vidioc_querycap(struct file *file, void *priv,
594 struct v4l2_capability *cap)
596 struct usb_microdia *dev;
598 dev = video_get_drvdata(priv);
600 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
602 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
603 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
604 | V4L2_CAP_READWRITE;
605 cap->version = (__u32) DRIVER_VERSION_NUM,
606 strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
608 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
609 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
610 return 0;
613 int microdia_vidioc_enum_input(struct file *file, void *priv,
614 struct v4l2_input *input)
616 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", input->index);
618 if (input->index)
619 return -EINVAL;
621 strlcpy(input->name, "Webcam", sizeof(input->name));
622 input->type = V4L2_INPUT_TYPE_CAMERA;
623 input->std = 0;
625 return 0;
628 int microdia_vidioc_g_input(struct file *file, void *priv, unsigned int *index)
630 UDIA_DEBUG("GET INPUT %d\n", *index);
632 if (index)
633 return -EINVAL;
635 return 0;
638 int microdia_vidioc_s_input(struct file *file, void *priv, unsigned int index)
640 UDIA_DEBUG("SET INPUT %d\n", index);
642 if (v4l_get_privileges(file) < 0)
643 return -EBUSY;
645 if (index != 0)
646 return -EINVAL;
648 return 0;
651 int microdia_vidioc_queryctrl(struct file *file, void *priv,
652 struct v4l2_queryctrl *ctrl)
654 int i;
655 int nbr;
657 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl->id);
659 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
661 for (i = 0; i < nbr; i++) {
662 if (microdia_controls[i].id == ctrl->id) {
663 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
664 memcpy(ctrl, &microdia_controls[i],
665 sizeof(struct v4l2_queryctrl));
666 break;
670 if (i >= nbr)
671 return -EINVAL;
673 return 0;
676 int microdia_vidioc_g_ctrl(struct file *file, void *priv,
677 struct v4l2_control *ctrl)
679 struct usb_microdia *dev;
681 dev = video_get_drvdata(priv);
683 UDIA_DEBUG("GET CTRL id=%d\n", ctrl->id);
685 switch (ctrl->id) {
686 case V4L2_CID_BRIGHTNESS:
687 ctrl->value = dev->vsettings.brightness;
688 break;
690 case V4L2_CID_EXPOSURE:
691 ctrl->value = dev->vsettings.exposure;
692 break;
694 case V4L2_CID_WHITENESS:
695 ctrl->value = dev->vsettings.whiteness;
696 break;
698 case V4L2_CID_SATURATION:
699 ctrl->value = dev->vsettings.colour;
700 break;
702 case V4L2_CID_CONTRAST:
703 ctrl->value = dev->vsettings.contrast;
704 break;
706 case V4L2_CID_HFLIP:
707 ctrl->value = dev->vsettings.hflip;
708 break;
710 case V4L2_CID_VFLIP:
711 ctrl->value = dev->vsettings.vflip;
712 break;
714 case V4L2_CID_SHARPNESS:
715 ctrl->value = dev->vsettings.sharpness;
716 break;
718 case V4L2_CID_RED_BALANCE:
719 ctrl->value = dev->vsettings.rgb_gain[0];
720 break;
722 case V4L2_CID_BLUE_BALANCE:
723 ctrl->value = dev->vsettings.rgb_gain[3];
724 break;
726 case V4L2_CID_AUTOEXPOSURE:
727 ctrl->value = dev->vsettings.auto_exposure;
728 break;
730 case V4L2_CID_AUTO_WHITE_BALANCE:
731 ctrl->value = dev->vsettings.auto_whitebalance;
732 break;
734 default:
735 return -EINVAL;
737 return 0;
740 int microdia_vidioc_s_ctrl(struct file *file, void *priv,
741 struct v4l2_control *ctrl)
743 struct usb_microdia *dev;
745 dev = video_get_drvdata(priv);
747 UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl->id, ctrl->value);
749 switch (ctrl->id) {
750 case V4L2_CID_BRIGHTNESS:
751 dev->vsettings.brightness = (0xff00 & ctrl->value);
752 dev_microdia_camera_set_brightness(dev);
753 break;
755 case V4L2_CID_EXPOSURE:
756 dev->vsettings.exposure = (0xff00 & ctrl->value);
757 dev_microdia_camera_set_exposure(dev);
758 break;
760 case V4L2_CID_WHITENESS:
761 dev->vsettings.whiteness = (0xff00 & ctrl->value);
762 dev_microdia_camera_set_gamma(dev);
763 break;
765 case V4L2_CID_SATURATION:
766 dev->vsettings.colour = (0xff00 & ctrl->value);
767 break;
769 case V4L2_CID_CONTRAST:
770 dev->vsettings.contrast = (0xff00 & ctrl->value);
771 dev_microdia_camera_set_contrast(dev);
772 break;
774 case V4L2_CID_HFLIP:
775 dev->vsettings.hflip = ctrl->value;
776 dev_microdia_camera_set_hvflip(dev);
777 break;
779 case V4L2_CID_VFLIP:
780 dev->vsettings.vflip = ctrl->value;
781 dev_microdia_camera_set_hvflip(dev);
782 break;
784 case V4L2_CID_SHARPNESS:
785 dev->vsettings.sharpness = ctrl->value;
786 dev_microdia_camera_set_sharpness(dev);
787 break;
789 case V4L2_CID_RED_BALANCE:
790 dev->vsettings.rgb_gain[0] = ctrl->value;
791 dev_microdia_camera_set_rgb_gain(dev);
792 break;
794 case V4L2_CID_BLUE_BALANCE:
795 dev->vsettings.rgb_gain[3] = ctrl->value;
796 dev_microdia_camera_set_rgb_gain(dev);
797 break;
799 case V4L2_CID_AUTOEXPOSURE:
800 dev->vsettings.auto_exposure = ctrl->value;
801 dev_microdia_camera_set_auto_exposure(dev);
802 break;
804 case V4L2_CID_AUTO_WHITE_BALANCE:
805 dev->vsettings.auto_whitebalance = ctrl->value;
806 dev_microdia_camera_set_auto_whitebalance(dev);
807 break;
809 default:
810 return -EINVAL;
813 return 0;
816 int microdia_vidioc_enum_fmt_cap(struct file *file, void *priv,
817 struct v4l2_fmtdesc *fmt)
819 struct usb_microdia *dev;
820 struct v4l2_pix_format *format;
822 dev = video_get_drvdata(priv);
824 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmt->index);
826 format = v4l2_enum_supported_formats(dev, fmt->index);
827 if (format == NULL)
828 return -EINVAL;
830 fmt->flags = 0;
831 fmt->pixelformat = format->pixelformat;
832 fmt->description[0] = fmt->pixelformat & 0xFF;
833 fmt->description[1] = (fmt->pixelformat >> 8) & 0xFF;
834 fmt->description[2] = (fmt->pixelformat >> 16) & 0xFF;
835 fmt->description[3] = fmt->pixelformat >> 24;
836 fmt->description[4] = 0;
838 return 0;
841 int microdia_vidioc_try_fmt_cap(struct file *file, void *priv,
842 struct v4l2_format *fmt)
844 struct usb_microdia *dev;
846 dev = video_get_drvdata(priv);
847 UDIA_DEBUG("TRY FMT %d\n", fmt->type);
849 /* when this code is used prevents mplayer from setting outfmt
850 if(fmt->fmt.pix.field != V4L2_FIELD_NONE)
851 return -EINVAL;
854 if (v4l2_format_supported(dev, fmt->fmt.pix.pixelformat) < 0)
855 return -EINVAL;
857 sn9c20x_get_closest_resolution(&fmt->fmt.pix.width,
858 &fmt->fmt.pix.height);
860 switch (fmt->fmt.pix.pixelformat) {
861 case V4L2_PIX_FMT_YUV420:
862 fmt->fmt.pix.bytesperline = (fmt->fmt.pix.width * 3)/2;
863 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
864 fmt->fmt.pix.bytesperline;
865 break;
866 case V4L2_PIX_FMT_RGB24:
867 case V4L2_PIX_FMT_BGR24:
868 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
869 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
870 fmt->fmt.pix.bytesperline;
871 break;
872 case V4L2_PIX_FMT_YUYV:
873 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 2;
874 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
875 fmt->fmt.pix.bytesperline;
876 break;
877 default:
878 return -EINVAL;
881 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
882 fmt->fmt.pix.priv = 0;
884 return 0;
887 int microdia_vidioc_g_fmt_cap(struct file *file, void *priv,
888 struct v4l2_format *fmt)
890 struct usb_microdia *dev;
892 dev = video_get_drvdata(priv);
894 UDIA_DEBUG("GET FMT %d\n", fmt->type);
896 memcpy(&(fmt->fmt.pix), &(dev->vsettings.format), sizeof(fmt->fmt.pix));
899 return 0;
902 int microdia_vidioc_s_fmt_cap(struct file *file, void *priv,
903 struct v4l2_format *fmt)
905 struct usb_microdia *dev;
906 int ret;
908 dev = video_get_drvdata(priv);
910 UDIA_DEBUG("SET FMT %d : %d\n", fmt->type, fmt->fmt.pix.pixelformat);
912 if (v4l_get_privileges(file) < 0)
913 return -EBUSY;
915 if (dev->queue.streaming)
916 return -EBUSY;
918 ret = microdia_vidioc_try_fmt_cap(file, priv, fmt);
919 if (ret)
920 return -EINVAL;
922 sn9c20x_set_resolution(dev, fmt->fmt.pix.width, fmt->fmt.pix.height);
924 memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix));
926 return 0;
929 int microdia_vidioc_reqbufs(struct file *file, void *priv,
930 struct v4l2_requestbuffers *request)
932 int ret = 0;
933 struct usb_microdia *dev;
935 dev = video_get_drvdata(priv);
937 if (v4l_get_privileges(file) < 0) {
938 ret = -EBUSY;
939 goto done;
942 if (request->memory != V4L2_MEMORY_MMAP ||
943 request->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
944 ret = -EINVAL;
945 goto done;
948 if (dev->queue.streaming) {
949 ret = -EBUSY;
950 goto done;
953 ret = microdia_alloc_buffers(&dev->queue, request->count,
954 MICRODIA_FRAME_SIZE);
955 if (ret < 0)
956 goto done;
958 dev->queue.drop_incomplete = 1;
960 request->count = ret;
961 ret = 0;
962 UDIA_INFO("Buffers Allocated %d\n", request->count);
963 done:
964 return ret;
967 int microdia_vidioc_querybuf(struct file *file, void *priv,
968 struct v4l2_buffer *buffer)
970 struct usb_microdia *dev;
972 dev = video_get_drvdata(priv);
974 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buffer->index, dev->queue.count);
976 if (buffer->memory != V4L2_MEMORY_MMAP ||
977 buffer->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
978 return -EINVAL;
980 if (!v4l_has_privileges(file))
981 return -EBUSY;
983 return microdia_query_buffer(&dev->queue, buffer);
986 int microdia_vidioc_qbuf(struct file *file, void *priv,
987 struct v4l2_buffer *buffer)
989 struct usb_microdia *dev;
991 dev = video_get_drvdata(priv);
993 UDIA_DEBUG("VIDIOC_QBUF\n");
995 if (!v4l_has_privileges(file))
996 return -EBUSY;
998 return microdia_queue_buffer(&dev->queue, buffer);
1001 int microdia_vidioc_dqbuf(struct file *file, void *priv,
1002 struct v4l2_buffer *buffer)
1004 struct usb_microdia *dev;
1005 int ret = 0;
1007 dev = video_get_drvdata(priv);
1009 UDIA_DEBUG("VIDIOC_DQBUF\n");
1011 if (!v4l_has_privileges(file))
1012 return -EBUSY;
1014 ret = microdia_dequeue_buffer(&dev->queue, buffer,
1015 file->f_flags & O_NONBLOCK);
1016 if (ret < 0)
1017 return ret;
1019 microdia_decompress(dev, buffer);
1021 return ret;
1024 int microdia_vidioc_streamon(struct file *file, void *priv,
1025 enum v4l2_buf_type type)
1027 struct usb_microdia *dev;
1029 dev = video_get_drvdata(priv);
1031 UDIA_DEBUG("VIDIOC_STREAMON\n");
1033 if (!v4l_has_privileges(file))
1034 return -EBUSY;
1036 if (dev->mode != MICRODIA_MODE_IDLE)
1037 return -EBUSY;
1039 return v4l2_enable_video(dev, MICRODIA_MODE_STREAM);
1042 int microdia_vidioc_streamoff(struct file *file, void *priv,
1043 enum v4l2_buf_type type)
1045 struct usb_microdia *dev;
1047 dev = video_get_drvdata(priv);
1049 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1051 if (!v4l_has_privileges(file))
1052 return -EBUSY;
1054 return v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
1057 int microdia_vidioc_g_param(struct file *file, void *priv,
1058 struct v4l2_streamparm *param)
1060 struct usb_microdia *dev;
1063 dev = video_get_drvdata(priv);
1065 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1066 return -EINVAL;
1068 param->parm.capture.capability = 0;
1069 param->parm.capture.capturemode = 0;
1070 param->parm.capture.timeperframe.numerator = 1;
1071 param->parm.capture.timeperframe.denominator = 30;
1072 param->parm.capture.readbuffers = 2;
1073 param->parm.capture.extendedmode = 0;
1075 return 0;
1078 int microdia_vidioc_s_param(struct file *file, void *priv,
1079 struct v4l2_streamparm *param)
1081 struct usb_microdia *dev;
1083 dev = video_get_drvdata(priv);
1085 if (v4l_get_privileges(file))
1086 return -EBUSY;
1088 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1089 return -EINVAL;
1091 return 0;
1095 * @param inode Inode pointer
1096 * @param fp File pointer
1097 * @param cmd Command
1098 * @param arg Arguements of the command
1100 * @returns 0 if all is OK
1102 * @brief Manage IOCTL
1104 * This function permits to manage all the IOCTL from the application.
1106 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1107 unsigned int cmd, unsigned long arg)
1109 int err;
1110 struct usb_microdia *dev;
1111 struct video_device *vdev;
1113 vdev = video_devdata(fp);
1114 dev = video_get_drvdata(video_devdata(fp));
1116 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1118 if (dev == NULL || vdev == NULL)
1119 return -EFAULT;
1121 err = video_ioctl2(inode, fp, cmd, arg);
1123 return err;
1128 * @param dev Device structure
1130 * @returns 0 if all is OK
1132 * @brief Register the video device
1134 * This function permits to register the USB device to the video device.
1136 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1138 int err;
1140 strcpy(dev->vdev->name, DRIVER_DESC);
1142 dev->vdev->dev = &dev->interface->dev;
1143 dev->vdev->owner = THIS_MODULE;
1144 dev->vdev->type = VID_TYPE_CAPTURE;
1145 dev->vdev->current_norm = 0;
1146 dev->vdev->tvnorms = 0;
1147 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1148 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1149 #endif
1150 dev->vdev->fops = &v4l_microdia_fops;
1151 dev->vdev->release = video_device_release;
1152 dev->vdev->minor = -1;
1154 if (log_level & MICRODIA_DEBUG)
1155 dev->vdev->debug = V4L2_DEBUG_IOCTL_ARG;
1157 dev->vdev->vidioc_querycap = microdia_vidioc_querycap;
1158 dev->vdev->vidioc_enum_fmt_cap = microdia_vidioc_enum_fmt_cap;
1159 dev->vdev->vidioc_try_fmt_cap = microdia_vidioc_try_fmt_cap;
1160 dev->vdev->vidioc_s_fmt_cap = microdia_vidioc_s_fmt_cap;
1161 dev->vdev->vidioc_g_fmt_cap = microdia_vidioc_g_fmt_cap;
1162 dev->vdev->vidioc_enum_input = microdia_vidioc_enum_input;
1163 dev->vdev->vidioc_g_input = microdia_vidioc_g_input;
1164 dev->vdev->vidioc_s_input = microdia_vidioc_s_input;
1165 dev->vdev->vidioc_streamon = microdia_vidioc_streamon;
1166 dev->vdev->vidioc_streamoff = microdia_vidioc_streamoff;
1167 dev->vdev->vidioc_queryctrl = microdia_vidioc_queryctrl;
1168 dev->vdev->vidioc_g_ctrl = microdia_vidioc_g_ctrl;
1169 dev->vdev->vidioc_s_ctrl = microdia_vidioc_s_ctrl;
1170 dev->vdev->vidioc_g_parm = microdia_vidioc_g_param;
1171 dev->vdev->vidioc_s_parm = microdia_vidioc_s_param;
1172 dev->vdev->vidioc_reqbufs = microdia_vidioc_reqbufs;
1173 dev->vdev->vidioc_qbuf = microdia_vidioc_qbuf;
1174 dev->vdev->vidioc_dqbuf = microdia_vidioc_dqbuf;
1175 dev->vdev->vidioc_querybuf = microdia_vidioc_querybuf;
1177 video_set_drvdata(dev->vdev, dev);
1179 microdia_queue_init(&dev->queue);
1181 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1183 if (err)
1184 UDIA_ERROR("Video register fail !\n");
1185 else
1186 UDIA_INFO("Microdia USB2.0 Camera is now controlling "
1187 "video device /dev/video%d\n",
1188 dev->vdev->minor);
1190 return err;
1195 * @param dev Device structure
1197 * @returns 0 if all is OK
1199 * @brief Unregister the video device
1201 * This function permits to unregister the video device.
1203 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1205 UDIA_INFO("Microdia USB2.0 Camera release resources video "
1206 "device /dev/video%d\n", dev->vdev->minor);
1208 video_set_drvdata(dev->vdev, NULL);
1209 video_unregister_device(dev->vdev);
1211 return 0;
1216 * @var v4l_microdia_fops
1218 * This variable contains some callback
1220 static struct file_operations v4l_microdia_fops = {
1221 .owner = THIS_MODULE,
1222 .open = v4l_microdia_open,
1223 .release = v4l_microdia_release,
1224 .read = v4l_microdia_read,
1225 .poll = v4l_microdia_poll,
1226 .mmap = v4l_microdia_mmap,
1227 .ioctl = v4l_microdia_ioctl,
1228 #ifdef CONFIG_COMPAT
1229 .compat_ioctl = v4l_compat_ioctl32,
1230 #endif
1231 .llseek = no_llseek