Fix 62B3 to use correct format decoding routines
[microdia.git] / microdia-v4l.c
blobf794eec3caede8ba5c01745b915a0f91f8dd2144
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_AUTOGAIN,
244 .type = V4L2_CTRL_TYPE_BOOLEAN,
245 .name = "Automatic exposure control",
246 .minimum = 0,
247 .maximum = 1,
248 .step = 1,
249 .default_value = 0,
252 .id = V4L2_CID_AUTO_WHITE_BALANCE,
253 .type = V4L2_CTRL_TYPE_BOOLEAN,
254 .name = "Automatic whitbalance control",
255 .minimum = 0,
256 .maximum = 1,
257 .step = 1,
258 .default_value = 0,
263 * The following three functions are used to get, test and drop v4l privleges.
265 int v4l_get_privileges(struct file *file)
267 struct usb_microdia *dev;
268 int ret = 0;
270 dev = video_get_drvdata(video_devdata(file));
272 if (dev->owner == file)
273 return 0;
275 mutex_lock(&open_lock);
276 if (dev->owner != NULL) {
277 ret = -EBUSY;
278 goto done;
280 dev->owner = file;
281 done:
282 mutex_unlock(&open_lock);
283 return ret;
286 int v4l_has_privileges(struct file *file)
288 struct usb_microdia *dev;
289 int ret = 0;
291 dev = video_get_drvdata(video_devdata(file));
293 if (dev->owner == file)
294 ret = 1;
296 return ret;
299 void v4l_drop_privileges(struct file *file)
301 struct usb_microdia *dev;
303 dev = video_get_drvdata(video_devdata(file));
305 if (dev->owner == file)
306 dev->owner = NULL;
309 int v4l2_enable_video(struct usb_microdia *dev, int mode)
311 int ret;
313 if (mode == MICRODIA_MODE_IDLE) {
314 dev_microdia_stop_stream(dev);
315 usb_microdia_isoc_cleanup(dev);
316 dev_microdia_camera_off(dev);
317 microdia_queue_enable(&dev->queue, 0);
318 dev->mode = mode;
319 return 0;
322 if (dev->mode != MICRODIA_MODE_IDLE)
323 return -EBUSY;
325 if (microdia_queue_enable(&dev->queue, 1) < 0)
326 return -EBUSY;
328 dev_microdia_camera_on(dev);
329 ret = usb_microdia_isoc_init(dev);
331 if (ret)
332 return ret;
334 dev_microdia_start_stream(dev);
335 dev_microdia_camera_settings(dev);
336 dev->mode = mode;
338 return 0;
341 int v4l_microdia_find_resolution(struct usb_microdia *dev,
342 int *width, int *height)
344 int i, max_res;
345 int find = 0;
347 if ((*width < microdia_image_sizes[0].x)
348 || (*height < microdia_image_sizes[0].y)) {
349 *width = microdia_image_sizes[0].x;
350 *height = microdia_image_sizes[0].y;
353 switch (dev->webcam_type) {
354 case MICRODIA_SXGA:
355 max_res = MICRODIA_NBR_SIZES-1;
356 if ((*width > microdia_image_sizes[max_res].x)
357 || (*height > microdia_image_sizes[max_res].y)) {
358 *width = microdia_image_sizes[max_res].x;
359 *height = microdia_image_sizes[max_res].y;
362 for (i = 0, find = 0; i < MICRODIA_NBR_SIZES; i++) {
363 if (microdia_image_sizes[i].x <= *width &&
364 microdia_image_sizes[i].y <= *height)
365 find = i;
367 break;
369 case MICRODIA_VGA:
370 max_res = MICRODIA_NBR_SIZES-4;
371 if ((*width > microdia_image_sizes[max_res].x)
372 || (*height > microdia_image_sizes[max_res].y)) {
373 *width = microdia_image_sizes[max_res].x;
374 *height = microdia_image_sizes[max_res].y;
377 for (i = 0, find = 0; i < MICRODIA_NBR_SIZES-3; i++) {
378 if (microdia_image_sizes[i].x <= *width &&
379 microdia_image_sizes[i].y <= *height)
380 find = i;
382 break;
385 *width = microdia_image_sizes[find].x;
386 *height = microdia_image_sizes[find].y;
388 return find;
393 * @param dev
394 * @param resolution Driver resolution
396 * @returns 0 if all is OK
398 * @brief Select a video mode
400 * This function permits to select a video mode.
402 int v4l_microdia_select_video_mode(struct usb_microdia *dev, int resolution)
404 dev->resolution = resolution;
406 UDIA_DEBUG("Set mode %d [%dx%d]\n", dev->resolution,
407 microdia_image_sizes[dev->resolution].x,
408 microdia_image_sizes[dev->resolution].y);
410 dev->view.x = microdia_image_sizes[dev->resolution].x;
411 dev->view.y = microdia_image_sizes[dev->resolution].y;
415 * Calculate the frame size
417 switch (dev->resolution) {
418 case MICRODIA_80x60:
419 case MICRODIA_160x120:
420 case MICRODIA_320x240:
421 case MICRODIA_640x480:
422 dev->image.x = microdia_image_sizes[MICRODIA_640x480].x;
423 dev->image.y = microdia_image_sizes[MICRODIA_640x480].y;
424 break;
426 case MICRODIA_800x600:
427 case MICRODIA_1024x768:
428 case MICRODIA_1280x1024:
429 dev->image.x = microdia_image_sizes[MICRODIA_1280x1024].x;
430 dev->image.y = microdia_image_sizes[MICRODIA_1280x1024].y;
431 break;
434 * queue.frame_size is only ever used in isoc_handler
435 * to test if the ISOC data is the correct size
436 * This modificate pre calculates this rather
437 * than doing the calculating in the isoc_handler
439 dev->queue.frame_size = dev->image.x * dev->image.y +
440 (dev->image.x * dev->image.y) / dev->frame_size_divisor;
442 return 0;
447 * @param inode Pointer on an inode
448 * @param fp File pointer
450 * @returns 0 if all is OK
452 * @brief Open the video device
454 * This function permits to open a video device (/dev/videoX)
456 static int v4l_microdia_open(struct inode *inode, struct file *fp)
458 int ret = 0;
460 struct usb_microdia *dev;
461 struct video_device *vdev;
463 mutex_lock(&open_lock);
465 vdev = video_devdata(fp);
466 dev = video_get_drvdata(video_devdata(fp));
468 fp->private_data = vdev;
470 kref_get(&dev->vopen);
472 mutex_unlock(&open_lock);
473 return ret;
478 * @param inode Pointer on inode
479 * @param fp File pointer
481 * @returns 0 if all is OK
483 * @brief Release an opened file.
485 * This function permits to release an opened file with the 'open' method.
487 static int v4l_microdia_release(struct inode *inode, struct file *fp)
489 struct usb_microdia *dev;
490 struct video_device *vdev;
492 mutex_lock(&open_lock);
494 vdev = video_devdata(fp);
495 dev = video_get_drvdata(video_devdata(fp));
497 if (v4l_has_privileges(fp)) {
498 v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
500 mutex_lock(&dev->queue.mutex);
501 microdia_free_buffers(&dev->queue);
502 mutex_unlock(&dev->queue.mutex);
505 v4l_drop_privileges(fp);
507 kref_put(&dev->vopen, usb_microdia_delete);
509 mutex_unlock(&open_lock);
510 return 0;
515 * @param fp File pointer
517 * @retval buf Buffer in user space
518 * @retval count
519 * @retval f_pos
521 * @returns Count value
523 * @brief Read the video device
525 * This function is called by the application is reading the video device.
527 static ssize_t v4l_microdia_read(struct file *fp, char __user *buf,
528 size_t count, loff_t *f_pos)
530 int i, ret;
531 int nbuffers;
532 struct v4l2_buffer buffer;
533 struct usb_microdia *dev;
535 dev = video_get_drvdata(video_devdata(fp));
537 ret = v4l_get_privileges(fp);
538 if (ret < 0)
539 return ret;
541 if (dev->mode != MICRODIA_MODE_IDLE &&
542 dev->mode != MICRODIA_MODE_READ)
543 return -EBUSY;
545 buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
546 buffer.memory = V4L2_MEMORY_MMAP;
547 if (dev->mode == MICRODIA_MODE_IDLE) {
548 nbuffers = microdia_alloc_buffers(&dev->queue, 2,
549 MICRODIA_FRAME_SIZE);
550 if (nbuffers < 0)
551 return nbuffers;
553 for (i = 0; i < nbuffers; i++) {
554 buffer = dev->queue.buffer[i].buf;
555 microdia_queue_buffer(&dev->queue, &buffer);
558 ret = v4l2_enable_video(dev, MICRODIA_MODE_READ);
559 if (ret < 0)
560 return ret;
563 if (dev->queue.read_buffer == NULL) {
564 ret = microdia_dequeue_buffer(&dev->queue, &buffer,
565 fp->f_flags & O_NONBLOCK);
566 if (ret < 0)
567 return ret;
569 microdia_decompress(dev, &buffer);
570 dev->queue.read_buffer = &dev->queue.buffer[buffer.index];
571 } else {
572 buffer = dev->queue.read_buffer->buf;
575 count = min((size_t)(buffer.bytesused - *f_pos), count);
576 if (copy_to_user(buf, dev->queue.mem + buffer.m.offset + *f_pos, count))
577 return -EFAULT;
579 *f_pos += count;
580 if (*f_pos >= buffer.bytesused) {
581 dev->queue.read_buffer = NULL;
582 microdia_queue_buffer(&dev->queue, &buffer);
583 *f_pos = 0;
585 return count;
590 * @param fp File pointer
591 * @param wait
593 * @returns 0 if all is OK
595 * @brief Polling function
597 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
599 struct usb_microdia *dev;
600 struct video_device *vdev;
602 vdev = video_devdata(fp);
603 dev = video_get_drvdata(video_devdata(fp));
605 UDIA_STREAM("Poll\n");
607 if (vdev == NULL || dev == NULL)
608 return -EFAULT;
610 return microdia_queue_poll(&dev->queue, fp, wait);
613 static void microdia_vm_open(struct vm_area_struct *vma)
615 struct microdia_buffer *buffer = vma->vm_private_data;
616 buffer->vma_use_count++;
620 static void microdia_vm_close(struct vm_area_struct *vma)
622 struct microdia_buffer *buffer = vma->vm_private_data;
623 buffer->vma_use_count--;
626 struct vm_operations_struct microdia_vm_ops = {
627 .open = microdia_vm_open,
628 .close = microdia_vm_close
632 * @param fp File pointer
633 * @param vma VMA structure
635 * @returns 0 if all is OK
637 * @brief Memory map
639 * This function permits to map a memory space.
641 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
643 struct page *page;
644 unsigned long addr, start, size;
645 unsigned int i;
646 int ret = 0;
648 struct usb_microdia *dev;
649 struct video_device *vdev;
650 struct microdia_buffer *buffer = NULL;
652 vdev = video_devdata(fp);
653 dev = video_get_drvdata(video_devdata(fp));
655 UDIA_STREAM("mmap\n");
657 start = vma->vm_start;
658 size = vma->vm_end - vma->vm_start;
660 mutex_lock(&dev->queue.mutex);
662 for (i = 0; i < dev->queue.count; ++i) {
663 buffer = &dev->queue.buffer[i];
664 if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
665 break;
668 if (i == dev->queue.count || size != dev->queue.buf_size) {
669 ret = -EINVAL;
670 goto done;
673 vma->vm_flags |= VM_IO;
675 addr = (unsigned long)dev->queue.mem + buffer->buf.m.offset;
676 while (size > 0) {
677 page = vmalloc_to_page((void *)addr);
678 ret = vm_insert_page(vma, start, page);
679 if (ret < 0)
680 goto done;
682 start += PAGE_SIZE;
683 addr += PAGE_SIZE;
684 size -= PAGE_SIZE;
687 vma->vm_ops = &microdia_vm_ops;
688 vma->vm_private_data = buffer;
689 microdia_vm_open(vma);
690 done:
691 mutex_unlock(&dev->queue.mutex);
692 return ret;
695 int microdia_vidioc_querycap(struct file *file, void *priv,
696 struct v4l2_capability *cap)
698 struct usb_microdia *dev;
700 dev = video_get_drvdata(priv);
702 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
704 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
705 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
706 | V4L2_CAP_READWRITE;
707 cap->version = (__u32) DRIVER_VERSION_NUM,
708 strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
710 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
711 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
712 return 0;
715 int microdia_vidioc_enum_input(struct file *file, void *priv,
716 struct v4l2_input *input)
718 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", input->index);
720 if (input->index)
721 return -EINVAL;
723 strlcpy(input->name, "Webcam", sizeof(input->name));
724 input->type = V4L2_INPUT_TYPE_CAMERA;
725 input->std = 0;
727 return 0;
730 int microdia_vidioc_g_input(struct file *file, void *priv, unsigned int *index)
732 UDIA_DEBUG("GET INPUT %d\n", *index);
734 if (index)
735 return -EINVAL;
737 return 0;
740 int microdia_vidioc_s_input(struct file *file, void *priv, unsigned int index)
742 UDIA_DEBUG("SET INPUT %d\n", index);
744 if (v4l_get_privileges(file) < 0)
745 return -EBUSY;
747 if (index != 0)
748 return -EINVAL;
750 return 0;
753 int microdia_vidioc_queryctrl(struct file *file, void *priv,
754 struct v4l2_queryctrl *ctrl)
756 int i;
757 int nbr;
759 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", ctrl->id);
761 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
763 for (i = 0; i < nbr; i++) {
764 if (microdia_controls[i].id == ctrl->id) {
765 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
766 memcpy(ctrl, &microdia_controls[i],
767 sizeof(struct v4l2_queryctrl));
768 break;
772 if (i >= nbr)
773 return -EINVAL;
775 return 0;
778 int microdia_vidioc_g_ctrl(struct file *file, void *priv,
779 struct v4l2_control *ctrl)
781 struct usb_microdia *dev;
783 dev = video_get_drvdata(priv);
785 UDIA_DEBUG("GET CTRL id=%d\n", ctrl->id);
787 switch (ctrl->id) {
788 case V4L2_CID_BRIGHTNESS:
789 ctrl->value = dev->vsettings.brightness;
790 break;
792 case V4L2_CID_EXPOSURE:
793 ctrl->value = dev->vsettings.exposure;
794 break;
796 case V4L2_CID_WHITENESS:
797 ctrl->value = dev->vsettings.whiteness;
798 break;
800 case V4L2_CID_SATURATION:
801 ctrl->value = dev->vsettings.colour;
802 break;
804 case V4L2_CID_CONTRAST:
805 ctrl->value = dev->vsettings.contrast;
806 break;
808 case V4L2_CID_HFLIP:
809 ctrl->value = dev->vsettings.hflip;
810 break;
812 case V4L2_CID_VFLIP:
813 ctrl->value = dev->vsettings.vflip;
814 break;
816 case V4L2_CID_SHARPNESS:
817 ctrl->value = dev->vsettings.sharpness;
818 break;
820 case V4L2_CID_AUTOGAIN:
821 ctrl->value = dev->vsettings.auto_exposure;
822 break;
824 case V4L2_CID_AUTO_WHITE_BALANCE:
825 ctrl->value = dev->vsettings.auto_whitebalance;
826 break;
828 default:
829 return -EINVAL;
831 return 0;
834 int microdia_vidioc_s_ctrl(struct file *file, void *priv,
835 struct v4l2_control *ctrl)
837 struct usb_microdia *dev;
839 dev = video_get_drvdata(priv);
841 UDIA_DEBUG("SET CTRL id=%d value=%d\n", ctrl->id, ctrl->value);
843 switch (ctrl->id) {
844 case V4L2_CID_BRIGHTNESS:
845 dev->vsettings.brightness = (0xff00 & ctrl->value);
846 dev_microdia_camera_set_brightness(dev);
847 break;
849 case V4L2_CID_EXPOSURE:
850 dev->vsettings.exposure = (0xff00 & ctrl->value);
851 dev_microdia_camera_set_exposure(dev);
852 break;
854 case V4L2_CID_WHITENESS:
855 dev->vsettings.whiteness = (0xff00 & ctrl->value);
856 dev_microdia_camera_set_gamma(dev);
857 break;
859 case V4L2_CID_SATURATION:
860 dev->vsettings.colour = (0xff00 & ctrl->value);
861 break;
863 case V4L2_CID_CONTRAST:
864 dev->vsettings.contrast = (0xff00 & ctrl->value);
865 dev_microdia_camera_set_contrast(dev);
866 break;
868 case V4L2_CID_HFLIP:
869 dev->vsettings.hflip = ctrl->value;
870 dev_microdia_camera_set_hvflip(dev);
871 break;
873 case V4L2_CID_VFLIP:
874 dev->vsettings.vflip = ctrl->value;
875 dev_microdia_camera_set_hvflip(dev);
876 break;
878 case V4L2_CID_SHARPNESS:
879 dev->vsettings.sharpness = ctrl->value;
880 dev_microdia_camera_set_sharpness(dev);
881 break;
883 case V4L2_CID_AUTOGAIN:
884 dev->vsettings.auto_exposure = ctrl->value;
885 dev_microdia_camera_set_auto_exposure(dev);
886 break;
888 case V4L2_CID_AUTO_WHITE_BALANCE:
889 dev->vsettings.auto_whitebalance = ctrl->value;
890 dev_microdia_camera_set_auto_whitebalance(dev);
891 break;
893 default:
894 return -EINVAL;
897 return 0;
900 int microdia_vidioc_enum_fmt_cap(struct file *file, void *priv,
901 struct v4l2_fmtdesc *fmt)
903 struct usb_microdia *dev;
904 struct v4l2_pix_format *format;
906 dev = video_get_drvdata(priv);
908 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmt->index);
910 format = v4l2_enum_supported_formats(dev, fmt->index);
911 if (format == NULL)
912 return -EINVAL;
914 fmt->flags = 0;
915 fmt->pixelformat = format->pixelformat;
916 fmt->description[0] = fmt->pixelformat & 0xFF;
917 fmt->description[1] = (fmt->pixelformat >> 8) & 0xFF;
918 fmt->description[2] = (fmt->pixelformat >> 16) & 0xFF;
919 fmt->description[3] = fmt->pixelformat >> 24;
920 fmt->description[4] = 0;
922 return 0;
925 int microdia_vidioc_try_fmt_cap(struct file *file, void *priv,
926 struct v4l2_format *fmt)
928 struct usb_microdia *dev;
930 dev = video_get_drvdata(priv);
931 UDIA_DEBUG("TRY FMT %d\n", fmt->type);
933 /* when this code is used prevents mplayer from setting outfmt
934 if(fmt->fmt.pix.field != V4L2_FIELD_NONE)
935 return -EINVAL;
938 if (v4l2_format_supported(dev, fmt->fmt.pix.pixelformat) < 0)
939 return -EINVAL;
941 v4l_microdia_find_resolution(dev, &fmt->fmt.pix.width,
942 &fmt->fmt.pix.height);
944 switch (fmt->fmt.pix.pixelformat) {
945 case V4L2_PIX_FMT_YUV420:
946 fmt->fmt.pix.bytesperline = (fmt->fmt.pix.width * 3)/2;
947 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
948 fmt->fmt.pix.bytesperline;
949 break;
950 case V4L2_PIX_FMT_RGB24:
951 case V4L2_PIX_FMT_BGR24:
952 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 3;
953 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
954 fmt->fmt.pix.bytesperline;
955 break;
956 case V4L2_PIX_FMT_YUYV:
957 fmt->fmt.pix.bytesperline = fmt->fmt.pix.width * 2;
958 fmt->fmt.pix.sizeimage = fmt->fmt.pix.height *
959 fmt->fmt.pix.bytesperline;
960 break;
961 default:
962 return -EINVAL;
965 fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
966 fmt->fmt.pix.priv = 0;
968 return 0;
971 int microdia_vidioc_g_fmt_cap(struct file *file, void *priv,
972 struct v4l2_format *fmt)
974 struct usb_microdia *dev;
976 dev = video_get_drvdata(priv);
978 UDIA_DEBUG("GET FMT %d\n", fmt->type);
980 memcpy(&(fmt->fmt.pix), &(dev->vsettings.format), sizeof(fmt->fmt.pix));
983 return 0;
986 int microdia_vidioc_s_fmt_cap(struct file *file, void *priv,
987 struct v4l2_format *fmt)
989 struct usb_microdia *dev;
990 int ret;
992 dev = video_get_drvdata(priv);
994 UDIA_DEBUG("SET FMT %d : %d\n", fmt->type, fmt->fmt.pix.pixelformat);
996 if (v4l_get_privileges(file) < 0)
997 return -EBUSY;
999 if (dev->queue.streaming)
1000 return -EBUSY;
1002 ret = microdia_vidioc_try_fmt_cap(file, priv, fmt);
1003 if (ret)
1004 return -EINVAL;
1006 UDIA_DEBUG("Set width=%d, height=%d\n",
1007 fmt->fmt.pix.width,
1008 fmt->fmt.pix.height);
1010 ret = v4l_microdia_find_resolution(dev, &fmt->fmt.pix.width,
1011 &fmt->fmt.pix.height);
1013 v4l_microdia_select_video_mode(dev, ret);
1015 memcpy(&(dev->vsettings.format), &(fmt->fmt.pix), sizeof(fmt->fmt.pix));
1017 return 0;
1020 int microdia_vidioc_reqbufs(struct file *file, void *priv,
1021 struct v4l2_requestbuffers *request)
1023 int ret = 0;
1024 struct usb_microdia *dev;
1026 dev = video_get_drvdata(priv);
1028 if (v4l_get_privileges(file) < 0) {
1029 ret = -EBUSY;
1030 goto done;
1033 if (request->memory != V4L2_MEMORY_MMAP ||
1034 request->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1035 ret = -EINVAL;
1036 goto done;
1039 if (dev->queue.streaming) {
1040 ret = -EBUSY;
1041 goto done;
1044 ret = microdia_alloc_buffers(&dev->queue, request->count,
1045 MICRODIA_FRAME_SIZE);
1046 if (ret < 0)
1047 goto done;
1049 dev->queue.drop_incomplete = 1;
1051 request->count = ret;
1052 ret = 0;
1053 UDIA_INFO("Buffers Allocated %d\n", request->count);
1054 done:
1055 return ret;
1058 int microdia_vidioc_querybuf(struct file *file, void *priv,
1059 struct v4l2_buffer *buffer)
1061 struct usb_microdia *dev;
1063 dev = video_get_drvdata(priv);
1065 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buffer->index, dev->queue.count);
1067 if (buffer->memory != V4L2_MEMORY_MMAP ||
1068 buffer->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1069 return -EINVAL;
1071 if (!v4l_has_privileges(file))
1072 return -EBUSY;
1074 return microdia_query_buffer(&dev->queue, buffer);
1077 int microdia_vidioc_qbuf(struct file *file, void *priv,
1078 struct v4l2_buffer *buffer)
1080 struct usb_microdia *dev;
1082 dev = video_get_drvdata(priv);
1084 UDIA_DEBUG("VIDIOC_QBUF\n");
1086 if (!v4l_has_privileges(file)) {
1087 return -EBUSY;
1090 return microdia_queue_buffer(&dev->queue, buffer);
1093 int microdia_vidioc_dqbuf(struct file *file, void *priv,
1094 struct v4l2_buffer *buffer)
1096 struct usb_microdia *dev;
1097 int ret = 0;
1099 dev = video_get_drvdata(priv);
1101 UDIA_DEBUG("VIDIOC_DQBUF\n");
1103 if (!v4l_has_privileges(file))
1104 return -EBUSY;
1106 ret = microdia_dequeue_buffer(&dev->queue, buffer,
1107 file->f_flags & O_NONBLOCK);
1108 if (ret < 0)
1109 return ret;
1111 microdia_decompress(dev, buffer);
1113 return ret;
1116 int microdia_vidioc_streamon(struct file *file, void *priv,
1117 enum v4l2_buf_type type)
1119 struct usb_microdia *dev;
1121 dev = video_get_drvdata(priv);
1123 UDIA_DEBUG("VIDIOC_STREAMON\n");
1125 if (!v4l_has_privileges(file))
1126 return -EBUSY;
1128 if (dev->mode != MICRODIA_MODE_IDLE)
1129 return -EBUSY;
1131 return v4l2_enable_video(dev, MICRODIA_MODE_STREAM);
1134 int microdia_vidioc_streamoff(struct file *file, void *priv,
1135 enum v4l2_buf_type type)
1137 struct usb_microdia *dev;
1139 dev = video_get_drvdata(priv);
1141 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1143 if (!v4l_has_privileges(file))
1144 return -EBUSY;
1146 return v4l2_enable_video(dev, MICRODIA_MODE_IDLE);
1149 int microdia_vidioc_g_param(struct file *file, void *priv,
1150 struct v4l2_streamparm *param)
1152 struct usb_microdia *dev;
1155 dev = video_get_drvdata(priv);
1157 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1158 return -EINVAL;
1160 param->parm.capture.capability = 0;
1161 param->parm.capture.capturemode = 0;
1162 param->parm.capture.timeperframe.numerator = 1;
1163 param->parm.capture.timeperframe.denominator = 30;
1164 param->parm.capture.readbuffers = 2;
1165 param->parm.capture.extendedmode = 0;
1167 return 0;
1170 int microdia_vidioc_s_param(struct file *file, void *priv,
1171 struct v4l2_streamparm *param)
1173 struct usb_microdia *dev;
1175 dev = video_get_drvdata(priv);
1177 if (v4l_get_privileges(file))
1178 return -EBUSY;
1180 if (param->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1181 return -EINVAL;
1183 return 0;
1187 * @param inode Inode pointer
1188 * @param fp File pointer
1189 * @param cmd Command
1190 * @param arg Arguements of the command
1192 * @returns 0 if all is OK
1194 * @brief Manage IOCTL
1196 * This function permits to manage all the IOCTL from the application.
1198 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1199 unsigned int cmd, unsigned long arg)
1201 int err;
1202 struct usb_microdia *dev;
1203 struct video_device *vdev;
1205 vdev = video_devdata(fp);
1206 dev = video_get_drvdata(video_devdata(fp));
1208 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1210 if (dev == NULL || vdev == NULL)
1211 return -EFAULT;
1213 err = video_ioctl2(inode, fp, cmd, arg);
1215 return err;
1220 * @param dev Device structure
1222 * @returns 0 if all is OK
1224 * @brief Register the video device
1226 * This function permits to register the USB device to the video device.
1228 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1230 int err;
1232 strcpy(dev->vdev->name, DRIVER_DESC);
1234 dev->vdev->dev = &dev->interface->dev;
1235 dev->vdev->owner = THIS_MODULE;
1236 dev->vdev->type = VID_TYPE_CAPTURE;
1237 dev->vdev->current_norm = 0;
1238 dev->vdev->tvnorms = 0;
1239 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1240 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1241 #endif
1242 dev->vdev->fops = &v4l_microdia_fops;
1243 dev->vdev->release = video_device_release;
1244 dev->vdev->minor = -1;
1245 #if CONFIG_MICRODIA_DEBUG
1246 dev->vdev->debug = V4L2_DEBUG_IOCTL_ARG;
1247 #endif
1248 dev->vdev->vidioc_querycap = microdia_vidioc_querycap;
1249 dev->vdev->vidioc_enum_fmt_cap = microdia_vidioc_enum_fmt_cap;
1250 dev->vdev->vidioc_try_fmt_cap = microdia_vidioc_try_fmt_cap;
1251 dev->vdev->vidioc_s_fmt_cap = microdia_vidioc_s_fmt_cap;
1252 dev->vdev->vidioc_g_fmt_cap = microdia_vidioc_g_fmt_cap;
1253 dev->vdev->vidioc_enum_input = microdia_vidioc_enum_input;
1254 dev->vdev->vidioc_g_input = microdia_vidioc_g_input;
1255 dev->vdev->vidioc_s_input = microdia_vidioc_s_input;
1256 dev->vdev->vidioc_streamon = microdia_vidioc_streamon;
1257 dev->vdev->vidioc_streamoff = microdia_vidioc_streamoff;
1258 dev->vdev->vidioc_queryctrl = microdia_vidioc_queryctrl;
1259 dev->vdev->vidioc_g_ctrl = microdia_vidioc_g_ctrl;
1260 dev->vdev->vidioc_s_ctrl = microdia_vidioc_s_ctrl;
1261 dev->vdev->vidioc_g_parm = microdia_vidioc_g_param;
1262 dev->vdev->vidioc_s_parm = microdia_vidioc_s_param;
1263 dev->vdev->vidioc_reqbufs = microdia_vidioc_reqbufs;
1264 dev->vdev->vidioc_qbuf = microdia_vidioc_qbuf;
1265 dev->vdev->vidioc_dqbuf = microdia_vidioc_dqbuf;
1266 dev->vdev->vidioc_querybuf = microdia_vidioc_querybuf;
1268 video_set_drvdata(dev->vdev, dev);
1270 microdia_queue_init(&dev->queue);
1272 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1274 if (err)
1275 UDIA_ERROR("Video register fail !\n");
1276 else
1277 UDIA_INFO("Microdia USB2.0 Camera is now controlling "
1278 "video device /dev/video%d\n",
1279 dev->vdev->minor);
1281 return err;
1286 * @param dev Device structure
1288 * @returns 0 if all is OK
1290 * @brief Unregister the video device
1292 * This function permits to unregister the video device.
1294 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1296 UDIA_INFO("Microdia USB2.0 Camera release resources video "
1297 "device /dev/video%d\n", dev->vdev->minor);
1299 video_set_drvdata(dev->vdev, NULL);
1300 video_unregister_device(dev->vdev);
1302 return 0;
1307 * @var v4l_microdia_fops
1309 * This variable contains some callback
1311 static struct file_operations v4l_microdia_fops = {
1312 .owner = THIS_MODULE,
1313 .open = v4l_microdia_open,
1314 .release = v4l_microdia_release,
1315 .read = v4l_microdia_read,
1316 .poll = v4l_microdia_poll,
1317 .mmap = v4l_microdia_mmap,
1318 .ioctl = v4l_microdia_ioctl,
1319 #ifdef CONFIG_COMPAT
1320 .compat_ioctl = v4l_compat_ioctl32,
1321 #endif
1322 .llseek = no_llseek