Remove subversion comments.
[microdia.git] / microdia-v4l.c
blobb8e05759ae72cdc174b288492c3df684af653cb4
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>
37 #include <linux/usb.h>
38 #include <media/v4l2-common.h>
40 #include "microdia.h"
43 static struct file_operations v4l_microdia_fops;
46 /**
47 * @var microdia_image_sizes
48 * List of all resolutions supported by the driver
50 const struct microdia_coord microdia_image_sizes[MICRODIA_NBR_SIZES] = {
51 { 80, 60 },
52 /*{ 128, 96 },*/
53 { 160, 120 },
54 /*{ 213, 160 }, */
55 { 320, 240 },
56 { 640, 480 },
57 { 800, 600 },
58 { 1024, 768 },
59 { 1280, 1024 }
63 /**
64 * @var microdia_controls
65 * List of all V4Lv2 controls supported by the driver
67 static struct v4l2_queryctrl microdia_controls[] = {
69 .id = V4L2_CID_BRIGHTNESS,
70 .type = V4L2_CTRL_TYPE_INTEGER,
71 .name = "Brightness",
72 .minimum = 0,
73 .maximum = 0xff00,
74 .step = 1,
75 .default_value = 0x7f00,
78 .id = V4L2_CID_WHITENESS,
79 .type = V4L2_CTRL_TYPE_INTEGER,
80 .name = "Whiteness",
81 .minimum = 0,
82 .maximum = 0xff00,
83 .step = 1,
84 .default_value = 0x7f00,
88 .id = V4L2_CID_SATURATION,
89 .type = V4L2_CTRL_TYPE_INTEGER,
90 .name = "Saturation",
91 .minimum = 0,
92 .maximum = 0xff00,
93 .step = 1,
94 .default_value = 0x7f00,
98 .id = V4L2_CID_CONTRAST,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Contrast",
101 .minimum = 0,
102 .maximum = 0xff00,
103 .step = 1,
104 .default_value = 0x0000,
107 .id = V4L2_CID_EXPOSURE,
108 .type = V4L2_CTRL_TYPE_INTEGER,
109 .name = "Exposure",
110 .minimum = 0,
111 .maximum = 0xff00,
112 .step = 1,
113 .default_value = 0x1000,
116 .id = V4L2_CID_HFLIP,
117 .type = V4L2_CTRL_TYPE_BOOLEAN,
118 .name = "Horizontal flip",
119 .minimum = 0,
120 .maximum = 1,
121 .step = 1,
122 .default_value = 0,
125 .id = V4L2_CID_VFLIP,
126 .type = V4L2_CTRL_TYPE_BOOLEAN,
127 .name = "Vertical flip",
128 .minimum = 0,
129 .maximum = 1,
130 .step = 1,
131 .default_value = 0,
136 /**
137 * @param dev
138 * @param width Width of wished resolution
139 * @param height Height of wished resolution
141 * @returns 0 if all is OK
143 * @brief Select a video mode
145 * This function permits to check and select a video mode.
147 int v4l_microdia_select_video_mode(struct usb_microdia *dev, int width, int height)
149 int i;
150 int find;
153 // Check width and height
154 // Notice : this test is usefull for the Kopete application !
155 printk( KERN_INFO "Changing resolution to %d by %d\n", width, height);
157 // Driver can't build an image smaller than the minimal resolution !
158 if ((width < microdia_image_sizes[0].x)
159 || (height < microdia_image_sizes[0].y)) {
160 width = microdia_image_sizes[0].x;
161 height = microdia_image_sizes[0].y;
164 // Driver can't build an image bigger than the maximal resolution !
165 switch (dev->webcam_type) {
166 case MICRODIA_SXGA:
167 if ((width > microdia_image_sizes[MICRODIA_NBR_SIZES-1].x)
168 || (height > microdia_image_sizes[MICRODIA_NBR_SIZES-1].y)) {
169 width = microdia_image_sizes[MICRODIA_NBR_SIZES-1].x;
170 height = microdia_image_sizes[MICRODIA_NBR_SIZES-1].y;
172 break;
174 case MICRODIA_VGA:
175 if ((width > microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].x)
176 || (height > microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].y)) {
177 width = microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].x;
178 height = microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].y;
180 break;
182 default:
183 return -1;
187 // Seek the best resolution
188 switch (dev->webcam_type) {
189 case MICRODIA_SXGA:
190 for (i=0, find=0; i<MICRODIA_NBR_SIZES; i++) {
191 if (microdia_image_sizes[i].x <= width && microdia_image_sizes[i].y <= height)
192 find = i;
194 break;
196 case MICRODIA_VGA:
197 for (i=0, find=0; i<MICRODIA_NBR_SIZES-3; i++) {
198 if (microdia_image_sizes[i].x <= width && microdia_image_sizes[i].y <= height)
199 find = i;
201 break;
203 default:
204 return -1;
207 // Save the new resolution
208 dev->resolution = find;
210 UDIA_DEBUG("Set mode %d [%dx%d]\n", dev->resolution,
211 microdia_image_sizes[dev->resolution].x, microdia_image_sizes[dev->resolution].y);
213 // Save the new size
214 dev->view.x = width;
215 dev->view.y = height;
218 // Calculate the frame size
219 switch (dev->resolution) {
220 case MICRODIA_80x60:
221 /*case MICRODIA_128x96:*/
222 case MICRODIA_160x120:
223 /*case MICRODIA_213x160:*/
224 case MICRODIA_320x240:
225 case MICRODIA_640x480:
226 dev->image.x = microdia_image_sizes[MICRODIA_640x480].x;
227 dev->image.y = microdia_image_sizes[MICRODIA_640x480].y;
228 dev->frame_size = dev->image.x * dev->image.y;
229 break;
231 case MICRODIA_800x600:
232 case MICRODIA_1024x768:
233 case MICRODIA_1280x1024:
234 dev->image.x = microdia_image_sizes[MICRODIA_1280x1024].x;
235 dev->image.y = microdia_image_sizes[MICRODIA_1280x1024].y;
236 dev->frame_size = dev->image.x * dev->image.y;
237 break;
241 // Calculate the image size
242 switch (dev->vsettings.palette) {
243 case MICRODIA_PALETTE_RGB24:
244 dev->view_size = 3 * dev->view.x * dev->view.y;
245 break;
246 case MICRODIA_PALETTE_BGR24:
247 dev->view_size = 3 * dev->view.x * dev->view.y;
248 break;
250 case MICRODIA_PALETTE_RGB32:
251 case MICRODIA_PALETTE_BGR32:
252 dev->view_size = 4 * dev->view.x * dev->view.y;
253 break;
255 case MICRODIA_PALETTE_UYVY:
256 case MICRODIA_PALETTE_YUYV:
257 dev->view_size = 2 * dev->view.x * dev->view.y;
258 break;
259 case MICRODIA_PALETTE_I420:
260 dev->view_size = dev->view.x * dev->view.y +
261 (dev->view.x * dev->view.y) / 2;
264 return 0;
268 /**
269 * @param inode Pointer on an inode
270 * @param fp File pointer
272 * @returns 0 if all is OK
274 * @brief Open the video device
276 * This function permits to open a video device (/dev/videoX)
278 static int v4l_microdia_open(struct inode *inode, struct file *fp)
280 int err;
282 struct usb_microdia *dev;
283 struct video_device *vdev;
285 vdev = video_devdata(fp);
286 dev = video_get_drvdata(video_devdata(fp));
288 if (dev == NULL) {
289 UDIA_ERROR("Device not initialized !!!\n");
290 BUG();
293 if (dev->vopen) {
294 UDIA_DEBUG("Device is busy, someone is using the device\n");
295 return -EBUSY;
298 // Allocate memory
299 err = microdia_allocate_buffers(dev);
301 if (err < 0) {
302 UDIA_ERROR("Failed to allocate buffer memory !\n");
303 return err;
306 // Reset buffers and parameters
307 microdia_reset_buffers(dev);
309 // Settings
310 dev->error_status = 0;
311 dev->visoc_errors = 0;
312 dev->vframes_error = 0;
313 dev->vframes_dumped = 0;
314 dev->vsettings.hue = 0xffff;
315 dev->vsettings.depth = 24;
318 dev->vsettings.palette = MICRODIA_PALETTE_I420;
321 // Select the resolution by default
322 v4l_microdia_select_video_mode(dev, 640, 480);
324 // Initialize the device
325 dev_microdia_init_camera(dev);
326 dev_microdia_camera_on(dev);
328 // Init Isoc and URB
329 err = usb_microdia_isoc_init(dev);
331 if (err) {
332 UDIA_ERROR("Failed to init ISOC stuff !\n");
333 usb_microdia_isoc_cleanup(dev);
334 microdia_free_buffers(dev);
335 return err;
338 // Start the video stream
339 dev_microdia_start_stream(dev);
340 dev_microdia_camera_settings(dev);
342 dev->vopen++;
343 fp->private_data = vdev;
345 return 0;
349 /**
350 * @param inode Pointer on inode
351 * @param fp File pointer
353 * @returns 0 if all is OK
355 * @brief Release an opened file.
357 * This function permits to release an opened file with the 'open' method.
359 static int v4l_microdia_release(struct inode *inode, struct file *fp)
361 struct usb_microdia *dev;
362 struct video_device *vdev;
364 vdev = video_devdata(fp);
365 dev = video_get_drvdata(video_devdata(fp));
367 if (dev->vopen == 0)
368 UDIA_ERROR("v4l_release called on closed device\n");
370 // Stop the video stream
371 dev_microdia_stop_stream(dev);
373 // ISOC and URB cleanup
374 usb_microdia_isoc_cleanup(dev);
376 // Free memory
377 microdia_free_buffers(dev);
379 // Switch off the camera
380 dev_microdia_camera_off(dev);
382 // dev_microdia_camera_asleep(dev);
384 dev->vopen--;
386 return 0;
390 /**
391 * @param fp File pointer
393 * @retval buf Buffer in user space
394 * @retval count
395 * @retval f_pos
397 * @returns Count value
399 * @brief Read the video device
401 * This function is called by the application is reading the video device.
403 static ssize_t v4l_microdia_read(struct file *fp, char __user *buf,
404 size_t count, loff_t *f_pos)
406 int noblock = fp->f_flags & O_NONBLOCK;
408 struct usb_microdia *dev;
409 struct video_device *vdev;
411 int bytes_to_read;
412 void *image_buffer_addr;
414 DECLARE_WAITQUEUE(wait, current);
416 vdev = video_devdata(fp);
417 dev = video_get_drvdata(video_devdata(fp));
419 UDIA_STREAM("Read vdev=0x%p, buf=0x%p, count=%zd\n", vdev, buf, count);
421 if (dev == NULL)
422 return -EFAULT;
424 if (vdev == NULL)
425 return -EFAULT;
427 if (dev->image_read_pos == 0) {
428 add_wait_queue(&dev->wait_frame, &wait);
430 while (dev->full_frames == NULL) {
431 if (dev->error_status) {
432 remove_wait_queue(&dev->wait_frame, &wait);
433 set_current_state(TASK_RUNNING);
434 return -dev->error_status ;
437 if (noblock) {
438 remove_wait_queue(&dev->wait_frame, &wait);
439 set_current_state(TASK_RUNNING);
440 return -EWOULDBLOCK;
443 if (signal_pending(current)) {
444 remove_wait_queue(&dev->wait_frame, &wait);
445 set_current_state(TASK_RUNNING);
446 return -ERESTARTSYS;
449 schedule();
450 set_current_state(TASK_INTERRUPTIBLE);
453 remove_wait_queue(&dev->wait_frame, &wait);
454 set_current_state(TASK_RUNNING);
456 if (microdia_handle_frame(dev))
457 return -EFAULT;
460 bytes_to_read = dev->view_size;
462 if (count + dev->image_read_pos > bytes_to_read)
463 count = bytes_to_read - dev->image_read_pos;
465 image_buffer_addr = dev->image_data;
466 image_buffer_addr += dev->images[dev->fill_image].offset;
467 image_buffer_addr += dev->image_read_pos;
469 if (copy_to_user(buf, image_buffer_addr, count))
470 return -EFAULT;
472 dev->image_read_pos += count;
474 if (dev->image_read_pos >= bytes_to_read) {
475 dev->image_read_pos = 0;
476 microdia_next_image(dev);
479 return count;
483 /**
484 * @param fp File pointer
485 * @param wait
487 * @returns 0 if all is OK
489 * @brief Polling function
491 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
493 struct usb_microdia *dev;
494 struct video_device *vdev;
496 vdev = video_devdata(fp);
497 dev = video_get_drvdata(video_devdata(fp));
499 UDIA_STREAM("Poll\n");
501 if (vdev == NULL)
502 return -EFAULT;
504 if (dev == NULL)
505 return -EFAULT;
507 poll_wait(fp, &dev->wait_frame, wait);
509 if (dev->error_status)
510 return POLLERR;
512 if (dev->full_frames != NULL)
513 return (POLLIN | POLLRDNORM);
515 return 0;
519 /**
520 * @param fp File pointer
521 * @param vma VMA structure
523 * @returns 0 if all is OK
525 * @brief Memory map
527 * This function permits to map a memory space.
529 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
531 unsigned int i;
533 unsigned long size;
534 unsigned long start;
535 unsigned long pos;
536 unsigned long page;
538 struct usb_microdia *dev;
540 struct video_device *vdev;
542 vdev = video_devdata(fp);
543 dev = video_get_drvdata(video_devdata(fp));
545 UDIA_STREAM("mmap\n");
547 start = vma->vm_start;
548 size = vma->vm_end - vma->vm_start;
550 // Find the buffer for this mapping...
551 for (i=0; i<dev->nbuffers; i++) {
552 pos = dev->images[i].offset;
554 if ((pos >> PAGE_SHIFT) == vma->vm_pgoff)
555 break;
558 // If no buffer found !
559 if (i == MICRODIA_MAX_IMAGES) {
560 UDIA_ERROR("mmap no buffer found !\n");
561 return -EINVAL;
564 if (i == 0) {
565 unsigned long total_size;
567 total_size = dev->nbuffers * dev->len_per_image;
569 if (size != dev->len_per_image && size != total_size)
570 return -EINVAL;
572 else if (size > dev->len_per_image)
573 return -EINVAL;
575 vma->vm_flags |= VM_IO;
577 pos = (unsigned long) dev->image_data;
579 while (size > 0) {
580 page = vmalloc_to_pfn((void *) pos);
582 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
583 return -EAGAIN;
585 start += PAGE_SIZE;
586 pos += PAGE_SIZE;
588 if (size > PAGE_SIZE)
589 size -= PAGE_SIZE;
590 else
591 size = 0;
594 return 0;
598 /**
599 * @param inode Inode pointer
600 * @param fp File pointer
601 * @param cmd Command
602 * @param arg Arguments of the command
604 * @returns 0 if all is OK
606 * @brief Manage IOCTL
608 * This function permits to manage all the IOCTL from the application.
610 static int v4l_microdia_do_ioctl(struct inode *inode, struct file *fp,
611 unsigned int cmd, void __user *arg)
613 struct usb_microdia *dev;
614 struct video_device *vdev;
616 DECLARE_WAITQUEUE(wait, current);
618 vdev = video_devdata(fp);
619 dev = video_get_drvdata(video_devdata(fp));
621 #if (CONFIG_MICRODIA_DEBUG == 1)
622 v4l_printk_ioctl(cmd);
623 #endif
625 switch (cmd) {
626 // Video 4 Linux v1
628 case VIDIOCGCAP:
630 struct video_capability *cap = arg;
632 UDIA_DEBUG("VIDIOCGCAP\n");
634 memset(cap, 0, sizeof(*cap));
635 strlcpy(cap->name, "microdia", sizeof(cap->name));
636 cap->type = VID_TYPE_CAPTURE;
637 cap->channels = 1;
638 cap->audios = 0;
640 switch (dev->webcam_type) {
641 case MICRODIA_SXGA:
642 cap->minwidth = microdia_image_sizes[MICRODIA_80x60].x;
643 cap->minheight = microdia_image_sizes[MICRODIA_80x60].y;
644 cap->maxwidth = microdia_image_sizes[MICRODIA_1280x1024].x;
645 cap->maxheight = microdia_image_sizes[MICRODIA_1280x1024].y;
646 break;
648 case MICRODIA_VGA:
649 cap->minwidth = microdia_image_sizes[MICRODIA_80x60].x;
650 cap->minheight = microdia_image_sizes[MICRODIA_80x60].y;
651 cap->maxwidth = microdia_image_sizes[MICRODIA_640x480].x;
652 cap->maxheight = microdia_image_sizes[MICRODIA_640x480].y;
653 break;
656 break;
658 case VIDIOCGCHAN:
660 struct video_channel *v = arg;
662 UDIA_DEBUG("VIDIOCGCHAN\n");
664 if (v->channel != 0)
665 return -EINVAL;
667 v->flags = 0;
668 v->tuners = 0;
669 v->type = VIDEO_TYPE_CAMERA;
670 strcpy(v->name, "Webcam");
672 break;
674 case VIDIOCSCHAN:
676 struct video_channel *v = arg;
678 UDIA_DEBUG("VIDIOCSCHAN\n");
680 if (v->channel != 0)
681 return -EINVAL;
683 break;
685 case VIDIOCGPICT:
687 struct video_picture *p = arg;
689 UDIA_DEBUG("VIDIOCGPICT\n");
691 p->brightness = dev->vsettings.brightness;
692 p->contrast = dev->vsettings.contrast;
693 p->whiteness = dev->vsettings.whiteness;
694 p->colour = dev->vsettings.colour;
695 p->depth = dev->vsettings.depth;
696 p->palette = dev->vsettings.palette;
697 p->hue = dev->vsettings.hue;
698 //p->exposure = dev->vsettings.exposure;
700 switch (dev->vsettings.palette) {
701 case MICRODIA_PALETTE_I420:
702 p->palette = VIDEO_PALETTE_YUV420P;
703 break;
705 case MICRODIA_PALETTE_BGR24:
706 p->palette = VIDEO_PALETTE_RGB24;
707 break;
709 case MICRODIA_PALETTE_BGR32:
710 p->palette = VIDEO_PALETTE_RGB32;
711 break;
713 case MICRODIA_PALETTE_UYVY:
714 p->palette = VIDEO_PALETTE_UYVY;
715 break;
717 case MICRODIA_PALETTE_YUYV:
718 p->palette = VIDEO_PALETTE_YUYV;
719 break;
722 break;
724 case VIDIOCSPICT:
726 struct video_picture *p = arg;
728 UDIA_DEBUG("VIDIOCSPICT\n");
730 dev->vsettings.brightness = p->brightness;
731 dev->vsettings.contrast = p->contrast;
732 dev->vsettings.whiteness = p->whiteness;
733 dev->vsettings.colour = p->colour;
734 dev->vsettings.hue = p->hue;
735 //dev->vsettings.exposure = p->exposure;
736 //dev->vsettings.gamma = p->gamma;
738 if (p->palette && p->palette != dev->vsettings.palette) {
739 switch (p->palette) {
740 case VIDEO_PALETTE_YUV420P:
741 dev->vsettings.depth = 12;
742 dev->vsettings.palette = MICRODIA_PALETTE_I420;
743 break;
745 case VIDEO_PALETTE_RGB24:
746 //Set BGR decoding for V4L1 RGB24 palette
747 dev->vsettings.depth = 24;
748 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
749 break;
751 /*case VIDEO_PALETTE_RGB32:
752 dev->vsettings.depth = 32;
753 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
754 break;
756 case VIDEO_PALETTE_UYVY:
757 dev->vsettings.depth = 16;
758 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
759 break;
761 case VIDEO_PALETTE_YUYV:
762 dev->vsettings.depth = 16;
763 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
764 break;
766 default:
767 return -EINVAL;
771 dev_microdia_camera_settings(dev);
773 UDIA_DEBUG("VIDIOCSPICT done\n");
775 break;
777 case VIDIOCGWIN:
779 struct video_window *vw = arg;
781 UDIA_DEBUG("VIDIOCGWIN\n");
783 vw->x = 0;
784 vw->y = 0;
785 vw->width = dev->view.x;
786 vw->height = dev->view.y;
787 vw->chromakey = 0;
789 break;
791 case VIDIOCSWIN:
793 struct video_window *vw = arg;
795 UDIA_DEBUG("VIDIOCSWIN\n");
797 UDIA_DEBUG("Set x=%d, y=%d\n", vw->x, vw->y);
798 UDIA_DEBUG("Set width=%d, height=%d\n", vw->width, vw->height);
799 UDIA_DEBUG("Flags = %X\n", vw->flags);
801 // Stop the video stream
802 dev_microdia_stop_stream(dev);
804 // ISOC and URB cleanup
805 usb_microdia_isoc_cleanup(dev);
807 // Switch off the camera
808 dev_microdia_camera_off(dev);
810 // dev_microdia_camera_asleep(dev);
812 // Select the new video mode
813 if (v4l_microdia_select_video_mode(dev, vw->width, vw->height)) {
814 UDIA_ERROR("Select video mode failed !\n");
815 return -EAGAIN;
818 // Clear the buffers
819 microdia_clear_buffers(dev);
821 // Initialize the device
822 dev_microdia_init_camera(dev);
823 dev_microdia_camera_on(dev);
825 // ISOC and URB init
826 usb_microdia_isoc_init(dev);
828 // Re-start the stream
829 dev_microdia_start_stream(dev);
831 // Video settings
832 dev_microdia_camera_settings(dev);
834 break;
836 case VIDIOCGFBUF:
838 struct video_buffer *vb = arg;
840 UDIA_DEBUG("VIDIOCGFBUF\n");
842 memset(vb, 0, sizeof(*vb));
844 break;
846 case VIDIOCGMBUF:
848 int i;
849 struct video_mbuf *vm = arg;
851 UDIA_DEBUG("VIDIOCGMBUF\n");
853 memset(vm, 0, sizeof(*vm));
855 vm->size = dev->nbuffers * dev->len_per_image;
856 vm->frames = dev->nbuffers;
858 for (i=0; i<dev->nbuffers; i++)
859 vm->offsets[i] = i * dev->len_per_image;
861 break;
863 case VIDIOCMCAPTURE:
865 struct video_mmap *vm = arg;
867 UDIA_DEBUG("VIDIOCMCAPTURE format=%d\n", vm->format);
869 if (vm->frame < 0 || vm->frame >= dev->nbuffers)
870 return -EINVAL;
872 if (vm->format) {
873 switch (vm->format) {
874 case VIDEO_PALETTE_YUV420P:
875 break;
877 case VIDEO_PALETTE_RGB24:
878 break;
880 /*case VIDEO_PALETTE_RGB32:
881 break;
883 case VIDEO_PALETTE_UYVY:
884 break;
886 case VIDEO_PALETTE_YUYV:
887 break;
889 default:
890 return -EINVAL;
894 if ((vm->width != dev->view.x) || (vm->height != dev->view.y))
895 return -EAGAIN;
897 if (dev->image_used[vm->frame])
898 return -EBUSY;
900 dev->image_used[vm->frame] = 1;
902 UDIA_DEBUG("VIDIOCMCAPTURE done\n");
904 break;
906 case VIDIOCSYNC:
908 int ret;
909 int *mbuf = arg;
911 UDIA_DEBUG("VIDIOCSYNC\n");
913 if (*mbuf < 0 || *mbuf >= dev->nbuffers)
914 return -EINVAL;
916 if (dev->image_used[*mbuf] == 0)
917 return -EINVAL;
919 add_wait_queue(&dev->wait_frame, &wait);
921 while (dev->full_frames == NULL) {
922 if (dev->error_status) {
923 remove_wait_queue(&dev->wait_frame, &wait);
924 set_current_state(TASK_RUNNING);
925 return -dev->error_status;
928 if (signal_pending(current)) {
929 remove_wait_queue(&dev->wait_frame, &wait);
930 set_current_state(TASK_RUNNING);
931 return -ERESTARTSYS;
934 schedule();
935 set_current_state(TASK_INTERRUPTIBLE);
938 remove_wait_queue(&dev->wait_frame, &wait);
939 set_current_state(TASK_RUNNING);
941 UDIA_DEBUG("VIDIOCSYNC: frame ready\n");
943 dev->fill_image = *mbuf;
945 ret = microdia_handle_frame(dev);
947 if (ret != 0)
948 UDIA_ERROR("VIDIOCSYNC error !\n");
950 dev->image_used[*mbuf] = 0;
952 break;
954 case VIDIOCGAUDIO:
955 UDIA_DEBUG("VIDIOCGAUDIO\n");
956 return -EINVAL;
957 break;
959 case VIDIOCSAUDIO:
960 UDIA_DEBUG("VIDIOCSAUDIO\n");
961 return -EINVAL;
962 break;
964 case VIDIOCGUNIT:
966 struct video_unit *vu = arg;
968 vu->video = dev->vdev->minor & 0x3f;
969 vu->audio = -1;
970 vu->vbi = -1;
971 vu->radio = -1;
972 vu->teletext = -1;
974 break;
977 // Video 4 Linux v2
979 case VIDIOC_QUERYCAP:
981 struct v4l2_capability *cap = arg;
983 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
985 memset(cap, 0, sizeof(*cap));
986 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
988 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
989 cap->version = (__u32) DRIVER_VERSION_NUM, strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
991 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
992 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
994 break;
996 case VIDIOC_ENUMINPUT:
998 struct v4l2_input *i = arg;
1000 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", i->index);
1002 if (i->index)
1003 return -EINVAL;
1005 strlcpy(i->name, "Webcam", sizeof(i->name));
1006 i->type = V4L2_INPUT_TYPE_CAMERA;
1008 break;
1010 case VIDIOC_G_INPUT:
1012 struct v4l2_input *i = arg;
1014 UDIA_DEBUG("GET INPUT %d\n", i->index);
1016 if (i->index)
1017 return -EINVAL;
1019 break;
1021 case VIDIOC_S_INPUT:
1023 struct v4l2_input *i = arg;
1025 UDIA_DEBUG("SET INPUT %d\n", i->index);
1027 if (i->index != 0)
1028 return -EINVAL;
1030 break;
1032 case VIDIOC_QUERYCTRL:
1034 int i;
1035 int nbr;
1036 struct v4l2_queryctrl *c = arg;
1038 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", c->id);
1040 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
1042 for (i=0; i<nbr; i++) {
1043 if (microdia_controls[i].id == c->id) {
1044 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
1045 memcpy(c, &microdia_controls[i], sizeof(struct v4l2_queryctrl));
1046 break;
1050 if (i >= nbr)
1051 return -EINVAL;
1053 break;
1055 case VIDIOC_G_CTRL:
1057 struct v4l2_control *c = arg;
1059 UDIA_DEBUG("GET CTRL id=%d\n", c->id);
1061 switch (c->id) {
1062 case V4L2_CID_BRIGHTNESS:
1063 c->value = dev->vsettings.brightness;
1064 break;
1066 case V4L2_CID_EXPOSURE:
1067 c->value = dev->vsettings.exposure;
1068 break;
1070 case V4L2_CID_WHITENESS:
1071 c->value = dev->vsettings.whiteness;
1072 break;
1074 case V4L2_CID_SATURATION:
1075 c->value = dev->vsettings.colour;
1076 break;
1078 case V4L2_CID_CONTRAST:
1079 c->value = dev->vsettings.contrast;
1080 break;
1082 case V4L2_CID_HFLIP:
1083 c->value = dev->vsettings.hflip;
1084 break;
1086 case V4L2_CID_VFLIP:
1087 c->value = dev->vsettings.vflip;
1088 break;
1090 default:
1091 return -EINVAL;
1094 break;
1096 case VIDIOC_S_CTRL:
1098 struct v4l2_control *c = arg;
1100 UDIA_DEBUG("SET CTRL id=%d value=%d\n", c->id, c->value);
1102 switch (c->id) {
1103 case V4L2_CID_BRIGHTNESS:
1104 dev->vsettings.brightness = (0xff00 & c->value);
1105 dev_microdia_camera_set_brightness(dev);
1106 break;
1108 case V4L2_CID_WHITENESS:
1109 dev->vsettings.whiteness = (0xff00 & c->value);
1110 dev_microdia_camera_set_gamma(dev);
1111 break;
1113 /*case V4L2_CID_SATURATION:
1114 dev->vsettings.colour = (0xff00 & c->value);
1115 break;*/
1116 case V4L2_CID_EXPOSURE:
1117 dev->vsettings.exposure = (0xff00 & c->value);
1118 dev_microdia_camera_set_exposure(dev);
1119 break;
1121 case V4L2_CID_CONTRAST:
1122 dev->vsettings.contrast = (0xff00 & c->value);
1123 dev_microdia_camera_set_contrast(dev);
1124 break;
1126 case V4L2_CID_HFLIP:
1127 dev->vsettings.hflip = c->value;
1128 dev_microdia_camera_set_hvflip(dev);
1129 break;
1131 case V4L2_CID_VFLIP:
1132 dev->vsettings.vflip = c->value;
1133 dev_microdia_camera_set_hvflip(dev);
1134 break;
1136 default:
1137 return -EINVAL;
1140 // dev_microdia_camera_settings(dev);
1142 break;
1144 case VIDIOC_ENUM_FMT:
1146 int index;
1147 struct v4l2_fmtdesc *fmtd = arg;
1149 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd->index);
1151 if (fmtd->index != 0)
1152 return -EINVAL;
1154 index = fmtd->index;
1156 memset(fmtd, 0, sizeof(*fmtd));
1158 fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1159 fmtd->index = index;
1161 switch (index) {
1162 case 0:
1163 fmtd->flags = 0;
1164 fmtd->pixelformat = V4L2_PIX_FMT_YUV420;
1165 strcpy(fmtd->description, "i420");
1166 break;
1167 /*fmtd->flags = 0;
1168 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1170 strcpy(fmtd->description, "rgb24");
1171 break;*/
1173 case 1:
1174 fmtd->flags = 0;
1175 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1177 strcpy(fmtd->description, "bgr24");
1178 break;
1180 case 2:
1181 fmtd->flags = 0;
1182 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1184 strcpy(fmtd->description, "rgb24");
1185 break;
1187 /*case 3:
1188 fmtd->flags = 0;
1189 fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
1191 strcpy(fmtd->description, "bgr32");
1192 break;
1194 case 4:
1195 fmtd->flags = 0;
1196 fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
1198 strcpy(fmtd->description, "uyvy");
1199 break;
1201 case 5:
1202 fmtd->flags = 0;
1203 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1205 strcpy(fmtd->description, "yuyv");
1206 break;*/
1208 default:
1209 return -EINVAL;
1212 break;
1214 case VIDIOC_G_FMT:
1216 struct v4l2_format *fmtd = arg;
1217 struct v4l2_pix_format pix_format;
1219 UDIA_DEBUG("GET FMT %d\n", fmtd->type);
1221 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1222 return -EINVAL;
1224 pix_format.width = dev->view.x;
1225 pix_format.height = dev->view.y;
1226 pix_format.field = V4L2_FIELD_NONE;
1227 pix_format.colorspace = V4L2_COLORSPACE_SRGB;
1228 pix_format.priv = 0;
1230 switch (dev->vsettings.palette) {
1231 case MICRODIA_PALETTE_I420:
1232 pix_format.pixelformat = V4L2_PIX_FMT_YUV420;
1233 pix_format.sizeimage = pix_format.width * pix_format.height +
1234 (pix_format.width * pix_format.height) / 2;
1235 case MICRODIA_PALETTE_BGR24:
1236 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1237 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1238 pix_format.bytesperline = 3 * pix_format.width;
1239 break;
1240 case MICRODIA_PALETTE_RGB24:
1241 pix_format.pixelformat = V4L2_PIX_FMT_RGB24;
1242 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1243 pix_format.bytesperline = 3 * pix_format.width;
1244 break;
1245 /*case MICRODIA_PALETTE_RGB32:
1246 pix_format.pixelformat = V4L2_PIX_FMT_RGB32;
1247 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1248 pix_format.bytesperline = 4 * pix_format.width;
1249 break;
1251 case MICRODIA_PALETTE_BGR24:
1252 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1253 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1254 pix_format.bytesperline = 3 * pix_format.width;
1255 break;
1257 case MICRODIA_PALETTE_BGR32:
1258 pix_format.pixelformat = V4L2_PIX_FMT_BGR32;
1259 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1260 pix_format.bytesperline = 4 * pix_format.width;
1261 break;
1263 case MICRODIA_PALETTE_UYVY:
1264 pix_format.pixelformat = V4L2_PIX_FMT_UYVY;
1265 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1266 pix_format.bytesperline = 2 * pix_format.width;
1267 break;
1269 case MICRODIA_PALETTE_YUYV:
1270 pix_format.pixelformat = V4L2_PIX_FMT_YUYV;
1271 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1272 pix_format.bytesperline = 2 * pix_format.width;
1273 break;
1277 memcpy(&(fmtd->fmt.pix), &pix_format, sizeof(pix_format));
1279 break;
1281 case VIDIOC_TRY_FMT:
1283 struct v4l2_format *fmtd = arg;
1285 UDIA_DEBUG("TRY FMT %d\n", fmtd->type);
1287 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1288 return -EINVAL;
1290 switch (fmtd->fmt.pix.pixelformat) {
1291 case V4L2_PIX_FMT_BGR24:
1292 /*case V4L2_PIX_FMT_BGR24:*/
1293 dev->vsettings.depth = 24;
1294 break;
1296 case V4L2_PIX_FMT_RGB24:
1297 dev->vsettings.depth = 24;
1298 break;
1299 /*case V4L2_PIX_FMT_RGB32:
1300 case V4L2_PIX_FMT_BGR32:
1301 dev->vsettings.depth = 32;
1302 break;
1304 case V4L2_PIX_FMT_UYVY:
1305 case V4L2_PIX_FMT_YUYV:
1306 dev->vsettings.depth = 16;
1307 break;
1309 case V4L2_PIX_FMT_YUV420:
1310 dev->vsettings.depth = 12;
1311 break;
1313 default:
1314 return -EINVAL;
1317 switch (dev->webcam_type) {
1318 case MICRODIA_SXGA:
1319 if (fmtd->fmt.pix.width > microdia_image_sizes[MICRODIA_NBR_SIZES-1].x)
1320 fmtd->fmt.pix.width = microdia_image_sizes[MICRODIA_NBR_SIZES-1].x;
1321 else if (fmtd->fmt.pix.width < microdia_image_sizes[0].x)
1322 fmtd->fmt.pix.width = microdia_image_sizes[0].x;
1324 if (fmtd->fmt.pix.height > microdia_image_sizes[MICRODIA_NBR_SIZES-1].y)
1325 fmtd->fmt.pix.height = microdia_image_sizes[MICRODIA_NBR_SIZES-1].y;
1326 else if (fmtd->fmt.pix.height < microdia_image_sizes[0].y)
1327 fmtd->fmt.pix.height = microdia_image_sizes[0].y;
1328 break;
1330 case MICRODIA_VGA:
1331 if (fmtd->fmt.pix.width > microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].x)
1332 fmtd->fmt.pix.width = microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].x;
1333 else if (fmtd->fmt.pix.width < microdia_image_sizes[0].x)
1334 fmtd->fmt.pix.width = microdia_image_sizes[0].x;
1336 if (fmtd->fmt.pix.height > microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].y)
1337 fmtd->fmt.pix.height = microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].y;
1338 else if (fmtd->fmt.pix.height < microdia_image_sizes[0].y)
1339 fmtd->fmt.pix.height = microdia_image_sizes[0].y;
1340 break;
1344 break;
1346 case VIDIOC_S_FMT:
1348 struct v4l2_format *fmtd = arg;
1350 UDIA_DEBUG("SET FMT %d : %d\n", fmtd->type, fmtd->fmt.pix.pixelformat);
1352 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1353 return -EINVAL;
1355 switch (fmtd->fmt.pix.pixelformat) {
1356 case V4L2_PIX_FMT_YUV420:
1357 dev->vsettings.depth = 12;
1358 dev->vsettings.palette = MICRODIA_PALETTE_I420;
1359 break;
1361 case V4L2_PIX_FMT_BGR24:
1362 //set the decoder BGR24 from application
1363 dev->vsettings.depth = 24;
1364 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1365 break;
1367 case V4L2_PIX_FMT_RGB24:
1368 //set the decoder RGB24 from application
1369 dev->vsettings.depth = 24;
1370 dev->vsettings.palette = MICRODIA_PALETTE_RGB24;
1371 break;
1373 /*case V4L2_PIX_FMT_RGB32:
1374 dev->vsettings.depth = 32;
1375 dev->vsettings.palette = MICRODIA_PALETTE_RGB32;
1376 break;
1378 case V4L2_PIX_FMT_BGR24:
1379 dev->vsettings.depth = 24;
1380 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1381 break;
1383 case V4L2_PIX_FMT_BGR32:
1384 dev->vsettings.depth = 32;
1385 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
1386 break;
1388 case V4L2_PIX_FMT_UYVY:
1389 dev->vsettings.depth = 16;
1390 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
1391 break;
1393 case V4L2_PIX_FMT_YUYV:
1394 dev->vsettings.depth = 16;
1395 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
1396 break;
1398 default:
1399 break;
1400 return -EINVAL;
1403 UDIA_DEBUG("Set width=%d, height=%d\n", fmtd->fmt.pix.width, fmtd->fmt.pix.height);
1405 // Stop the video stream
1406 dev_microdia_stop_stream(dev);
1408 // ISOC and URB cleanup
1409 usb_microdia_isoc_cleanup(dev);
1411 // Switch off the camera
1412 dev_microdia_camera_off(dev);
1414 // dev_microdia_camera_asleep(dev);
1416 // Select the new video mode
1417 if (v4l_microdia_select_video_mode(dev, fmtd->fmt.pix.width, fmtd->fmt.pix.height)) {
1418 UDIA_ERROR("Select video mode failed !\n");
1419 return -EAGAIN;
1422 // Clear the buffers
1423 microdia_clear_buffers(dev);
1425 // Initialize the device
1426 dev_microdia_init_camera(dev);
1427 dev_microdia_camera_on(dev);
1429 // ISOC and URB init
1430 usb_microdia_isoc_init(dev);
1432 // Re-start the stream
1433 dev_microdia_start_stream(dev);
1435 // Video settings
1436 dev_microdia_camera_settings(dev);
1438 break;
1440 case VIDIOC_QUERYSTD:
1442 UDIA_DEBUG("QUERY STD\n");
1443 return -EINVAL;
1445 break;
1447 case VIDIOC_G_STD:
1449 v4l2_std_id *std = arg;
1451 UDIA_DEBUG("GET STD\n");
1453 *std = V4L2_STD_UNKNOWN;
1455 break;
1457 case VIDIOC_S_STD:
1459 v4l2_std_id *std = arg;
1461 UDIA_DEBUG("SET STD\n");
1463 if (*std != V4L2_STD_UNKNOWN)
1464 return -EINVAL;
1466 break;
1468 case VIDIOC_ENUMSTD:
1470 struct v4l2_standard *std = arg;
1472 UDIA_DEBUG("VIDIOC_ENUMSTD\n");
1474 if (std->index != 0)
1475 return -EINVAL;
1477 std->id = V4L2_STD_UNKNOWN;
1478 strncpy(std->name, "webcam", sizeof(std->name));
1480 break;
1483 case VIDIOC_REQBUFS:
1485 int nbuffers;
1486 struct v4l2_requestbuffers *rb = arg;
1488 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1489 return -EINVAL;
1491 if (rb->memory != V4L2_MEMORY_MMAP)
1492 return -EINVAL;
1494 nbuffers = rb->count;
1496 if (nbuffers < 2)
1497 nbuffers = 2;
1498 else if (nbuffers > dev->nbuffers)
1499 nbuffers = dev->nbuffers;
1501 rb->count = dev->nbuffers;
1503 break;
1505 case VIDIOC_QUERYBUF:
1507 int index;
1508 struct v4l2_buffer *buf = arg;
1510 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buf->index, dev->nbuffers);
1512 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1513 return -EINVAL;
1515 if (buf->memory != V4L2_MEMORY_MMAP)
1516 return -EINVAL;
1518 index = buf->index;
1520 if (index < 0 || index >= dev->nbuffers)
1521 return -EINVAL;
1523 memset(buf, 0, sizeof(struct v4l2_buffer));
1525 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1526 buf->index = index;
1527 buf->m.offset = index * dev->len_per_image;
1528 buf->bytesused = dev->view_size;
1529 buf->field = V4L2_FIELD_NONE;
1530 buf->memory = V4L2_MEMORY_MMAP;
1531 buf->length = dev->len_per_image;
1533 break;
1535 case VIDIOC_QBUF:
1537 struct v4l2_buffer *buf = arg;
1539 UDIA_DEBUG("VIDIOC_QBUF\n");
1541 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1542 return -EINVAL;
1544 if (buf->memory != V4L2_MEMORY_MMAP)
1545 return -EINVAL;
1547 if (buf->index < 0 || buf->index >= dev->nbuffers)
1548 return -EINVAL;
1550 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1551 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1553 break;
1555 case VIDIOC_DQBUF:
1557 int ret;
1558 struct v4l2_buffer *buf = arg;
1560 UDIA_DEBUG("VIDIOC_DQBUF\n");
1562 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1563 return -EINVAL;
1565 add_wait_queue(&dev->wait_frame, &wait);
1567 while (dev->full_frames == NULL) {
1568 if (dev->error_status) {
1569 remove_wait_queue(&dev->wait_frame, &wait);
1570 set_current_state(TASK_RUNNING);
1572 return -dev->error_status;
1575 if (signal_pending(current)) {
1576 remove_wait_queue(&dev->wait_frame, &wait);
1577 set_current_state(TASK_RUNNING);
1579 return -ERESTARTSYS;
1581 if (fp->f_flags & O_NONBLOCK) {
1582 remove_wait_queue(&dev->wait_frame, &wait);
1583 set_current_state(TASK_RUNNING);
1585 return -EAGAIN;
1587 schedule();
1588 set_current_state(TASK_INTERRUPTIBLE);
1591 remove_wait_queue(&dev->wait_frame, &wait);
1592 set_current_state(TASK_RUNNING);
1594 UDIA_DEBUG("VIDIOC_DQBUF : frame ready.\n");
1596 ret = microdia_handle_frame(dev);
1598 if (ret)
1599 return -EFAULT;
1601 buf->index = dev->fill_image;
1602 buf->bytesused = dev->view_size;
1603 buf->flags = V4L2_BUF_FLAG_MAPPED;
1604 buf->field = V4L2_FIELD_NONE;
1605 do_gettimeofday(&buf->timestamp);
1606 buf->sequence = 0;
1607 buf->memory = V4L2_MEMORY_MMAP;
1608 buf->m.offset = dev->fill_image * dev->len_per_image;
1609 buf->length = buf->bytesused;
1611 microdia_next_image(dev);
1613 break;
1615 case VIDIOC_STREAMON:
1617 UDIA_DEBUG("VIDIOC_STREAMON\n");
1619 usb_microdia_isoc_init(dev);
1621 break;
1623 case VIDIOC_STREAMOFF:
1625 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1627 usb_microdia_isoc_cleanup(dev);
1629 break;
1631 case VIDIOC_G_PARM:
1633 struct v4l2_streamparm *sp = arg;
1635 UDIA_DEBUG("GET PARM %d\n", sp->type);
1637 if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1638 return -EINVAL;
1640 sp->parm.capture.capability = 0;
1641 sp->parm.capture.capturemode = 0;
1642 sp->parm.capture.timeperframe.numerator = 1;
1643 sp->parm.capture.timeperframe.denominator = 30;
1644 sp->parm.capture.readbuffers = 2;
1645 sp->parm.capture.extendedmode = 0;
1647 break;
1650 case VIDIOC_G_AUDIO:
1651 UDIA_DEBUG("GET AUDIO\n");
1652 return -EINVAL;
1653 break;
1655 case VIDIOC_S_AUDIO:
1656 UDIA_DEBUG("SET AUDIO\n");
1657 return -EINVAL;
1658 break;
1660 case VIDIOC_S_TUNER:
1661 UDIA_DEBUG("SET TUNER\n");
1662 return -EINVAL;
1663 break;
1665 case VIDIOC_G_FBUF:
1666 case VIDIOC_S_FBUF:
1667 case VIDIOC_OVERLAY:
1668 return -EINVAL;
1669 break;
1671 case VIDIOC_G_TUNER:
1672 case VIDIOC_G_FREQUENCY:
1673 case VIDIOC_S_FREQUENCY:
1674 return -EINVAL;
1675 break;
1677 case VIDIOC_QUERYMENU:
1678 return -EINVAL;
1679 break;
1681 case VIDIOC_CROPCAP:
1683 struct v4l2_cropcap cc;
1685 cc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1686 cc.pixelaspect.numerator = 1;
1687 cc.pixelaspect.denominator = 1;
1688 cc.bounds.top = 0;
1689 cc.bounds.left = 0;
1690 cc.bounds.width = 640;
1691 cc.bounds.height = 480;
1692 cc.defrect.top = 0;
1693 cc.defrect.left = 0;
1694 cc.defrect.width = 640;
1695 cc.defrect.height = 480;
1697 memcpy(arg, &cc, sizeof(cc));
1699 break;
1701 default:
1702 UDIA_DEBUG("IOCTL unknown !\n");
1703 return -ENOIOCTLCMD;
1706 return 0;
1710 /**
1711 * @param inode Inode pointer
1712 * @param fp File pointer
1713 * @param cmd Command
1714 * @param arg Arguements of the command
1716 * @returns 0 if all is OK
1718 * @brief Manage IOCTL
1720 * This function permits to manage all the IOCTL from the application.
1722 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1723 unsigned int cmd, unsigned long arg)
1725 int err;
1726 struct usb_microdia *dev;
1727 struct video_device *vdev;
1729 vdev = video_devdata(fp);
1730 dev = video_get_drvdata(video_devdata(fp));
1732 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1734 if (dev == NULL)
1735 return -EFAULT;
1737 if (vdev == NULL)
1738 return -EFAULT;
1740 err = v4l_microdia_do_ioctl(inode, fp, cmd, (void __user *) arg);
1742 return err;
1746 /**
1747 * @param dev Device structure
1749 * @returns 0 if all is OK
1751 * @brief Register the video device
1753 * This function permits to register the USB device to the video device.
1755 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1757 int err;
1759 strcpy(dev->vdev->name, DRIVER_DESC);
1761 dev->vdev->dev = &dev->interface->dev;
1762 dev->vdev->owner = THIS_MODULE;
1763 dev->vdev->type = VID_TYPE_CAPTURE;
1764 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1765 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1766 #endif
1767 dev->vdev->fops = &v4l_microdia_fops;
1768 dev->vdev->release = video_device_release;
1769 dev->vdev->minor = -1;
1771 video_set_drvdata(dev->vdev, dev);
1773 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1775 if (err)
1776 UDIA_ERROR("Video register fail !\n");
1777 else
1778 UDIA_INFO("Microdia USB2.0 Camera is now controlling video device /dev/video%d\n", dev->vdev->minor);
1780 return err;
1784 /**
1785 * @param dev Device structure
1787 * @returns 0 if all is OK
1789 * @brief Unregister the video device
1791 * This function permits to unregister the video device.
1793 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1795 UDIA_INFO("Microdia USB2.0 Camera release resources video device /dev/video%d\n", dev->vdev->minor);
1797 video_set_drvdata(dev->vdev, NULL);
1798 video_unregister_device(dev->vdev);
1800 return 0;
1805 * @var v4l_microdia_fops
1807 * This variable contains some callback
1809 static struct file_operations v4l_microdia_fops = {
1810 .owner = THIS_MODULE,
1811 .open = v4l_microdia_open,
1812 .release = v4l_microdia_release,
1813 .read = v4l_microdia_read,
1814 .poll = v4l_microdia_poll,
1815 .mmap = v4l_microdia_mmap,
1816 .ioctl = v4l_microdia_ioctl,
1817 #ifdef CONFIG_COMPAT
1818 .compat_ioctl = v4l_compat_ioctl32,
1819 #endif
1820 .llseek = no_llseek