Added support for O_NONBLOCK in DQBUF ioctl
[microdia.git] / microdia-v4l.c
blobe4d077446e2ab409e1b07c6bf58f2cb77338cb04
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
27 * @par SubVersion
28 * $Date: 2008-02-05 10:10:01 +0100 (mar, 05 fév 2008) $
29 * $Revision: 72 $
30 * $Author: nicklas79 $
31 * $HeadURL: https://syntekdriver.svn.sourceforge.net/svnroot/syntekdriver/trunk/driver/microdia-v4l.c $
34 #include <linux/module.h>
35 #include <linux/init.h>
36 #include <linux/kernel.h>
37 #include <linux/version.h>
38 #include <linux/errno.h>
39 #include <linux/slab.h>
40 #include <linux/kref.h>
41 #include <linux/vmalloc.h>
43 #include <linux/usb.h>
44 #include <media/v4l2-common.h>
46 #include "microdia.h"
49 static struct file_operations v4l_microdia_fops;
52 /**
53 * @var microdia_image_sizes
54 * List of all resolutions supported by the driver
56 const struct microdia_coord microdia_image_sizes[MICRODIA_NBR_SIZES] = {
57 { 80, 60 },
58 /*{ 128, 96 },*/
59 { 160, 120 },
60 /*{ 213, 160 }, */
61 { 320, 240 },
62 { 640, 480 },
63 { 800, 600 },
64 { 1024, 768 },
65 { 1280, 1024 }
69 /**
70 * @var microdia_controls
71 * List of all V4Lv2 controls supported by the driver
73 static struct v4l2_queryctrl microdia_controls[] = {
75 .id = V4L2_CID_BRIGHTNESS,
76 .type = V4L2_CTRL_TYPE_INTEGER,
77 .name = "Brightness",
78 .minimum = 0,
79 .maximum = 0xff00,
80 .step = 1,
81 .default_value = 0x7f00,
84 .id = V4L2_CID_WHITENESS,
85 .type = V4L2_CTRL_TYPE_INTEGER,
86 .name = "Whiteness",
87 .minimum = 0,
88 .maximum = 0xff00,
89 .step = 1,
90 .default_value = 0x7f00,
94 .id = V4L2_CID_SATURATION,
95 .type = V4L2_CTRL_TYPE_INTEGER,
96 .name = "Saturation",
97 .minimum = 0,
98 .maximum = 0xff00,
99 .step = 1,
100 .default_value = 0x7f00,
104 .id = V4L2_CID_CONTRAST,
105 .type = V4L2_CTRL_TYPE_INTEGER,
106 .name = "Contrast",
107 .minimum = 0,
108 .maximum = 0xff00,
109 .step = 1,
110 .default_value = 0x0000,
113 .id = V4L2_CID_EXPOSURE,
114 .type = V4L2_CTRL_TYPE_INTEGER,
115 .name = "Exposure",
116 .minimum = 0,
117 .maximum = 0xff00,
118 .step = 1,
119 .default_value = 0x1000,
125 /**
126 * @param dev
127 * @param width Width of wished resolution
128 * @param height Height of wished resolution
130 * @returns 0 if all is OK
132 * @brief Select a video mode
134 * This function permits to check and select a video mode.
136 int v4l_microdia_select_video_mode(struct usb_microdia *dev, int width, int height)
138 int i;
139 int find;
142 // Check width and height
143 // Notice : this test is usefull for the Kopete application !
144 printk( KERN_INFO "Changing resolution to %d by %d\n", width, height);
146 // Driver can't build an image smaller than the minimal resolution !
147 if ((width < microdia_image_sizes[0].x)
148 || (height < microdia_image_sizes[0].y)) {
149 width = microdia_image_sizes[0].x;
150 height = microdia_image_sizes[0].y;
153 // Driver can't build an image bigger than the maximal resolution !
154 switch (dev->webcam_type) {
155 case MICRODIA_SXGA:
156 if ((width > microdia_image_sizes[MICRODIA_NBR_SIZES-1].x)
157 || (height > microdia_image_sizes[MICRODIA_NBR_SIZES-1].y)) {
158 width = microdia_image_sizes[MICRODIA_NBR_SIZES-1].x;
159 height = microdia_image_sizes[MICRODIA_NBR_SIZES-1].y;
161 break;
163 case MICRODIA_VGA:
164 if ((width > microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].x)
165 || (height > microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].y)) {
166 width = microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].x;
167 height = microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].y;
169 break;
171 default:
172 return -1;
176 // Seek the best resolution
177 switch (dev->webcam_type) {
178 case MICRODIA_SXGA:
179 for (i=0, find=0; i<MICRODIA_NBR_SIZES; i++) {
180 if (microdia_image_sizes[i].x <= width && microdia_image_sizes[i].y <= height)
181 find = i;
183 break;
185 case MICRODIA_VGA:
186 for (i=0, find=0; i<MICRODIA_NBR_SIZES-3; i++) {
187 if (microdia_image_sizes[i].x <= width && microdia_image_sizes[i].y <= height)
188 find = i;
190 break;
192 default:
193 return -1;
196 // Save the new resolution
197 dev->resolution = find;
199 UDIA_DEBUG("Set mode %d [%dx%d]\n", dev->resolution,
200 microdia_image_sizes[dev->resolution].x, microdia_image_sizes[dev->resolution].y);
202 // Save the new size
203 dev->view.x = width;
204 dev->view.y = height;
207 // Calculate the frame size
208 switch (dev->resolution) {
209 case MICRODIA_80x60:
210 /*case MICRODIA_128x96:*/
211 case MICRODIA_160x120:
212 /*case MICRODIA_213x160:*/
213 case MICRODIA_320x240:
214 case MICRODIA_640x480:
215 dev->image.x = microdia_image_sizes[MICRODIA_640x480].x;
216 dev->image.y = microdia_image_sizes[MICRODIA_640x480].y;
217 dev->frame_size = dev->image.x * dev->image.y;
218 break;
220 case MICRODIA_800x600:
221 case MICRODIA_1024x768:
222 case MICRODIA_1280x1024:
223 dev->image.x = microdia_image_sizes[MICRODIA_1280x1024].x;
224 dev->image.y = microdia_image_sizes[MICRODIA_1280x1024].y;
225 dev->frame_size = dev->image.x * dev->image.y;
226 break;
230 // Calculate the image size
231 switch (dev->vsettings.palette) {
232 case MICRODIA_PALETTE_RGB24:
233 case MICRODIA_PALETTE_BGR24:
234 dev->view_size = 3 * dev->view.x * dev->view.y;
235 break;
237 case MICRODIA_PALETTE_RGB32:
238 case MICRODIA_PALETTE_BGR32:
239 dev->view_size = 4 * dev->view.x * dev->view.y;
240 break;
242 case MICRODIA_PALETTE_UYVY:
243 case MICRODIA_PALETTE_YUYV:
244 dev->view_size = 2 * dev->view.x * dev->view.y;
245 break;
246 case MICRODIA_PALETTE_I420:
247 dev->view_size = dev->view.x * dev->view.y +
248 (dev->view.x * dev->view.y) / 2;
251 return 0;
255 /**
256 * @param inode Pointer on an inode
257 * @param fp File pointer
259 * @returns 0 if all is OK
261 * @brief Open the video device
263 * This function permits to open a video device (/dev/videoX)
265 static int v4l_microdia_open(struct inode *inode, struct file *fp)
267 int err;
269 struct usb_microdia *dev;
270 struct video_device *vdev;
272 vdev = video_devdata(fp);
273 dev = video_get_drvdata(video_devdata(fp));
275 if (dev == NULL) {
276 UDIA_ERROR("Device not initialized !!!\n");
277 BUG();
280 if (dev->vopen) {
281 UDIA_DEBUG("Device is busy, someone is using the device\n");
282 return -EBUSY;
285 // Allocate memory
286 err = microdia_allocate_buffers(dev);
288 if (err < 0) {
289 UDIA_ERROR("Failed to allocate buffer memory !\n");
290 return err;
293 // Reset buffers and parameters
294 microdia_reset_buffers(dev);
296 // Settings
297 dev->error_status = 0;
298 dev->visoc_errors = 0;
299 dev->vframes_error = 0;
300 dev->vframes_dumped = 0;
301 dev->vsettings.hue = 0xffff;
302 dev->vsettings.depth = 24;
303 //Removed by Boris Borisov for test the 6270 patch from Brian Johnson
304 // dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
305 //Add by B. Borisov for test the 6270 patch from Brian Johnson
306 dev->vsettings.palette = MICRODIA_PALETTE_I420;
308 // Select the resolution by default
309 v4l_microdia_select_video_mode(dev, 640, 480);
311 // Initialize the device
312 dev_microdia_init_camera(dev);
313 dev_microdia_camera_on(dev);
315 // Init Isoc and URB
316 err = usb_microdia_isoc_init(dev);
318 if (err) {
319 UDIA_ERROR("Failed to init ISOC stuff !\n");
320 usb_microdia_isoc_cleanup(dev);
321 microdia_free_buffers(dev);
322 return err;
325 // Start the video stream
326 dev_microdia_start_stream(dev);
327 dev_microdia_camera_settings(dev);
329 dev->vopen++;
330 fp->private_data = vdev;
332 return 0;
336 /**
337 * @param inode Pointer on inode
338 * @param fp File pointer
340 * @returns 0 if all is OK
342 * @brief Release an opened file.
344 * This function permits to release an opened file with the 'open' method.
346 static int v4l_microdia_release(struct inode *inode, struct file *fp)
348 struct usb_microdia *dev;
349 struct video_device *vdev;
351 vdev = video_devdata(fp);
352 dev = video_get_drvdata(video_devdata(fp));
354 if (dev->vopen == 0)
355 UDIA_ERROR("v4l_release called on closed device\n");
357 // Stop the video stream
358 dev_microdia_stop_stream(dev);
360 // ISOC and URB cleanup
361 usb_microdia_isoc_cleanup(dev);
363 // Free memory
364 microdia_free_buffers(dev);
366 // Switch off the camera
367 dev_microdia_camera_off(dev);
369 // dev_microdia_camera_asleep(dev);
371 dev->vopen--;
373 return 0;
377 /**
378 * @param fp File pointer
380 * @retval buf Buffer in user space
381 * @retval count
382 * @retval f_pos
384 * @returns Count value
386 * @brief Read the video device
388 * This function is called by the application is reading the video device.
390 static ssize_t v4l_microdia_read(struct file *fp, char __user *buf,
391 size_t count, loff_t *f_pos)
393 int noblock = fp->f_flags & O_NONBLOCK;
395 struct usb_microdia *dev;
396 struct video_device *vdev;
398 int bytes_to_read;
399 void *image_buffer_addr;
401 DECLARE_WAITQUEUE(wait, current);
403 vdev = video_devdata(fp);
404 dev = video_get_drvdata(video_devdata(fp));
406 UDIA_STREAM("Read vdev=0x%p, buf=0x%p, count=%zd\n", vdev, buf, count);
408 if (dev == NULL)
409 return -EFAULT;
411 if (vdev == NULL)
412 return -EFAULT;
414 if (dev->image_read_pos == 0) {
415 add_wait_queue(&dev->wait_frame, &wait);
417 while (dev->full_frames == NULL) {
418 if (dev->error_status) {
419 remove_wait_queue(&dev->wait_frame, &wait);
420 set_current_state(TASK_RUNNING);
421 return -dev->error_status ;
424 if (noblock) {
425 remove_wait_queue(&dev->wait_frame, &wait);
426 set_current_state(TASK_RUNNING);
427 return -EWOULDBLOCK;
430 if (signal_pending(current)) {
431 remove_wait_queue(&dev->wait_frame, &wait);
432 set_current_state(TASK_RUNNING);
433 return -ERESTARTSYS;
436 schedule();
437 set_current_state(TASK_INTERRUPTIBLE);
440 remove_wait_queue(&dev->wait_frame, &wait);
441 set_current_state(TASK_RUNNING);
443 if (microdia_handle_frame(dev))
444 return -EFAULT;
447 bytes_to_read = dev->view_size;
449 if (count + dev->image_read_pos > bytes_to_read)
450 count = bytes_to_read - dev->image_read_pos;
452 image_buffer_addr = dev->image_data;
453 image_buffer_addr += dev->images[dev->fill_image].offset;
454 image_buffer_addr += dev->image_read_pos;
456 if (copy_to_user(buf, image_buffer_addr, count))
457 return -EFAULT;
459 dev->image_read_pos += count;
461 if (dev->image_read_pos >= bytes_to_read) {
462 dev->image_read_pos = 0;
463 microdia_next_image(dev);
466 return count;
470 /**
471 * @param fp File pointer
472 * @param wait
474 * @returns 0 if all is OK
476 * @brief Polling function
478 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
480 struct usb_microdia *dev;
481 struct video_device *vdev;
483 vdev = video_devdata(fp);
484 dev = video_get_drvdata(video_devdata(fp));
486 UDIA_STREAM("Poll\n");
488 if (vdev == NULL)
489 return -EFAULT;
491 if (dev == NULL)
492 return -EFAULT;
494 poll_wait(fp, &dev->wait_frame, wait);
496 if (dev->error_status)
497 return POLLERR;
499 if (dev->full_frames != NULL)
500 return (POLLIN | POLLRDNORM);
502 return 0;
506 /**
507 * @param fp File pointer
508 * @param vma VMA structure
510 * @returns 0 if all is OK
512 * @brief Memory map
514 * This function permits to map a memory space.
516 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
518 unsigned int i;
520 unsigned long size;
521 unsigned long start;
522 unsigned long pos;
523 unsigned long page;
525 struct usb_microdia *dev;
527 struct video_device *vdev;
529 vdev = video_devdata(fp);
530 dev = video_get_drvdata(video_devdata(fp));
532 UDIA_STREAM("mmap\n");
534 start = vma->vm_start;
535 size = vma->vm_end - vma->vm_start;
537 // Find the buffer for this mapping...
538 for (i=0; i<dev->nbuffers; i++) {
539 pos = dev->images[i].offset;
541 if ((pos >> PAGE_SHIFT) == vma->vm_pgoff)
542 break;
545 // If no buffer found !
546 if (i == MICRODIA_MAX_IMAGES) {
547 UDIA_ERROR("mmap no buffer found !\n");
548 return -EINVAL;
551 if (i == 0) {
552 unsigned long total_size;
554 total_size = dev->nbuffers * dev->len_per_image;
556 if (size != dev->len_per_image && size != total_size)
557 return -EINVAL;
559 else if (size > dev->len_per_image)
560 return -EINVAL;
562 vma->vm_flags |= VM_IO;
564 pos = (unsigned long) dev->image_data;
566 while (size > 0) {
567 page = vmalloc_to_pfn((void *) pos);
569 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
570 return -EAGAIN;
572 start += PAGE_SIZE;
573 pos += PAGE_SIZE;
575 if (size > PAGE_SIZE)
576 size -= PAGE_SIZE;
577 else
578 size = 0;
581 return 0;
585 /**
586 * @param inode Inode pointer
587 * @param fp File pointer
588 * @param cmd Command
589 * @param arg Arguments of the command
591 * @returns 0 if all is OK
593 * @brief Manage IOCTL
595 * This function permits to manage all the IOCTL from the application.
597 static int v4l_microdia_do_ioctl(struct inode *inode, struct file *fp,
598 unsigned int cmd, void __user *arg)
600 struct usb_microdia *dev;
601 struct video_device *vdev;
603 DECLARE_WAITQUEUE(wait, current);
605 vdev = video_devdata(fp);
606 dev = video_get_drvdata(video_devdata(fp));
608 #if (CONFIG_MICRODIA_DEBUG == 1)
609 v4l_printk_ioctl(cmd);
610 #endif
612 switch (cmd) {
613 // Video 4 Linux v1
615 case VIDIOCGCAP:
617 struct video_capability *cap = arg;
619 UDIA_DEBUG("VIDIOCGCAP\n");
621 memset(cap, 0, sizeof(*cap));
622 strlcpy(cap->name, "microdia", sizeof(cap->name));
623 cap->type = VID_TYPE_CAPTURE;
624 cap->channels = 1;
625 cap->audios = 0;
627 switch (dev->webcam_type) {
628 case MICRODIA_SXGA:
629 cap->minwidth = microdia_image_sizes[MICRODIA_80x60].x;
630 cap->minheight = microdia_image_sizes[MICRODIA_80x60].y;
631 cap->maxwidth = microdia_image_sizes[MICRODIA_1280x1024].x;
632 cap->maxheight = microdia_image_sizes[MICRODIA_1280x1024].y;
633 break;
635 case MICRODIA_VGA:
636 cap->minwidth = microdia_image_sizes[MICRODIA_80x60].x;
637 cap->minheight = microdia_image_sizes[MICRODIA_80x60].y;
638 cap->maxwidth = microdia_image_sizes[MICRODIA_640x480].x;
639 cap->maxheight = microdia_image_sizes[MICRODIA_640x480].y;
640 break;
643 break;
645 case VIDIOCGCHAN:
647 struct video_channel *v = arg;
649 UDIA_DEBUG("VIDIOCGCHAN\n");
651 if (v->channel != 0)
652 return -EINVAL;
654 v->flags = 0;
655 v->tuners = 0;
656 v->type = VIDEO_TYPE_CAMERA;
657 strcpy(v->name, "Webcam");
659 break;
661 case VIDIOCSCHAN:
663 struct video_channel *v = arg;
665 UDIA_DEBUG("VIDIOCSCHAN\n");
667 if (v->channel != 0)
668 return -EINVAL;
670 break;
672 case VIDIOCGPICT:
674 struct video_picture *p = arg;
676 UDIA_DEBUG("VIDIOCGPICT\n");
678 p->brightness = dev->vsettings.brightness;
679 p->contrast = dev->vsettings.contrast;
680 p->whiteness = dev->vsettings.whiteness;
681 p->colour = dev->vsettings.colour;
682 p->depth = dev->vsettings.depth;
683 p->palette = dev->vsettings.palette;
684 p->hue = dev->vsettings.hue;
685 //p->exposure = dev->vsettings.exposure;
687 switch (dev->vsettings.palette) {
688 case MICRODIA_PALETTE_I420:
689 p->palette = VIDEO_PALETTE_YUV420P;
690 break;
692 case MICRODIA_PALETTE_BGR24:
693 p->palette = VIDEO_PALETTE_RGB24;
694 break;
696 case MICRODIA_PALETTE_BGR32:
697 p->palette = VIDEO_PALETTE_RGB32;
698 break;
700 case MICRODIA_PALETTE_UYVY:
701 p->palette = VIDEO_PALETTE_UYVY;
702 break;
704 case MICRODIA_PALETTE_YUYV:
705 p->palette = VIDEO_PALETTE_YUYV;
706 break;
709 break;
711 case VIDIOCSPICT:
713 struct video_picture *p = arg;
715 UDIA_DEBUG("VIDIOCSPICT\n");
717 dev->vsettings.brightness = p->brightness;
718 dev->vsettings.contrast = p->contrast;
719 dev->vsettings.whiteness = p->whiteness;
720 dev->vsettings.colour = p->colour;
721 dev->vsettings.hue = p->hue;
722 //dev->vsettings.exposure = p->exposure;
723 //dev->vsettings.gamma = p->gamma;
725 if (p->palette && p->palette != dev->vsettings.palette) {
726 switch (p->palette) {
727 case VIDEO_PALETTE_YUV420P:
728 dev->vsettings.depth = 12;
729 dev->vsettings.palette = MICRODIA_PALETTE_I420;
730 break;
732 case VIDEO_PALETTE_RGB24:
733 //Add by Boris Borisov patch from Brian Johnson
734 if(dev->webcam_model == MICRODIA_6270
735 || dev->webcam_model == MICRODIA_627B)
736 return -EINVAL;
737 dev->vsettings.depth = 24;
738 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
739 break;
741 /*case VIDEO_PALETTE_RGB32:
742 dev->vsettings.depth = 32;
743 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
744 break;
746 case VIDEO_PALETTE_UYVY:
747 dev->vsettings.depth = 16;
748 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
749 break;
751 case VIDEO_PALETTE_YUYV:
752 dev->vsettings.depth = 16;
753 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
754 break;
756 default:
757 return -EINVAL;
761 dev_microdia_camera_settings(dev);
763 UDIA_DEBUG("VIDIOCSPICT done\n");
765 break;
767 case VIDIOCGWIN:
769 struct video_window *vw = arg;
771 UDIA_DEBUG("VIDIOCGWIN\n");
773 vw->x = 0;
774 vw->y = 0;
775 vw->width = dev->view.x;
776 vw->height = dev->view.y;
777 vw->chromakey = 0;
779 break;
781 case VIDIOCSWIN:
783 struct video_window *vw = arg;
785 UDIA_DEBUG("VIDIOCSWIN\n");
787 UDIA_DEBUG("Set x=%d, y=%d\n", vw->x, vw->y);
788 UDIA_DEBUG("Set width=%d, height=%d\n", vw->width, vw->height);
789 UDIA_DEBUG("Flags = %X\n", vw->flags);
791 // Stop the video stream
792 dev_microdia_stop_stream(dev);
794 // ISOC and URB cleanup
795 usb_microdia_isoc_cleanup(dev);
797 // Switch off the camera
798 dev_microdia_camera_off(dev);
800 // dev_microdia_camera_asleep(dev);
802 // Select the new video mode
803 if (v4l_microdia_select_video_mode(dev, vw->width, vw->height)) {
804 UDIA_ERROR("Select video mode failed !\n");
805 return -EAGAIN;
808 // Clear the buffers
809 microdia_clear_buffers(dev);
811 // Initialize the device
812 dev_microdia_init_camera(dev);
813 dev_microdia_camera_on(dev);
815 // ISOC and URB init
816 usb_microdia_isoc_init(dev);
818 // Re-start the stream
819 dev_microdia_start_stream(dev);
821 // Video settings
822 dev_microdia_camera_settings(dev);
824 break;
826 case VIDIOCGFBUF:
828 struct video_buffer *vb = arg;
830 UDIA_DEBUG("VIDIOCGFBUF\n");
832 memset(vb, 0, sizeof(*vb));
834 break;
836 case VIDIOCGMBUF:
838 int i;
839 struct video_mbuf *vm = arg;
841 UDIA_DEBUG("VIDIOCGMBUF\n");
843 memset(vm, 0, sizeof(*vm));
845 vm->size = dev->nbuffers * dev->len_per_image;
846 vm->frames = dev->nbuffers;
848 for (i=0; i<dev->nbuffers; i++)
849 vm->offsets[i] = i * dev->len_per_image;
851 break;
853 case VIDIOCMCAPTURE:
855 struct video_mmap *vm = arg;
857 UDIA_DEBUG("VIDIOCMCAPTURE format=%d\n", vm->format);
859 if (vm->frame < 0 || vm->frame >= dev->nbuffers)
860 return -EINVAL;
862 if (vm->format) {
863 switch (vm->format) {
864 case VIDEO_PALETTE_YUV420P:
865 break;
867 case VIDEO_PALETTE_RGB24:
868 break;
870 /*case VIDEO_PALETTE_RGB32:
871 break;
873 case VIDEO_PALETTE_UYVY:
874 break;
876 case VIDEO_PALETTE_YUYV:
877 break;
879 default:
880 return -EINVAL;
884 if ((vm->width != dev->view.x) || (vm->height != dev->view.y))
885 return -EAGAIN;
887 if (dev->image_used[vm->frame])
888 return -EBUSY;
890 dev->image_used[vm->frame] = 1;
892 UDIA_DEBUG("VIDIOCMCAPTURE done\n");
894 break;
896 case VIDIOCSYNC:
898 int ret;
899 int *mbuf = arg;
901 UDIA_DEBUG("VIDIOCSYNC\n");
903 if (*mbuf < 0 || *mbuf >= dev->nbuffers)
904 return -EINVAL;
906 if (dev->image_used[*mbuf] == 0)
907 return -EINVAL;
909 add_wait_queue(&dev->wait_frame, &wait);
911 while (dev->full_frames == NULL) {
912 if (dev->error_status) {
913 remove_wait_queue(&dev->wait_frame, &wait);
914 set_current_state(TASK_RUNNING);
915 return -dev->error_status;
918 if (signal_pending(current)) {
919 remove_wait_queue(&dev->wait_frame, &wait);
920 set_current_state(TASK_RUNNING);
921 return -ERESTARTSYS;
924 schedule();
925 set_current_state(TASK_INTERRUPTIBLE);
928 remove_wait_queue(&dev->wait_frame, &wait);
929 set_current_state(TASK_RUNNING);
931 UDIA_DEBUG("VIDIOCSYNC: frame ready\n");
933 dev->fill_image = *mbuf;
935 ret = microdia_handle_frame(dev);
937 if (ret != 0)
938 UDIA_ERROR("VIDIOCSYNC error !\n");
940 dev->image_used[*mbuf] = 0;
942 break;
944 case VIDIOCGAUDIO:
945 UDIA_DEBUG("VIDIOCGAUDIO\n");
946 return -EINVAL;
947 break;
949 case VIDIOCSAUDIO:
950 UDIA_DEBUG("VIDIOCSAUDIO\n");
951 return -EINVAL;
952 break;
954 case VIDIOCGUNIT:
956 struct video_unit *vu = arg;
958 vu->video = dev->vdev->minor & 0x3f;
959 vu->audio = -1;
960 vu->vbi = -1;
961 vu->radio = -1;
962 vu->teletext = -1;
964 break;
967 // Video 4 Linux v2
969 case VIDIOC_QUERYCAP:
971 struct v4l2_capability *cap = arg;
973 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
975 memset(cap, 0, sizeof(*cap));
976 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
978 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
979 cap->version = (__u32) DRIVER_VERSION_NUM, strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
981 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
982 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
984 break;
986 case VIDIOC_ENUMINPUT:
988 struct v4l2_input *i = arg;
990 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", i->index);
992 if (i->index)
993 return -EINVAL;
995 strlcpy(i->name, "Webcam", sizeof(i->name));
996 i->type = V4L2_INPUT_TYPE_CAMERA;
998 break;
1000 case VIDIOC_G_INPUT:
1002 struct v4l2_input *i = arg;
1004 UDIA_DEBUG("GET INPUT %d\n", i->index);
1006 if (i->index)
1007 return -EINVAL;
1009 break;
1011 case VIDIOC_S_INPUT:
1013 struct v4l2_input *i = arg;
1015 UDIA_DEBUG("SET INPUT %d\n", i->index);
1017 if (i->index != 0)
1018 return -EINVAL;
1020 break;
1022 case VIDIOC_QUERYCTRL:
1024 int i;
1025 int nbr;
1026 struct v4l2_queryctrl *c = arg;
1028 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", c->id);
1030 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
1032 for (i=0; i<nbr; i++) {
1033 if (microdia_controls[i].id == c->id) {
1034 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
1035 memcpy(c, &microdia_controls[i], sizeof(struct v4l2_queryctrl));
1036 break;
1040 if (i >= nbr)
1041 return -EINVAL;
1043 break;
1045 case VIDIOC_G_CTRL:
1047 struct v4l2_control *c = arg;
1049 UDIA_DEBUG("GET CTRL id=%d\n", c->id);
1051 switch (c->id) {
1052 case V4L2_CID_BRIGHTNESS:
1053 c->value = dev->vsettings.brightness;
1054 break;
1056 case V4L2_CID_EXPOSURE:
1057 c->value = dev->vsettings.exposure;
1058 break;
1060 case V4L2_CID_WHITENESS:
1061 c->value = dev->vsettings.whiteness;
1062 break;
1064 case V4L2_CID_SATURATION:
1065 c->value = dev->vsettings.colour;
1066 break;
1068 case V4L2_CID_CONTRAST:
1069 c->value = dev->vsettings.contrast;
1070 break;
1072 default:
1073 return -EINVAL;
1076 break;
1078 case VIDIOC_S_CTRL:
1080 struct v4l2_control *c = arg;
1082 UDIA_DEBUG("SET CTRL id=%d value=%d\n", c->id, c->value);
1084 switch (c->id) {
1085 case V4L2_CID_BRIGHTNESS:
1086 dev->vsettings.brightness = (0xff00 & c->value);
1087 dev_microdia_camera_set_brightness(dev);
1088 break;
1090 case V4L2_CID_WHITENESS:
1091 dev->vsettings.whiteness = (0xff00 & c->value);
1092 dev_microdia_camera_set_gamma(dev);
1093 break;
1095 /*case V4L2_CID_SATURATION:
1096 dev->vsettings.colour = (0xff00 & c->value);
1097 break;*/
1098 case V4L2_CID_EXPOSURE:
1099 dev->vsettings.exposure = (0xff00 & c->value);
1100 dev_microdia_camera_set_exposure(dev);
1101 break;
1103 case V4L2_CID_CONTRAST:
1104 dev->vsettings.contrast = (0xff00 & c->value);
1105 dev_microdia_camera_set_contrast(dev);
1106 break;
1108 default:
1109 return -EINVAL;
1112 // dev_microdia_camera_settings(dev);
1114 break;
1116 case VIDIOC_ENUM_FMT:
1118 int index;
1119 struct v4l2_fmtdesc *fmtd = arg;
1121 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd->index);
1123 if (fmtd->index != 0)
1124 return -EINVAL;
1126 index = fmtd->index;
1128 memset(fmtd, 0, sizeof(*fmtd));
1130 fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1131 fmtd->index = index;
1133 switch (index) {
1134 case 0:
1135 fmtd->flags = 0;
1136 fmtd->pixelformat = V4L2_PIX_FMT_YUV420;
1137 strcpy(fmtd->description, "i420");
1138 break;
1139 /*fmtd->flags = 0;
1140 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1142 strcpy(fmtd->description, "rgb24");
1143 break;*/
1145 case 1:
1146 fmtd->flags = 0;
1147 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1149 strcpy(fmtd->description, "bgr24");
1150 break;
1152 /*case 2:
1153 fmtd->flags = 0;
1154 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1156 strcpy(fmtd->description, "bgr24");
1157 break;
1159 case 3:
1160 fmtd->flags = 0;
1161 fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
1163 strcpy(fmtd->description, "bgr32");
1164 break;
1166 case 4:
1167 fmtd->flags = 0;
1168 fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
1170 strcpy(fmtd->description, "uyvy");
1171 break;
1173 case 5:
1174 fmtd->flags = 0;
1175 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1177 strcpy(fmtd->description, "yuyv");
1178 break;*/
1180 default:
1181 return -EINVAL;
1184 break;
1186 case VIDIOC_G_FMT:
1188 struct v4l2_format *fmtd = arg;
1189 struct v4l2_pix_format pix_format;
1191 UDIA_DEBUG("GET FMT %d\n", fmtd->type);
1193 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1194 return -EINVAL;
1196 pix_format.width = dev->view.x;
1197 pix_format.height = dev->view.y;
1198 pix_format.field = V4L2_FIELD_NONE;
1199 pix_format.colorspace = V4L2_COLORSPACE_SRGB;
1200 pix_format.priv = 0;
1202 switch (dev->vsettings.palette) {
1203 case MICRODIA_PALETTE_I420:
1204 pix_format.pixelformat = V4L2_PIX_FMT_YUV420;
1205 pix_format.sizeimage = pix_format.width * pix_format.height +
1206 (pix_format.width * pix_format.height) / 2;
1207 case MICRODIA_PALETTE_BGR24:
1208 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1209 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1210 pix_format.bytesperline = 3 * pix_format.width;
1211 break;
1213 /*case MICRODIA_PALETTE_RGB32:
1214 pix_format.pixelformat = V4L2_PIX_FMT_RGB32;
1215 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1216 pix_format.bytesperline = 4 * pix_format.width;
1217 break;
1219 case MICRODIA_PALETTE_BGR24:
1220 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1221 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1222 pix_format.bytesperline = 3 * pix_format.width;
1223 break;
1225 case MICRODIA_PALETTE_BGR32:
1226 pix_format.pixelformat = V4L2_PIX_FMT_BGR32;
1227 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1228 pix_format.bytesperline = 4 * pix_format.width;
1229 break;
1231 case MICRODIA_PALETTE_UYVY:
1232 pix_format.pixelformat = V4L2_PIX_FMT_UYVY;
1233 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1234 pix_format.bytesperline = 2 * pix_format.width;
1235 break;
1237 case MICRODIA_PALETTE_YUYV:
1238 pix_format.pixelformat = V4L2_PIX_FMT_YUYV;
1239 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1240 pix_format.bytesperline = 2 * pix_format.width;
1241 break;
1245 memcpy(&(fmtd->fmt.pix), &pix_format, sizeof(pix_format));
1247 break;
1249 case VIDIOC_TRY_FMT:
1251 struct v4l2_format *fmtd = arg;
1253 UDIA_DEBUG("TRY FMT %d\n", fmtd->type);
1255 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1256 return -EINVAL;
1258 switch (fmtd->fmt.pix.pixelformat) {
1259 case V4L2_PIX_FMT_BGR24:
1260 //Add by Boris Borisov patch by Brian Jhonson
1261 if(dev->webcam_model == MICRODIA_6270 ||
1262 dev->webcam_model == MICRODIA_627B)
1263 return -EINVAL;
1264 /*case V4L2_PIX_FMT_BGR24:*/
1265 dev->vsettings.depth = 24;
1266 break;
1268 /*case V4L2_PIX_FMT_RGB32:
1269 case V4L2_PIX_FMT_BGR32:
1270 dev->vsettings.depth = 32;
1271 break;
1273 case V4L2_PIX_FMT_UYVY:
1274 case V4L2_PIX_FMT_YUYV:
1275 dev->vsettings.depth = 16;
1276 break;
1278 case V4L2_PIX_FMT_YUV420:
1279 dev->vsettings.depth = 12;
1280 break;
1282 default:
1283 return -EINVAL;
1286 switch (dev->webcam_type) {
1287 case MICRODIA_SXGA:
1288 if (fmtd->fmt.pix.width > microdia_image_sizes[MICRODIA_NBR_SIZES-1].x)
1289 fmtd->fmt.pix.width = microdia_image_sizes[MICRODIA_NBR_SIZES-1].x;
1290 else if (fmtd->fmt.pix.width < microdia_image_sizes[0].x)
1291 fmtd->fmt.pix.width = microdia_image_sizes[0].x;
1293 if (fmtd->fmt.pix.height > microdia_image_sizes[MICRODIA_NBR_SIZES-1].y)
1294 fmtd->fmt.pix.height = microdia_image_sizes[MICRODIA_NBR_SIZES-1].y;
1295 else if (fmtd->fmt.pix.height < microdia_image_sizes[0].y)
1296 fmtd->fmt.pix.height = microdia_image_sizes[0].y;
1297 break;
1299 case MICRODIA_VGA:
1300 if (fmtd->fmt.pix.width > microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].x)
1301 fmtd->fmt.pix.width = microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].x;
1302 else if (fmtd->fmt.pix.width < microdia_image_sizes[0].x)
1303 fmtd->fmt.pix.width = microdia_image_sizes[0].x;
1305 if (fmtd->fmt.pix.height > microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].y)
1306 fmtd->fmt.pix.height = microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].y;
1307 else if (fmtd->fmt.pix.height < microdia_image_sizes[0].y)
1308 fmtd->fmt.pix.height = microdia_image_sizes[0].y;
1309 break;
1313 break;
1315 case VIDIOC_S_FMT:
1317 struct v4l2_format *fmtd = arg;
1319 UDIA_DEBUG("SET FMT %d : %d\n", fmtd->type, fmtd->fmt.pix.pixelformat);
1321 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1322 return -EINVAL;
1324 switch (fmtd->fmt.pix.pixelformat) {
1325 case V4L2_PIX_FMT_YUV420:
1326 dev->vsettings.depth = 12;
1327 dev->vsettings.palette = MICRODIA_PALETTE_I420;
1328 break;
1330 case V4L2_PIX_FMT_BGR24:
1331 dev->vsettings.depth = 24;
1332 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1333 break;
1335 /*case V4L2_PIX_FMT_RGB32:
1336 dev->vsettings.depth = 32;
1337 dev->vsettings.palette = MICRODIA_PALETTE_RGB32;
1338 break;
1340 case V4L2_PIX_FMT_BGR24:
1341 dev->vsettings.depth = 24;
1342 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1343 break;
1345 case V4L2_PIX_FMT_BGR32:
1346 dev->vsettings.depth = 32;
1347 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
1348 break;
1350 case V4L2_PIX_FMT_UYVY:
1351 dev->vsettings.depth = 16;
1352 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
1353 break;
1355 case V4L2_PIX_FMT_YUYV:
1356 dev->vsettings.depth = 16;
1357 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
1358 break;
1360 default:
1361 break;
1362 return -EINVAL;
1365 UDIA_DEBUG("Set width=%d, height=%d\n", fmtd->fmt.pix.width, fmtd->fmt.pix.height);
1367 // Stop the video stream
1368 dev_microdia_stop_stream(dev);
1370 // ISOC and URB cleanup
1371 usb_microdia_isoc_cleanup(dev);
1373 // Switch off the camera
1374 dev_microdia_camera_off(dev);
1376 // dev_microdia_camera_asleep(dev);
1378 // Select the new video mode
1379 if (v4l_microdia_select_video_mode(dev, fmtd->fmt.pix.width, fmtd->fmt.pix.height)) {
1380 UDIA_ERROR("Select video mode failed !\n");
1381 return -EAGAIN;
1384 // Clear the buffers
1385 microdia_clear_buffers(dev);
1387 // Initialize the device
1388 dev_microdia_init_camera(dev);
1389 dev_microdia_camera_on(dev);
1391 // ISOC and URB init
1392 usb_microdia_isoc_init(dev);
1394 // Re-start the stream
1395 dev_microdia_start_stream(dev);
1397 // Video settings
1398 dev_microdia_camera_settings(dev);
1400 break;
1402 case VIDIOC_QUERYSTD:
1404 UDIA_DEBUG("QUERY STD\n");
1405 return -EINVAL;
1407 break;
1409 case VIDIOC_G_STD:
1411 v4l2_std_id *std = arg;
1413 UDIA_DEBUG("GET STD\n");
1415 *std = V4L2_STD_UNKNOWN;
1417 break;
1419 case VIDIOC_S_STD:
1421 v4l2_std_id *std = arg;
1423 UDIA_DEBUG("SET STD\n");
1425 if (*std != V4L2_STD_UNKNOWN)
1426 return -EINVAL;
1428 break;
1430 case VIDIOC_ENUMSTD:
1432 struct v4l2_standard *std = arg;
1434 UDIA_DEBUG("VIDIOC_ENUMSTD\n");
1436 if (std->index != 0)
1437 return -EINVAL;
1439 std->id = V4L2_STD_UNKNOWN;
1440 strncpy(std->name, "webcam", sizeof(std->name));
1442 break;
1445 case VIDIOC_REQBUFS:
1447 int nbuffers;
1448 struct v4l2_requestbuffers *rb = arg;
1450 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1451 return -EINVAL;
1453 if (rb->memory != V4L2_MEMORY_MMAP)
1454 return -EINVAL;
1456 nbuffers = rb->count;
1458 if (nbuffers < 2)
1459 nbuffers = 2;
1460 else if (nbuffers > dev->nbuffers)
1461 nbuffers = dev->nbuffers;
1463 rb->count = dev->nbuffers;
1465 break;
1467 case VIDIOC_QUERYBUF:
1469 int index;
1470 struct v4l2_buffer *buf = arg;
1472 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buf->index, dev->nbuffers);
1474 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1475 return -EINVAL;
1477 if (buf->memory != V4L2_MEMORY_MMAP)
1478 return -EINVAL;
1480 index = buf->index;
1482 if (index < 0 || index >= dev->nbuffers)
1483 return -EINVAL;
1485 memset(buf, 0, sizeof(struct v4l2_buffer));
1487 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1488 buf->index = index;
1489 buf->m.offset = index * dev->len_per_image;
1490 buf->bytesused = dev->view_size;
1491 buf->field = V4L2_FIELD_NONE;
1492 buf->memory = V4L2_MEMORY_MMAP;
1493 buf->length = dev->len_per_image;
1495 break;
1497 case VIDIOC_QBUF:
1499 struct v4l2_buffer *buf = arg;
1501 UDIA_DEBUG("VIDIOC_QBUF\n");
1503 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1504 return -EINVAL;
1506 if (buf->memory != V4L2_MEMORY_MMAP)
1507 return -EINVAL;
1509 if (buf->index < 0 || buf->index >= dev->nbuffers)
1510 return -EINVAL;
1512 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1513 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1515 break;
1517 case VIDIOC_DQBUF:
1519 int ret;
1520 struct v4l2_buffer *buf = arg;
1522 UDIA_DEBUG("VIDIOC_DQBUF\n");
1524 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1525 return -EINVAL;
1527 add_wait_queue(&dev->wait_frame, &wait);
1529 while (dev->full_frames == NULL) {
1530 if (dev->error_status) {
1531 remove_wait_queue(&dev->wait_frame, &wait);
1532 set_current_state(TASK_RUNNING);
1534 return -dev->error_status;
1537 if (signal_pending(current)) {
1538 remove_wait_queue(&dev->wait_frame, &wait);
1539 set_current_state(TASK_RUNNING);
1541 return -ERESTARTSYS;
1543 if (fp->f_flags & O_NONBLOCK) {
1544 remove_wait_queue(&dev->wait_frame, &wait);
1545 set_current_state(TASK_RUNNING);
1547 return -EAGAIN;
1549 schedule();
1550 set_current_state(TASK_INTERRUPTIBLE);
1553 remove_wait_queue(&dev->wait_frame, &wait);
1554 set_current_state(TASK_RUNNING);
1556 UDIA_DEBUG("VIDIOC_DQBUF : frame ready.\n");
1558 ret = microdia_handle_frame(dev);
1560 if (ret)
1561 return -EFAULT;
1563 buf->index = dev->fill_image;
1564 buf->bytesused = dev->view_size;
1565 buf->flags = V4L2_BUF_FLAG_MAPPED;
1566 buf->field = V4L2_FIELD_NONE;
1567 do_gettimeofday(&buf->timestamp);
1568 buf->sequence = 0;
1569 buf->memory = V4L2_MEMORY_MMAP;
1570 buf->m.offset = dev->fill_image * dev->len_per_image;
1571 buf->length = buf->bytesused;
1573 microdia_next_image(dev);
1575 break;
1577 case VIDIOC_STREAMON:
1579 UDIA_DEBUG("VIDIOC_STREAMON\n");
1581 usb_microdia_isoc_init(dev);
1583 break;
1585 case VIDIOC_STREAMOFF:
1587 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1589 usb_microdia_isoc_cleanup(dev);
1591 break;
1593 case VIDIOC_G_PARM:
1595 struct v4l2_streamparm *sp = arg;
1597 UDIA_DEBUG("GET PARM %d\n", sp->type);
1599 if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1600 return -EINVAL;
1602 sp->parm.capture.capability = 0;
1603 sp->parm.capture.capturemode = 0;
1604 sp->parm.capture.timeperframe.numerator = 1;
1605 sp->parm.capture.timeperframe.denominator = 30;
1606 sp->parm.capture.readbuffers = 2;
1607 sp->parm.capture.extendedmode = 0;
1609 break;
1612 case VIDIOC_G_AUDIO:
1613 UDIA_DEBUG("GET AUDIO\n");
1614 return -EINVAL;
1615 break;
1617 case VIDIOC_S_AUDIO:
1618 UDIA_DEBUG("SET AUDIO\n");
1619 return -EINVAL;
1620 break;
1622 case VIDIOC_S_TUNER:
1623 UDIA_DEBUG("SET TUNER\n");
1624 return -EINVAL;
1625 break;
1627 case VIDIOC_G_FBUF:
1628 case VIDIOC_S_FBUF:
1629 case VIDIOC_OVERLAY:
1630 return -EINVAL;
1631 break;
1633 case VIDIOC_G_TUNER:
1634 case VIDIOC_G_FREQUENCY:
1635 case VIDIOC_S_FREQUENCY:
1636 return -EINVAL;
1637 break;
1639 case VIDIOC_QUERYMENU:
1640 return -EINVAL;
1641 break;
1643 case VIDIOC_CROPCAP:
1645 struct v4l2_cropcap cc;
1647 cc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1648 cc.pixelaspect.numerator = 1;
1649 cc.pixelaspect.denominator = 1;
1650 cc.bounds.top = 0;
1651 cc.bounds.left = 0;
1652 cc.bounds.width = 640;
1653 cc.bounds.height = 480;
1654 cc.defrect.top = 0;
1655 cc.defrect.left = 0;
1656 cc.defrect.width = 640;
1657 cc.defrect.height = 480;
1659 memcpy(arg, &cc, sizeof(cc));
1661 break;
1663 default:
1664 UDIA_DEBUG("IOCTL unknown !\n");
1665 return -ENOIOCTLCMD;
1668 return 0;
1672 /**
1673 * @param inode Inode pointer
1674 * @param fp File pointer
1675 * @param cmd Command
1676 * @param arg Arguements of the command
1678 * @returns 0 if all is OK
1680 * @brief Manage IOCTL
1682 * This function permits to manage all the IOCTL from the application.
1684 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1685 unsigned int cmd, unsigned long arg)
1687 int err;
1688 struct usb_microdia *dev;
1689 struct video_device *vdev;
1691 vdev = video_devdata(fp);
1692 dev = video_get_drvdata(video_devdata(fp));
1694 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1696 if (dev == NULL)
1697 return -EFAULT;
1699 if (vdev == NULL)
1700 return -EFAULT;
1702 err = v4l_microdia_do_ioctl(inode, fp, cmd, (void __user *) arg);
1704 return err;
1708 /**
1709 * @param dev Device structure
1711 * @returns 0 if all is OK
1713 * @brief Register the video device
1715 * This function permits to register the USB device to the video device.
1717 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1719 int err;
1721 strcpy(dev->vdev->name, DRIVER_DESC);
1723 dev->vdev->dev = &dev->interface->dev;
1724 dev->vdev->owner = THIS_MODULE;
1725 dev->vdev->type = VID_TYPE_CAPTURE;
1726 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1727 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1728 #endif
1729 dev->vdev->fops = &v4l_microdia_fops;
1730 dev->vdev->release = video_device_release;
1731 dev->vdev->minor = -1;
1733 video_set_drvdata(dev->vdev, dev);
1735 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1737 if (err)
1738 UDIA_ERROR("Video register fail !\n");
1739 else
1740 UDIA_INFO("Microdia USB2.0 Camera is now controlling video device /dev/video%d\n", dev->vdev->minor);
1742 return err;
1746 /**
1747 * @param dev Device structure
1749 * @returns 0 if all is OK
1751 * @brief Unregister the video device
1753 * This function permits to unregister the video device.
1755 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1757 UDIA_INFO("Microdia USB2.0 Camera release resources video device /dev/video%d\n", dev->vdev->minor);
1759 video_set_drvdata(dev->vdev, NULL);
1760 video_unregister_device(dev->vdev);
1762 return 0;
1767 * @var v4l_microdia_fops
1769 * This variable contains some callback
1771 static struct file_operations v4l_microdia_fops = {
1772 .owner = THIS_MODULE,
1773 .open = v4l_microdia_open,
1774 .release = v4l_microdia_release,
1775 .read = v4l_microdia_read,
1776 .poll = v4l_microdia_poll,
1777 .mmap = v4l_microdia_mmap,
1778 .ioctl = v4l_microdia_ioctl,
1779 #ifdef CONFIG_COMPAT
1780 .compat_ioctl = v4l_compat_ioctl32,
1781 #endif
1782 .llseek = no_llseek