Makefile now supports rmmod option.
[microdia.git] / microdia-v4l.c
blobfc7d48b26ec26b275129310f29d121749272e932
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,
93 .id = V4L2_CID_SATURATION,
94 .type = V4L2_CTRL_TYPE_INTEGER,
95 .name = "Saturation",
96 .minimum = 0,
97 .maximum = 0xff00,
98 .step = 1,
99 .default_value = 0x7f00,
102 .id = V4L2_CID_CONTRAST,
103 .type = V4L2_CTRL_TYPE_INTEGER,
104 .name = "Contrast",
105 .minimum = 0,
106 .maximum = 0xff00,
107 .step = 1,
108 .default_value = 0x7f00,
113 /**
114 * @param dev
115 * @param width Width of wished resolution
116 * @param height Height of wished resolution
118 * @returns 0 if all is OK
120 * @brief Select a video mode
122 * This function permits to check and select a video mode.
124 int v4l_microdia_select_video_mode(struct usb_microdia *dev, int width, int height)
126 int i;
127 int find;
130 // Check width and height
131 // Notice : this test is usefull for the Kopete application !
132 printk( KERN_INFO "Changing resolution to %d by %d\n", width, height);
134 // Driver can't build an image smaller than the minimal resolution !
135 if ((width < microdia_image_sizes[0].x)
136 || (height < microdia_image_sizes[0].y)) {
137 width = microdia_image_sizes[0].x;
138 height = microdia_image_sizes[0].y;
141 // Driver can't build an image bigger than the maximal resolution !
142 switch (dev->webcam_type) {
143 case MICRODIA_SXGA:
144 if ((width > microdia_image_sizes[MICRODIA_NBR_SIZES-1].x)
145 || (height > microdia_image_sizes[MICRODIA_NBR_SIZES-1].y)) {
146 width = microdia_image_sizes[MICRODIA_NBR_SIZES-1].x;
147 height = microdia_image_sizes[MICRODIA_NBR_SIZES-1].y;
149 break;
151 case MICRODIA_VGA:
152 if ((width > microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].x)
153 || (height > microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].y)) {
154 width = microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].x;
155 height = microdia_image_sizes[MICRODIA_NBR_SIZES-3-1].y;
157 break;
159 default:
160 return -1;
164 // Seek the best resolution
165 switch (dev->webcam_type) {
166 case MICRODIA_SXGA:
167 for (i=0, find=0; i<MICRODIA_NBR_SIZES; i++) {
168 if (microdia_image_sizes[i].x <= width && microdia_image_sizes[i].y <= height)
169 find = i;
171 break;
173 case MICRODIA_VGA:
174 for (i=0, find=0; i<MICRODIA_NBR_SIZES-3; i++) {
175 if (microdia_image_sizes[i].x <= width && microdia_image_sizes[i].y <= height)
176 find = i;
178 break;
180 default:
181 return -1;
184 // Save the new resolution
185 dev->resolution = find;
187 UDIA_DEBUG("Set mode %d [%dx%d]\n", dev->resolution,
188 microdia_image_sizes[dev->resolution].x, microdia_image_sizes[dev->resolution].y);
190 // Save the new size
191 dev->view.x = width;
192 dev->view.y = height;
195 // Calculate the frame size
196 switch (dev->resolution) {
197 case MICRODIA_80x60:
198 /*case MICRODIA_128x96:*/
199 case MICRODIA_160x120:
200 /*case MICRODIA_213x160:*/
201 case MICRODIA_320x240:
202 case MICRODIA_640x480:
203 dev->image.x = microdia_image_sizes[MICRODIA_640x480].x;
204 dev->image.y = microdia_image_sizes[MICRODIA_640x480].y;
205 dev->frame_size = dev->image.x * dev->image.y;
206 break;
208 case MICRODIA_800x600:
209 case MICRODIA_1024x768:
210 case MICRODIA_1280x1024:
211 dev->image.x = microdia_image_sizes[MICRODIA_1280x1024].x;
212 dev->image.y = microdia_image_sizes[MICRODIA_1280x1024].y;
213 dev->frame_size = dev->image.x * dev->image.y;
214 break;
218 // Calculate the image size
219 switch (dev->vsettings.palette) {
220 case MICRODIA_PALETTE_RGB24:
221 case MICRODIA_PALETTE_BGR24:
222 dev->view_size = 3 * dev->view.x * dev->view.y;
223 break;
225 case MICRODIA_PALETTE_RGB32:
226 case MICRODIA_PALETTE_BGR32:
227 dev->view_size = 4 * dev->view.x * dev->view.y;
228 break;
230 case MICRODIA_PALETTE_UYVY:
231 case MICRODIA_PALETTE_YUYV:
232 dev->view_size = 2 * dev->view.x * dev->view.y;
233 break;
234 case MICRODIA_PALETTE_I420:
235 dev->view_size = dev->view.x * dev->view.y +
236 (dev->view.x * dev->view.y) / 2;
239 return 0;
243 /**
244 * @param inode Pointer on an inode
245 * @param fp File pointer
247 * @returns 0 if all is OK
249 * @brief Open the video device
251 * This function permits to open a video device (/dev/videoX)
253 static int v4l_microdia_open(struct inode *inode, struct file *fp)
255 int err;
257 struct usb_microdia *dev;
258 struct video_device *vdev;
260 vdev = video_devdata(fp);
261 dev = video_get_drvdata(video_devdata(fp));
263 if (dev == NULL) {
264 UDIA_ERROR("Device not initialized !!!\n");
265 BUG();
268 if (dev->vopen) {
269 UDIA_DEBUG("Device is busy, someone is using the device\n");
270 return -EBUSY;
273 // Allocate memory
274 err = microdia_allocate_buffers(dev);
276 if (err < 0) {
277 UDIA_ERROR("Failed to allocate buffer memory !\n");
278 return err;
281 // Reset buffers and parameters
282 microdia_reset_buffers(dev);
284 // Settings
285 dev->error_status = 0;
286 dev->visoc_errors = 0;
287 dev->vframes_error = 0;
288 dev->vframes_dumped = 0;
289 dev->vsettings.hue = 0xffff;
290 dev->vsettings.depth = 24;
291 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
293 // Select the resolution by default
294 v4l_microdia_select_video_mode(dev, 640, 480);
296 // Initialize the device
297 dev_microdia_init_camera(dev);
298 dev_microdia_camera_on(dev);
300 // Init Isoc and URB
301 err = usb_microdia_isoc_init(dev);
303 if (err) {
304 UDIA_ERROR("Failed to init ISOC stuff !\n");
305 usb_microdia_isoc_cleanup(dev);
306 microdia_free_buffers(dev);
307 return err;
310 // Start the video stream
311 dev_microdia_start_stream(dev);
313 dev->vopen++;
314 fp->private_data = vdev;
316 return 0;
320 /**
321 * @param inode Pointer on inode
322 * @param fp File pointer
324 * @returns 0 if all is OK
326 * @brief Release an opened file.
328 * This function permits to release an opened file with the 'open' method.
330 static int v4l_microdia_release(struct inode *inode, struct file *fp)
332 struct usb_microdia *dev;
333 struct video_device *vdev;
335 vdev = video_devdata(fp);
336 dev = video_get_drvdata(video_devdata(fp));
338 if (dev->vopen == 0)
339 UDIA_ERROR("v4l_release called on closed device\n");
341 // Stop the video stream
342 dev_microdia_stop_stream(dev);
344 // ISOC and URB cleanup
345 usb_microdia_isoc_cleanup(dev);
347 // Free memory
348 microdia_free_buffers(dev);
350 // Switch off the camera
351 dev_microdia_camera_off(dev);
353 // dev_microdia_camera_asleep(dev);
355 dev->vopen--;
357 return 0;
361 /**
362 * @param fp File pointer
364 * @retval buf Buffer in user space
365 * @retval count
366 * @retval f_pos
368 * @returns Count value
370 * @brief Read the video device
372 * This function is called by the application is reading the video device.
374 static ssize_t v4l_microdia_read(struct file *fp, char __user *buf,
375 size_t count, loff_t *f_pos)
377 int noblock = fp->f_flags & O_NONBLOCK;
379 struct usb_microdia *dev;
380 struct video_device *vdev;
382 int bytes_to_read;
383 void *image_buffer_addr;
385 DECLARE_WAITQUEUE(wait, current);
387 vdev = video_devdata(fp);
388 dev = video_get_drvdata(video_devdata(fp));
390 UDIA_STREAM("Read vdev=0x%p, buf=0x%p, count=%zd\n", vdev, buf, count);
392 if (dev == NULL)
393 return -EFAULT;
395 if (vdev == NULL)
396 return -EFAULT;
398 if (dev->image_read_pos == 0) {
399 add_wait_queue(&dev->wait_frame, &wait);
401 while (dev->full_frames == NULL) {
402 if (dev->error_status) {
403 remove_wait_queue(&dev->wait_frame, &wait);
404 set_current_state(TASK_RUNNING);
405 return -dev->error_status ;
408 if (noblock) {
409 remove_wait_queue(&dev->wait_frame, &wait);
410 set_current_state(TASK_RUNNING);
411 return -EWOULDBLOCK;
414 if (signal_pending(current)) {
415 remove_wait_queue(&dev->wait_frame, &wait);
416 set_current_state(TASK_RUNNING);
417 return -ERESTARTSYS;
420 schedule();
421 set_current_state(TASK_INTERRUPTIBLE);
424 remove_wait_queue(&dev->wait_frame, &wait);
425 set_current_state(TASK_RUNNING);
427 if (microdia_handle_frame(dev))
428 return -EFAULT;
431 bytes_to_read = dev->view_size;
433 if (count + dev->image_read_pos > bytes_to_read)
434 count = bytes_to_read - dev->image_read_pos;
436 image_buffer_addr = dev->image_data;
437 image_buffer_addr += dev->images[dev->fill_image].offset;
438 image_buffer_addr += dev->image_read_pos;
440 if (copy_to_user(buf, image_buffer_addr, count))
441 return -EFAULT;
443 dev->image_read_pos += count;
445 if (dev->image_read_pos >= bytes_to_read) {
446 dev->image_read_pos = 0;
447 microdia_next_image(dev);
450 return count;
454 /**
455 * @param fp File pointer
456 * @param wait
458 * @returns 0 if all is OK
460 * @brief Polling function
462 static unsigned int v4l_microdia_poll(struct file *fp, poll_table *wait)
464 struct usb_microdia *dev;
465 struct video_device *vdev;
467 vdev = video_devdata(fp);
468 dev = video_get_drvdata(video_devdata(fp));
470 UDIA_STREAM("Poll\n");
472 if (vdev == NULL)
473 return -EFAULT;
475 if (dev == NULL)
476 return -EFAULT;
478 poll_wait(fp, &dev->wait_frame, wait);
480 if (dev->error_status)
481 return POLLERR;
483 if (dev->full_frames != NULL)
484 return (POLLIN | POLLRDNORM);
486 return 0;
490 /**
491 * @param fp File pointer
492 * @param vma VMA structure
494 * @returns 0 if all is OK
496 * @brief Memory map
498 * This function permits to map a memory space.
500 static int v4l_microdia_mmap(struct file *fp, struct vm_area_struct *vma)
502 unsigned int i;
504 unsigned long size;
505 unsigned long start;
506 unsigned long pos;
507 unsigned long page;
509 struct usb_microdia *dev;
511 struct video_device *vdev;
513 vdev = video_devdata(fp);
514 dev = video_get_drvdata(video_devdata(fp));
516 UDIA_STREAM("mmap\n");
518 start = vma->vm_start;
519 size = vma->vm_end - vma->vm_start;
521 // Find the buffer for this mapping...
522 for (i=0; i<dev->nbuffers; i++) {
523 pos = dev->images[i].offset;
525 if ((pos >> PAGE_SHIFT) == vma->vm_pgoff)
526 break;
529 // If no buffer found !
530 if (i == MICRODIA_MAX_IMAGES) {
531 UDIA_ERROR("mmap no buffer found !\n");
532 return -EINVAL;
535 if (i == 0) {
536 unsigned long total_size;
538 total_size = dev->nbuffers * dev->len_per_image;
540 if (size != dev->len_per_image && size != total_size)
541 return -EINVAL;
543 else if (size > dev->len_per_image)
544 return -EINVAL;
546 vma->vm_flags |= VM_IO;
548 pos = (unsigned long) dev->image_data;
550 while (size > 0) {
551 page = vmalloc_to_pfn((void *) pos);
553 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
554 return -EAGAIN;
556 start += PAGE_SIZE;
557 pos += PAGE_SIZE;
559 if (size > PAGE_SIZE)
560 size -= PAGE_SIZE;
561 else
562 size = 0;
565 return 0;
569 /**
570 * @param inode Inode pointer
571 * @param fp File pointer
572 * @param cmd Command
573 * @param arg Arguments of the command
575 * @returns 0 if all is OK
577 * @brief Manage IOCTL
579 * This function permits to manage all the IOCTL from the application.
581 static int v4l_microdia_do_ioctl(struct inode *inode, struct file *fp,
582 unsigned int cmd, void __user *arg)
584 struct usb_microdia *dev;
585 struct video_device *vdev;
587 DECLARE_WAITQUEUE(wait, current);
589 vdev = video_devdata(fp);
590 dev = video_get_drvdata(video_devdata(fp));
592 #if (CONFIG_MICRODIA_DEBUG == 1)
593 v4l_printk_ioctl(cmd);
594 #endif
596 switch (cmd) {
597 // Video 4 Linux v1
599 case VIDIOCGCAP:
601 struct video_capability *cap = arg;
603 UDIA_DEBUG("VIDIOCGCAP\n");
605 memset(cap, 0, sizeof(*cap));
606 strlcpy(cap->name, "microdia", sizeof(cap->name));
607 cap->type = VID_TYPE_CAPTURE;
608 cap->channels = 1;
609 cap->audios = 0;
611 switch (dev->webcam_type) {
612 case MICRODIA_SXGA:
613 cap->minwidth = microdia_image_sizes[MICRODIA_80x60].x;
614 cap->minheight = microdia_image_sizes[MICRODIA_80x60].y;
615 cap->maxwidth = microdia_image_sizes[MICRODIA_1280x1024].x;
616 cap->maxheight = microdia_image_sizes[MICRODIA_1280x1024].y;
617 break;
619 case MICRODIA_VGA:
620 cap->minwidth = microdia_image_sizes[MICRODIA_80x60].x;
621 cap->minheight = microdia_image_sizes[MICRODIA_80x60].y;
622 cap->maxwidth = microdia_image_sizes[MICRODIA_640x480].x;
623 cap->maxheight = microdia_image_sizes[MICRODIA_640x480].y;
624 break;
627 break;
629 case VIDIOCGCHAN:
631 struct video_channel *v = arg;
633 UDIA_DEBUG("VIDIOCGCHAN\n");
635 if (v->channel != 0)
636 return -EINVAL;
638 v->flags = 0;
639 v->tuners = 0;
640 v->type = VIDEO_TYPE_CAMERA;
641 strcpy(v->name, "Webcam");
643 break;
645 case VIDIOCSCHAN:
647 struct video_channel *v = arg;
649 UDIA_DEBUG("VIDIOCSCHAN\n");
651 if (v->channel != 0)
652 return -EINVAL;
654 break;
656 case VIDIOCGPICT:
658 struct video_picture *p = arg;
660 UDIA_DEBUG("VIDIOCGPICT\n");
662 p->brightness = dev->vsettings.brightness;
663 p->contrast = dev->vsettings.contrast;
664 p->whiteness = dev->vsettings.whiteness;
665 p->colour = dev->vsettings.colour;
666 p->depth = dev->vsettings.depth;
667 p->palette = dev->vsettings.palette;
668 p->hue = dev->vsettings.hue;
670 switch (dev->vsettings.palette) {
671 case MICRODIA_PALETTE_I420:
672 p->palette = VIDEO_PALETTE_YUV420P;
673 break;
675 case MICRODIA_PALETTE_BGR24:
676 p->palette = VIDEO_PALETTE_RGB24;
677 break;
679 case MICRODIA_PALETTE_BGR32:
680 p->palette = VIDEO_PALETTE_RGB32;
681 break;
683 case MICRODIA_PALETTE_UYVY:
684 p->palette = VIDEO_PALETTE_UYVY;
685 break;
687 case MICRODIA_PALETTE_YUYV:
688 p->palette = VIDEO_PALETTE_YUYV;
689 break;
692 break;
694 case VIDIOCSPICT:
696 struct video_picture *p = arg;
698 UDIA_DEBUG("VIDIOCSPICT\n");
700 dev->vsettings.brightness = p->brightness;
701 dev->vsettings.contrast = p->contrast;
702 dev->vsettings.whiteness = p->whiteness;
703 dev->vsettings.colour = p->colour;
704 dev->vsettings.hue = p->hue;
706 if (p->palette && p->palette != dev->vsettings.palette) {
707 switch (p->palette) {
708 case VIDEO_PALETTE_YUV420P:
709 dev->vsettings.depth = 12;
710 dev->vsettings.palette = MICRODIA_PALETTE_I420;
711 break;
713 case VIDEO_PALETTE_RGB24:
714 dev->vsettings.depth = 24;
715 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
716 break;
718 /*case VIDEO_PALETTE_RGB32:
719 dev->vsettings.depth = 32;
720 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
721 break;
723 case VIDEO_PALETTE_UYVY:
724 dev->vsettings.depth = 16;
725 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
726 break;
728 case VIDEO_PALETTE_YUYV:
729 dev->vsettings.depth = 16;
730 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
731 break;
733 default:
734 return -EINVAL;
738 // dev_microdia_camera_settings(dev);
740 UDIA_DEBUG("VIDIOCSPICT done\n");
742 break;
744 case VIDIOCGWIN:
746 struct video_window *vw = arg;
748 UDIA_DEBUG("VIDIOCGWIN\n");
750 vw->x = 0;
751 vw->y = 0;
752 vw->width = dev->view.x;
753 vw->height = dev->view.y;
754 vw->chromakey = 0;
756 break;
758 case VIDIOCSWIN:
760 struct video_window *vw = arg;
762 UDIA_DEBUG("VIDIOCSWIN\n");
764 UDIA_DEBUG("Set x=%d, y=%d\n", vw->x, vw->y);
765 UDIA_DEBUG("Set width=%d, height=%d\n", vw->width, vw->height);
766 UDIA_DEBUG("Flags = %X\n", vw->flags);
768 // Stop the video stream
769 dev_microdia_stop_stream(dev);
771 // ISOC and URB cleanup
772 usb_microdia_isoc_cleanup(dev);
774 // Switch off the camera
775 dev_microdia_camera_off(dev);
777 // dev_microdia_camera_asleep(dev);
779 // Select the new video mode
780 if (v4l_microdia_select_video_mode(dev, vw->width, vw->height)) {
781 UDIA_ERROR("Select video mode failed !\n");
782 return -EAGAIN;
785 // Clear the buffers
786 microdia_clear_buffers(dev);
788 // Initialize the device
789 dev_microdia_init_camera(dev);
790 dev_microdia_camera_on(dev);
792 // ISOC and URB init
793 usb_microdia_isoc_init(dev);
795 // Re-start the stream
796 dev_microdia_start_stream(dev);
798 // Video settings
799 // dev_microdia_camera_settings(dev);
801 break;
803 case VIDIOCGFBUF:
805 struct video_buffer *vb = arg;
807 UDIA_DEBUG("VIDIOCGFBUF\n");
809 memset(vb, 0, sizeof(*vb));
811 break;
813 case VIDIOCGMBUF:
815 int i;
816 struct video_mbuf *vm = arg;
818 UDIA_DEBUG("VIDIOCGMBUF\n");
820 memset(vm, 0, sizeof(*vm));
822 vm->size = dev->nbuffers * dev->len_per_image;
823 vm->frames = dev->nbuffers;
825 for (i=0; i<dev->nbuffers; i++)
826 vm->offsets[i] = i * dev->len_per_image;
828 break;
830 case VIDIOCMCAPTURE:
832 struct video_mmap *vm = arg;
834 UDIA_DEBUG("VIDIOCMCAPTURE format=%d\n", vm->format);
836 if (vm->frame < 0 || vm->frame >= dev->nbuffers)
837 return -EINVAL;
839 if (vm->format) {
840 switch (vm->format) {
841 case VIDEO_PALETTE_YUV420P:
842 break;
844 case VIDEO_PALETTE_RGB24:
845 break;
847 /*case VIDEO_PALETTE_RGB32:
848 break;
850 case VIDEO_PALETTE_UYVY:
851 break;
853 case VIDEO_PALETTE_YUYV:
854 break;
856 default:
857 return -EINVAL;
861 if ((vm->width != dev->view.x) || (vm->height != dev->view.y))
862 return -EAGAIN;
864 if (dev->image_used[vm->frame])
865 return -EBUSY;
867 dev->image_used[vm->frame] = 1;
869 UDIA_DEBUG("VIDIOCMCAPTURE done\n");
871 break;
873 case VIDIOCSYNC:
875 int ret;
876 int *mbuf = arg;
878 UDIA_DEBUG("VIDIOCSYNC\n");
880 if (*mbuf < 0 || *mbuf >= dev->nbuffers)
881 return -EINVAL;
883 if (dev->image_used[*mbuf] == 0)
884 return -EINVAL;
886 add_wait_queue(&dev->wait_frame, &wait);
888 while (dev->full_frames == NULL) {
889 if (dev->error_status) {
890 remove_wait_queue(&dev->wait_frame, &wait);
891 set_current_state(TASK_RUNNING);
892 return -dev->error_status;
895 if (signal_pending(current)) {
896 remove_wait_queue(&dev->wait_frame, &wait);
897 set_current_state(TASK_RUNNING);
898 return -ERESTARTSYS;
901 schedule();
902 set_current_state(TASK_INTERRUPTIBLE);
905 remove_wait_queue(&dev->wait_frame, &wait);
906 set_current_state(TASK_RUNNING);
908 UDIA_DEBUG("VIDIOCSYNC: frame ready\n");
910 dev->fill_image = *mbuf;
912 ret = microdia_handle_frame(dev);
914 if (ret != 0)
915 UDIA_ERROR("VIDIOCSYNC error !\n");
917 dev->image_used[*mbuf] = 0;
919 break;
921 case VIDIOCGAUDIO:
922 UDIA_DEBUG("VIDIOCGAUDIO\n");
923 return -EINVAL;
924 break;
926 case VIDIOCSAUDIO:
927 UDIA_DEBUG("VIDIOCSAUDIO\n");
928 return -EINVAL;
929 break;
931 case VIDIOCGUNIT:
933 struct video_unit *vu = arg;
935 vu->video = dev->vdev->minor & 0x3f;
936 vu->audio = -1;
937 vu->vbi = -1;
938 vu->radio = -1;
939 vu->teletext = -1;
941 break;
944 // Video 4 Linux v2
946 case VIDIOC_QUERYCAP:
948 struct v4l2_capability *cap = arg;
950 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
952 memset(cap, 0, sizeof(*cap));
953 strlcpy(cap->driver, "microdia", sizeof(cap->driver));
955 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
956 cap->version = (__u32) DRIVER_VERSION_NUM, strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
958 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
959 strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
961 break;
963 case VIDIOC_ENUMINPUT:
965 struct v4l2_input *i = arg;
967 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", i->index);
969 if (i->index)
970 return -EINVAL;
972 strlcpy(i->name, "Webcam", sizeof(i->name));
973 i->type = V4L2_INPUT_TYPE_CAMERA;
975 break;
977 case VIDIOC_G_INPUT:
979 struct v4l2_input *i = arg;
981 UDIA_DEBUG("GET INPUT %d\n", i->index);
983 if (i->index)
984 return -EINVAL;
986 break;
988 case VIDIOC_S_INPUT:
990 struct v4l2_input *i = arg;
992 UDIA_DEBUG("SET INPUT %d\n", i->index);
994 if (i->index != 0)
995 return -EINVAL;
997 break;
999 case VIDIOC_QUERYCTRL:
1001 int i;
1002 int nbr;
1003 struct v4l2_queryctrl *c = arg;
1005 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", c->id);
1007 nbr = sizeof(microdia_controls)/sizeof(struct v4l2_queryctrl);
1009 for (i=0; i<nbr; i++) {
1010 if (microdia_controls[i].id == c->id) {
1011 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
1012 memcpy(c, &microdia_controls[i], sizeof(struct v4l2_queryctrl));
1013 break;
1017 if (i >= nbr)
1018 return -EINVAL;
1020 break;
1022 case VIDIOC_G_CTRL:
1024 struct v4l2_control *c = arg;
1026 UDIA_DEBUG("GET CTRL id=%d\n", c->id);
1028 switch (c->id) {
1029 case V4L2_CID_BRIGHTNESS:
1030 c->value = dev->vsettings.brightness;
1031 break;
1033 case V4L2_CID_WHITENESS:
1034 c->value = dev->vsettings.whiteness;
1035 break;
1037 case V4L2_CID_SATURATION:
1038 c->value = dev->vsettings.colour;
1039 break;
1041 case V4L2_CID_CONTRAST:
1042 c->value = dev->vsettings.contrast;
1043 break;
1045 default:
1046 return -EINVAL;
1049 break;
1051 case VIDIOC_S_CTRL:
1053 struct v4l2_control *c = arg;
1055 UDIA_DEBUG("SET CTRL id=%d value=%d\n", c->id, c->value);
1057 switch (c->id) {
1058 case V4L2_CID_BRIGHTNESS:
1059 dev->vsettings.brightness = (0xff00 & c->value);
1060 break;
1062 case V4L2_CID_WHITENESS:
1063 dev->vsettings.whiteness = (0xff00 & c->value);
1064 break;
1066 case V4L2_CID_SATURATION:
1067 dev->vsettings.colour = (0xff00 & c->value);
1068 break;
1070 case V4L2_CID_CONTRAST:
1071 dev->vsettings.contrast = (0xff00 & c->value);
1072 break;
1074 default:
1075 return -EINVAL;
1078 // dev_microdia_camera_settings(dev);
1080 break;
1082 case VIDIOC_ENUM_FMT:
1084 int index;
1085 struct v4l2_fmtdesc *fmtd = arg;
1087 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd->index);
1089 if (fmtd->index != 0)
1090 return -EINVAL;
1092 index = fmtd->index;
1094 memset(fmtd, 0, sizeof(*fmtd));
1096 fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1097 fmtd->index = index;
1099 switch (index) {
1100 case 0:
1101 fmtd->flags = 0;
1102 fmtd->pixelformat = V4L2_PIX_FMT_YUV420;
1103 strcpy(fmtd->description, "i420");
1104 break;
1105 /*fmtd->flags = 0;
1106 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1108 strcpy(fmtd->description, "rgb24");
1109 break;*/
1111 case 1:
1112 fmtd->flags = 0;
1113 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1115 strcpy(fmtd->description, "bgr24");
1116 break;
1118 /*case 2:
1119 fmtd->flags = 0;
1120 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1122 strcpy(fmtd->description, "bgr24");
1123 break;
1125 case 3:
1126 fmtd->flags = 0;
1127 fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
1129 strcpy(fmtd->description, "bgr32");
1130 break;
1132 case 4:
1133 fmtd->flags = 0;
1134 fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
1136 strcpy(fmtd->description, "uyvy");
1137 break;
1139 case 5:
1140 fmtd->flags = 0;
1141 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1143 strcpy(fmtd->description, "yuyv");
1144 break;*/
1146 default:
1147 return -EINVAL;
1150 break;
1152 case VIDIOC_G_FMT:
1154 struct v4l2_format *fmtd = arg;
1155 struct v4l2_pix_format pix_format;
1157 UDIA_DEBUG("GET FMT %d\n", fmtd->type);
1159 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1160 return -EINVAL;
1162 pix_format.width = dev->view.x;
1163 pix_format.height = dev->view.y;
1164 pix_format.field = V4L2_FIELD_NONE;
1165 pix_format.colorspace = V4L2_COLORSPACE_SRGB;
1166 pix_format.priv = 0;
1168 switch (dev->vsettings.palette) {
1169 case MICRODIA_PALETTE_I420:
1170 pix_format.pixelformat = V4L2_PIX_FMT_YUV420;
1171 pix_format.sizeimage = pix_format.width * pix_format.height +
1172 (pix_format.width * pix_format.height) / 2;
1173 case MICRODIA_PALETTE_BGR24:
1174 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1175 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1176 pix_format.bytesperline = 3 * pix_format.width;
1177 break;
1179 /*case MICRODIA_PALETTE_RGB32:
1180 pix_format.pixelformat = V4L2_PIX_FMT_RGB32;
1181 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1182 pix_format.bytesperline = 4 * pix_format.width;
1183 break;
1185 case MICRODIA_PALETTE_BGR24:
1186 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1187 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1188 pix_format.bytesperline = 3 * pix_format.width;
1189 break;
1191 case MICRODIA_PALETTE_BGR32:
1192 pix_format.pixelformat = V4L2_PIX_FMT_BGR32;
1193 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1194 pix_format.bytesperline = 4 * pix_format.width;
1195 break;
1197 case MICRODIA_PALETTE_UYVY:
1198 pix_format.pixelformat = V4L2_PIX_FMT_UYVY;
1199 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1200 pix_format.bytesperline = 2 * pix_format.width;
1201 break;
1203 case MICRODIA_PALETTE_YUYV:
1204 pix_format.pixelformat = V4L2_PIX_FMT_YUYV;
1205 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1206 pix_format.bytesperline = 2 * pix_format.width;
1207 break;
1211 memcpy(&(fmtd->fmt.pix), &pix_format, sizeof(pix_format));
1213 break;
1215 case VIDIOC_TRY_FMT:
1217 struct v4l2_format *fmtd = arg;
1219 UDIA_DEBUG("TRY FMT %d\n", fmtd->type);
1221 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1222 return -EINVAL;
1224 switch (fmtd->fmt.pix.pixelformat) {
1225 case V4L2_PIX_FMT_BGR24:
1226 /*case V4L2_PIX_FMT_BGR24:*/
1227 dev->vsettings.depth = 24;
1228 break;
1230 /*case V4L2_PIX_FMT_RGB32:
1231 case V4L2_PIX_FMT_BGR32:
1232 dev->vsettings.depth = 32;
1233 break;
1235 case V4L2_PIX_FMT_UYVY:
1236 case V4L2_PIX_FMT_YUYV:
1237 dev->vsettings.depth = 16;
1238 break;
1240 case V4L2_PIX_FMT_YUV420:
1241 dev->vsettings.depth = 12;
1242 break;
1244 default:
1245 return -EINVAL;
1248 switch (dev->webcam_type) {
1249 case MICRODIA_SXGA:
1250 if (fmtd->fmt.pix.width > microdia_image_sizes[MICRODIA_NBR_SIZES-1].x)
1251 fmtd->fmt.pix.width = microdia_image_sizes[MICRODIA_NBR_SIZES-1].x;
1252 else if (fmtd->fmt.pix.width < microdia_image_sizes[0].x)
1253 fmtd->fmt.pix.width = microdia_image_sizes[0].x;
1255 if (fmtd->fmt.pix.height > microdia_image_sizes[MICRODIA_NBR_SIZES-1].y)
1256 fmtd->fmt.pix.height = microdia_image_sizes[MICRODIA_NBR_SIZES-1].y;
1257 else if (fmtd->fmt.pix.height < microdia_image_sizes[0].y)
1258 fmtd->fmt.pix.height = microdia_image_sizes[0].y;
1259 break;
1261 case MICRODIA_VGA:
1262 if (fmtd->fmt.pix.width > microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].x)
1263 fmtd->fmt.pix.width = microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].x;
1264 else if (fmtd->fmt.pix.width < microdia_image_sizes[0].x)
1265 fmtd->fmt.pix.width = microdia_image_sizes[0].x;
1267 if (fmtd->fmt.pix.height > microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].y)
1268 fmtd->fmt.pix.height = microdia_image_sizes[MICRODIA_NBR_SIZES-1-3].y;
1269 else if (fmtd->fmt.pix.height < microdia_image_sizes[0].y)
1270 fmtd->fmt.pix.height = microdia_image_sizes[0].y;
1271 break;
1275 break;
1277 case VIDIOC_S_FMT:
1279 struct v4l2_format *fmtd = arg;
1281 UDIA_DEBUG("SET FMT %d : %d\n", fmtd->type, fmtd->fmt.pix.pixelformat);
1283 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1284 return -EINVAL;
1286 switch (fmtd->fmt.pix.pixelformat) {
1287 case V4L2_PIX_FMT_YUV420:
1288 dev->vsettings.depth = 12;
1289 dev->vsettings.palette = MICRODIA_PALETTE_I420;
1290 break;
1292 case V4L2_PIX_FMT_BGR24:
1293 dev->vsettings.depth = 24;
1294 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1295 break;
1297 /*case V4L2_PIX_FMT_RGB32:
1298 dev->vsettings.depth = 32;
1299 dev->vsettings.palette = MICRODIA_PALETTE_RGB32;
1300 break;
1302 case V4L2_PIX_FMT_BGR24:
1303 dev->vsettings.depth = 24;
1304 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1305 break;
1307 case V4L2_PIX_FMT_BGR32:
1308 dev->vsettings.depth = 32;
1309 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
1310 break;
1312 case V4L2_PIX_FMT_UYVY:
1313 dev->vsettings.depth = 16;
1314 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
1315 break;
1317 case V4L2_PIX_FMT_YUYV:
1318 dev->vsettings.depth = 16;
1319 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
1320 break;
1322 default:
1323 break;
1324 return -EINVAL;
1327 UDIA_DEBUG("Set width=%d, height=%d\n", fmtd->fmt.pix.width, fmtd->fmt.pix.height);
1329 // Stop the video stream
1330 dev_microdia_stop_stream(dev);
1332 // ISOC and URB cleanup
1333 usb_microdia_isoc_cleanup(dev);
1335 // Switch off the camera
1336 dev_microdia_camera_off(dev);
1338 // dev_microdia_camera_asleep(dev);
1340 // Select the new video mode
1341 if (v4l_microdia_select_video_mode(dev, fmtd->fmt.pix.width, fmtd->fmt.pix.height)) {
1342 UDIA_ERROR("Select video mode failed !\n");
1343 return -EAGAIN;
1346 // Clear the buffers
1347 microdia_clear_buffers(dev);
1349 // Initialize the device
1350 dev_microdia_init_camera(dev);
1351 dev_microdia_camera_on(dev);
1353 // ISOC and URB init
1354 usb_microdia_isoc_init(dev);
1356 // Re-start the stream
1357 dev_microdia_start_stream(dev);
1359 // Video settings
1360 // dev_microdia_camera_settings(dev);
1362 break;
1364 case VIDIOC_QUERYSTD:
1366 UDIA_DEBUG("QUERY STD\n");
1367 return -EINVAL;
1369 break;
1371 case VIDIOC_G_STD:
1373 v4l2_std_id *std = arg;
1375 UDIA_DEBUG("GET STD\n");
1377 *std = V4L2_STD_UNKNOWN;
1379 break;
1381 case VIDIOC_S_STD:
1383 v4l2_std_id *std = arg;
1385 UDIA_DEBUG("SET STD\n");
1387 if (*std != V4L2_STD_UNKNOWN)
1388 return -EINVAL;
1390 break;
1392 case VIDIOC_ENUMSTD:
1394 struct v4l2_standard *std = arg;
1396 UDIA_DEBUG("VIDIOC_ENUMSTD\n");
1398 if (std->index != 0)
1399 return -EINVAL;
1401 std->id = V4L2_STD_UNKNOWN;
1402 strncpy(std->name, "webcam", sizeof(std->name));
1404 break;
1407 case VIDIOC_REQBUFS:
1409 int nbuffers;
1410 struct v4l2_requestbuffers *rb = arg;
1412 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1413 return -EINVAL;
1415 if (rb->memory != V4L2_MEMORY_MMAP)
1416 return -EINVAL;
1418 nbuffers = rb->count;
1420 if (nbuffers < 2)
1421 nbuffers = 2;
1422 else if (nbuffers > dev->nbuffers)
1423 nbuffers = dev->nbuffers;
1425 rb->count = dev->nbuffers;
1427 break;
1429 case VIDIOC_QUERYBUF:
1431 int index;
1432 struct v4l2_buffer *buf = arg;
1434 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buf->index, dev->nbuffers);
1436 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1437 return -EINVAL;
1439 if (buf->memory != V4L2_MEMORY_MMAP)
1440 return -EINVAL;
1442 index = buf->index;
1444 if (index < 0 || index >= dev->nbuffers)
1445 return -EINVAL;
1447 memset(buf, 0, sizeof(struct v4l2_buffer));
1449 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1450 buf->index = index;
1451 buf->m.offset = index * dev->len_per_image;
1452 buf->bytesused = dev->view_size;
1453 buf->field = V4L2_FIELD_NONE;
1454 buf->memory = V4L2_MEMORY_MMAP;
1455 buf->length = dev->len_per_image;
1457 break;
1459 case VIDIOC_QBUF:
1461 struct v4l2_buffer *buf = arg;
1463 UDIA_DEBUG("VIDIOC_QBUF\n");
1465 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1466 return -EINVAL;
1468 if (buf->memory != V4L2_MEMORY_MMAP)
1469 return -EINVAL;
1471 if (buf->index < 0 || buf->index >= dev->nbuffers)
1472 return -EINVAL;
1474 buf->flags |= V4L2_BUF_FLAG_QUEUED;
1475 buf->flags &= ~V4L2_BUF_FLAG_DONE;
1477 break;
1479 case VIDIOC_DQBUF:
1481 int ret;
1482 struct v4l2_buffer *buf = arg;
1484 UDIA_DEBUG("VIDIOC_DQBUF\n");
1486 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1487 return -EINVAL;
1489 add_wait_queue(&dev->wait_frame, &wait);
1491 while (dev->full_frames == NULL) {
1492 if (dev->error_status) {
1493 remove_wait_queue(&dev->wait_frame, &wait);
1494 set_current_state(TASK_RUNNING);
1496 return -dev->error_status;
1499 if (signal_pending(current)) {
1500 remove_wait_queue(&dev->wait_frame, &wait);
1501 set_current_state(TASK_RUNNING);
1503 return -ERESTARTSYS;
1506 schedule();
1507 set_current_state(TASK_INTERRUPTIBLE);
1510 remove_wait_queue(&dev->wait_frame, &wait);
1511 set_current_state(TASK_RUNNING);
1513 UDIA_DEBUG("VIDIOC_DQBUF : frame ready.\n");
1515 ret = microdia_handle_frame(dev);
1517 if (ret)
1518 return -EFAULT;
1520 buf->index = dev->fill_image;
1521 buf->bytesused = dev->view_size;
1522 buf->flags = V4L2_BUF_FLAG_MAPPED;
1523 buf->field = V4L2_FIELD_NONE;
1524 do_gettimeofday(&buf->timestamp);
1525 buf->sequence = 0;
1526 buf->memory = V4L2_MEMORY_MMAP;
1527 buf->m.offset = dev->fill_image * dev->len_per_image;
1528 buf->length = buf->bytesused;
1530 microdia_next_image(dev);
1532 break;
1534 case VIDIOC_STREAMON:
1536 UDIA_DEBUG("VIDIOC_STREAMON\n");
1538 usb_microdia_isoc_init(dev);
1540 break;
1542 case VIDIOC_STREAMOFF:
1544 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1546 usb_microdia_isoc_cleanup(dev);
1548 break;
1550 case VIDIOC_G_PARM:
1552 struct v4l2_streamparm *sp = arg;
1554 UDIA_DEBUG("GET PARM %d\n", sp->type);
1556 if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1557 return -EINVAL;
1559 sp->parm.capture.capability = 0;
1560 sp->parm.capture.capturemode = 0;
1561 sp->parm.capture.timeperframe.numerator = 1;
1562 sp->parm.capture.timeperframe.denominator = 30;
1563 sp->parm.capture.readbuffers = 2;
1564 sp->parm.capture.extendedmode = 0;
1566 break;
1569 case VIDIOC_G_AUDIO:
1570 UDIA_DEBUG("GET AUDIO\n");
1571 return -EINVAL;
1572 break;
1574 case VIDIOC_S_AUDIO:
1575 UDIA_DEBUG("SET AUDIO\n");
1576 return -EINVAL;
1577 break;
1579 case VIDIOC_S_TUNER:
1580 UDIA_DEBUG("SET TUNER\n");
1581 return -EINVAL;
1582 break;
1584 case VIDIOC_G_FBUF:
1585 case VIDIOC_S_FBUF:
1586 case VIDIOC_OVERLAY:
1587 return -EINVAL;
1588 break;
1590 case VIDIOC_G_TUNER:
1591 case VIDIOC_G_FREQUENCY:
1592 case VIDIOC_S_FREQUENCY:
1593 return -EINVAL;
1594 break;
1596 case VIDIOC_QUERYMENU:
1597 return -EINVAL;
1598 break;
1600 case VIDIOC_CROPCAP:
1602 struct v4l2_cropcap cc;
1604 cc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1605 cc.pixelaspect.numerator = 1;
1606 cc.pixelaspect.denominator = 1;
1607 cc.bounds.top = 0;
1608 cc.bounds.left = 0;
1609 cc.bounds.width = 640;
1610 cc.bounds.height = 480;
1611 cc.defrect.top = 0;
1612 cc.defrect.left = 0;
1613 cc.defrect.width = 640;
1614 cc.defrect.height = 480;
1616 memcpy(arg, &cc, sizeof(cc));
1618 break;
1620 default:
1621 UDIA_DEBUG("IOCTL unknown !\n");
1622 return -ENOIOCTLCMD;
1625 return 0;
1629 /**
1630 * @param inode Inode pointer
1631 * @param fp File pointer
1632 * @param cmd Command
1633 * @param arg Arguements of the command
1635 * @returns 0 if all is OK
1637 * @brief Manage IOCTL
1639 * This function permits to manage all the IOCTL from the application.
1641 static int v4l_microdia_ioctl(struct inode *inode, struct file *fp,
1642 unsigned int cmd, unsigned long arg)
1644 int err;
1645 struct usb_microdia *dev;
1646 struct video_device *vdev;
1648 vdev = video_devdata(fp);
1649 dev = video_get_drvdata(video_devdata(fp));
1651 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd);
1653 if (dev == NULL)
1654 return -EFAULT;
1656 if (vdev == NULL)
1657 return -EFAULT;
1659 err = v4l_microdia_do_ioctl(inode, fp, cmd, (void __user *) arg);
1661 return err;
1665 /**
1666 * @param dev Device structure
1668 * @returns 0 if all is OK
1670 * @brief Register the video device
1672 * This function permits to register the USB device to the video device.
1674 int v4l_microdia_register_video_device(struct usb_microdia *dev)
1676 int err;
1678 strcpy(dev->vdev->name, DRIVER_DESC);
1680 dev->vdev->dev = &dev->interface->dev;
1681 dev->vdev->owner = THIS_MODULE;
1682 dev->vdev->type = VID_TYPE_CAPTURE;
1683 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1684 dev->vdev->hardware = VID_HARDWARE_MICRODIA;
1685 #endif
1686 dev->vdev->fops = &v4l_microdia_fops;
1687 dev->vdev->release = video_device_release;
1688 dev->vdev->minor = -1;
1690 video_set_drvdata(dev->vdev, dev);
1692 err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
1694 if (err)
1695 UDIA_ERROR("Video register fail !\n");
1696 else
1697 UDIA_INFO("Microdia USB2.0 Camera is now controlling video device /dev/video%d\n", dev->vdev->minor);
1699 return err;
1703 /**
1704 * @param dev Device structure
1706 * @returns 0 if all is OK
1708 * @brief Unregister the video device
1710 * This function permits to unregister the video device.
1712 int v4l_microdia_unregister_video_device(struct usb_microdia *dev)
1714 UDIA_INFO("Microdia USB2.0 Camera release resources video device /dev/video%d\n", dev->vdev->minor);
1716 video_set_drvdata(dev->vdev, NULL);
1717 video_unregister_device(dev->vdev);
1719 return 0;
1724 * @var v4l_microdia_fops
1726 * This variable contains some callback
1728 static struct file_operations v4l_microdia_fops = {
1729 .owner = THIS_MODULE,
1730 .open = v4l_microdia_open,
1731 .release = v4l_microdia_release,
1732 .read = v4l_microdia_read,
1733 .poll = v4l_microdia_poll,
1734 .mmap = v4l_microdia_mmap,
1735 .ioctl = v4l_microdia_ioctl,
1736 #ifdef CONFIG_COMPAT
1737 .compat_ioctl = v4l_compat_ioctl32,
1738 #endif
1739 .llseek = no_llseek