3 * @author Nicolas VIVIEN
7 * @brief Driver for Microdia USB video camera
9 * @note Copyright (C) Nicolas VIVIEN
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
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 * $Date: 2008-02-05 10:10:01 +0100 (mar, 05 fév 2008) $
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>
49 static struct file_operations v4l_microdia_fops
;
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
] = {
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
,
81 .default_value
= 0x7f00,
84 .id
= V4L2_CID_WHITENESS
,
85 .type
= V4L2_CTRL_TYPE_INTEGER
,
90 .default_value
= 0x7f00,
94 .id = V4L2_CID_SATURATION,
95 .type = V4L2_CTRL_TYPE_INTEGER,
100 .default_value = 0x7f00,
104 .id
= V4L2_CID_CONTRAST
,
105 .type
= V4L2_CTRL_TYPE_INTEGER
,
110 .default_value
= 0x0000,
113 .id
= V4L2_CID_EXPOSURE
,
114 .type
= V4L2_CTRL_TYPE_INTEGER
,
119 .default_value
= 0x1000,
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
)
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
) {
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
;
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
;
176 // Seek the best resolution
177 switch (dev
->webcam_type
) {
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
)
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
)
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
);
204 dev
->view
.y
= height
;
207 // Calculate the frame size
208 switch (dev
->resolution
) {
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
;
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
;
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
;
237 case MICRODIA_PALETTE_RGB32
:
238 case MICRODIA_PALETTE_BGR32
:
239 dev
->view_size
= 4 * dev
->view
.x
* dev
->view
.y
;
242 case MICRODIA_PALETTE_UYVY
:
243 case MICRODIA_PALETTE_YUYV
:
244 dev
->view_size
= 2 * dev
->view
.x
* dev
->view
.y
;
246 case MICRODIA_PALETTE_I420
:
247 dev
->view_size
= dev
->view
.x
* dev
->view
.y
+
248 (dev
->view
.x
* dev
->view
.y
) / 2;
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
)
269 struct usb_microdia
*dev
;
270 struct video_device
*vdev
;
272 vdev
= video_devdata(fp
);
273 dev
= video_get_drvdata(video_devdata(fp
));
276 UDIA_ERROR("Device not initialized !!!\n");
281 UDIA_DEBUG("Device is busy, someone is using the device\n");
286 err
= microdia_allocate_buffers(dev
);
289 UDIA_ERROR("Failed to allocate buffer memory !\n");
293 // Reset buffers and parameters
294 microdia_reset_buffers(dev
);
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
);
316 err
= usb_microdia_isoc_init(dev
);
319 UDIA_ERROR("Failed to init ISOC stuff !\n");
320 usb_microdia_isoc_cleanup(dev
);
321 microdia_free_buffers(dev
);
325 // Start the video stream
326 dev_microdia_start_stream(dev
);
327 dev_microdia_camera_settings(dev
);
330 fp
->private_data
= vdev
;
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
));
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
);
364 microdia_free_buffers(dev
);
366 // Switch off the camera
367 dev_microdia_camera_off(dev
);
369 // dev_microdia_camera_asleep(dev);
378 * @param fp File pointer
380 * @retval buf Buffer in user space
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
;
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
);
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
;
425 remove_wait_queue(&dev
->wait_frame
, &wait
);
426 set_current_state(TASK_RUNNING
);
430 if (signal_pending(current
)) {
431 remove_wait_queue(&dev
->wait_frame
, &wait
);
432 set_current_state(TASK_RUNNING
);
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
))
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
))
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
);
471 * @param fp File pointer
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");
494 poll_wait(fp
, &dev
->wait_frame
, wait
);
496 if (dev
->error_status
)
499 if (dev
->full_frames
!= NULL
)
500 return (POLLIN
| POLLRDNORM
);
507 * @param fp File pointer
508 * @param vma VMA structure
510 * @returns 0 if all is OK
514 * This function permits to map a memory space.
516 static int v4l_microdia_mmap(struct file
*fp
, struct vm_area_struct
*vma
)
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
)
545 // If no buffer found !
546 if (i
== MICRODIA_MAX_IMAGES
) {
547 UDIA_ERROR("mmap no buffer found !\n");
552 unsigned long total_size
;
554 total_size
= dev
->nbuffers
* dev
->len_per_image
;
556 if (size
!= dev
->len_per_image
&& size
!= total_size
)
559 else if (size
> dev
->len_per_image
)
562 vma
->vm_flags
|= VM_IO
;
564 pos
= (unsigned long) dev
->image_data
;
567 page
= vmalloc_to_pfn((void *) pos
);
569 if (remap_pfn_range(vma
, start
, page
, PAGE_SIZE
, PAGE_SHARED
))
575 if (size
> PAGE_SIZE
)
586 * @param inode Inode pointer
587 * @param fp File pointer
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
);
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
;
627 switch (dev
->webcam_type
) {
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
;
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
;
647 struct video_channel
*v
= arg
;
649 UDIA_DEBUG("VIDIOCGCHAN\n");
656 v
->type
= VIDEO_TYPE_CAMERA
;
657 strcpy(v
->name
, "Webcam");
663 struct video_channel
*v
= arg
;
665 UDIA_DEBUG("VIDIOCSCHAN\n");
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
;
692 case MICRODIA_PALETTE_BGR24
:
693 p
->palette
= VIDEO_PALETTE_RGB24
;
696 case MICRODIA_PALETTE_BGR32
:
697 p
->palette
= VIDEO_PALETTE_RGB32
;
700 case MICRODIA_PALETTE_UYVY
:
701 p
->palette
= VIDEO_PALETTE_UYVY
;
704 case MICRODIA_PALETTE_YUYV
:
705 p
->palette
= VIDEO_PALETTE_YUYV
;
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
;
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
)
737 dev
->vsettings
.depth
= 24;
738 dev
->vsettings
.palette
= MICRODIA_PALETTE_BGR24
;
741 /*case VIDEO_PALETTE_RGB32:
742 dev->vsettings.depth = 32;
743 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
746 case VIDEO_PALETTE_UYVY:
747 dev->vsettings.depth = 16;
748 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
751 case VIDEO_PALETTE_YUYV:
752 dev->vsettings.depth = 16;
753 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
761 dev_microdia_camera_settings(dev
);
763 UDIA_DEBUG("VIDIOCSPICT done\n");
769 struct video_window
*vw
= arg
;
771 UDIA_DEBUG("VIDIOCGWIN\n");
775 vw
->width
= dev
->view
.x
;
776 vw
->height
= dev
->view
.y
;
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");
809 microdia_clear_buffers(dev
);
811 // Initialize the device
812 dev_microdia_init_camera(dev
);
813 dev_microdia_camera_on(dev
);
816 usb_microdia_isoc_init(dev
);
818 // Re-start the stream
819 dev_microdia_start_stream(dev
);
822 dev_microdia_camera_settings(dev
);
828 struct video_buffer
*vb
= arg
;
830 UDIA_DEBUG("VIDIOCGFBUF\n");
832 memset(vb
, 0, sizeof(*vb
));
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
;
855 struct video_mmap
*vm
= arg
;
857 UDIA_DEBUG("VIDIOCMCAPTURE format=%d\n", vm
->format
);
859 if (vm
->frame
< 0 || vm
->frame
>= dev
->nbuffers
)
863 switch (vm
->format
) {
864 case VIDEO_PALETTE_YUV420P
:
867 case VIDEO_PALETTE_RGB24
:
870 /*case VIDEO_PALETTE_RGB32:
873 case VIDEO_PALETTE_UYVY:
876 case VIDEO_PALETTE_YUYV:
884 if ((vm
->width
!= dev
->view
.x
) || (vm
->height
!= dev
->view
.y
))
887 if (dev
->image_used
[vm
->frame
])
890 dev
->image_used
[vm
->frame
] = 1;
892 UDIA_DEBUG("VIDIOCMCAPTURE done\n");
901 UDIA_DEBUG("VIDIOCSYNC\n");
903 if (*mbuf
< 0 || *mbuf
>= dev
->nbuffers
)
906 if (dev
->image_used
[*mbuf
] == 0)
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
);
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
);
938 UDIA_ERROR("VIDIOCSYNC error !\n");
940 dev
->image_used
[*mbuf
] = 0;
945 UDIA_DEBUG("VIDIOCGAUDIO\n");
950 UDIA_DEBUG("VIDIOCSAUDIO\n");
956 struct video_unit
*vu
= arg
;
958 vu
->video
= dev
->vdev
->minor
& 0x3f;
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
));
986 case VIDIOC_ENUMINPUT
:
988 struct v4l2_input
*i
= arg
;
990 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", i
->index
);
995 strlcpy(i
->name
, "Webcam", sizeof(i
->name
));
996 i
->type
= V4L2_INPUT_TYPE_CAMERA
;
1000 case VIDIOC_G_INPUT
:
1002 struct v4l2_input
*i
= arg
;
1004 UDIA_DEBUG("GET INPUT %d\n", i
->index
);
1011 case VIDIOC_S_INPUT
:
1013 struct v4l2_input
*i
= arg
;
1015 UDIA_DEBUG("SET INPUT %d\n", i
->index
);
1022 case VIDIOC_QUERYCTRL
:
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
, µdia_controls
[i
], sizeof(struct v4l2_queryctrl
));
1047 struct v4l2_control
*c
= arg
;
1049 UDIA_DEBUG("GET CTRL id=%d\n", c
->id
);
1052 case V4L2_CID_BRIGHTNESS
:
1053 c
->value
= dev
->vsettings
.brightness
;
1056 case V4L2_CID_EXPOSURE
:
1057 c
->value
= dev
->vsettings
.exposure
;
1060 case V4L2_CID_WHITENESS
:
1061 c
->value
= dev
->vsettings
.whiteness
;
1064 case V4L2_CID_SATURATION:
1065 c->value = dev->vsettings.colour;
1068 case V4L2_CID_CONTRAST
:
1069 c
->value
= dev
->vsettings
.contrast
;
1080 struct v4l2_control
*c
= arg
;
1082 UDIA_DEBUG("SET CTRL id=%d value=%d\n", c
->id
, c
->value
);
1085 case V4L2_CID_BRIGHTNESS
:
1086 dev
->vsettings
.brightness
= (0xff00 & c
->value
);
1087 dev_microdia_camera_set_brightness(dev
);
1090 case V4L2_CID_WHITENESS
:
1091 dev
->vsettings
.whiteness
= (0xff00 & c
->value
);
1092 dev_microdia_camera_set_gamma(dev
);
1095 /*case V4L2_CID_SATURATION:
1096 dev->vsettings.colour = (0xff00 & c->value);
1098 case V4L2_CID_EXPOSURE
:
1099 dev
->vsettings
.exposure
= (0xff00 & c
->value
);
1100 dev_microdia_camera_set_exposure(dev
);
1103 case V4L2_CID_CONTRAST
:
1104 dev
->vsettings
.contrast
= (0xff00 & c
->value
);
1105 dev_microdia_camera_set_contrast(dev
);
1112 // dev_microdia_camera_settings(dev);
1116 case VIDIOC_ENUM_FMT
:
1119 struct v4l2_fmtdesc
*fmtd
= arg
;
1121 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd
->index
);
1123 if (fmtd
->index
!= 0)
1126 index
= fmtd
->index
;
1128 memset(fmtd
, 0, sizeof(*fmtd
));
1130 fmtd
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1131 fmtd
->index
= index
;
1136 fmtd
->pixelformat
= V4L2_PIX_FMT_YUV420
;
1137 strcpy(fmtd
->description
, "i420");
1140 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1142 strcpy(fmtd->description, "rgb24");
1147 fmtd
->pixelformat
= V4L2_PIX_FMT_BGR24
;
1149 strcpy(fmtd
->description
, "bgr24");
1154 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1156 strcpy(fmtd->description, "bgr24");
1161 fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
1163 strcpy(fmtd->description, "bgr32");
1168 fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
1170 strcpy(fmtd->description, "uyvy");
1175 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1177 strcpy(fmtd->description, "yuyv");
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
)
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
;
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;
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;
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;
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;
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;
1245 memcpy(&(fmtd
->fmt
.pix
), &pix_format
, sizeof(pix_format
));
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
)
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
)
1264 /*case V4L2_PIX_FMT_BGR24:*/
1265 dev
->vsettings
.depth
= 24;
1268 /*case V4L2_PIX_FMT_RGB32:
1269 case V4L2_PIX_FMT_BGR32:
1270 dev->vsettings.depth = 32;
1273 case V4L2_PIX_FMT_UYVY:
1274 case V4L2_PIX_FMT_YUYV:
1275 dev->vsettings.depth = 16;
1278 case V4L2_PIX_FMT_YUV420
:
1279 dev
->vsettings
.depth
= 12;
1286 switch (dev
->webcam_type
) {
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
;
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
;
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
)
1324 switch (fmtd
->fmt
.pix
.pixelformat
) {
1325 case V4L2_PIX_FMT_YUV420
:
1326 dev
->vsettings
.depth
= 12;
1327 dev
->vsettings
.palette
= MICRODIA_PALETTE_I420
;
1330 case V4L2_PIX_FMT_BGR24
:
1331 dev
->vsettings
.depth
= 24;
1332 dev
->vsettings
.palette
= MICRODIA_PALETTE_BGR24
;
1335 /*case V4L2_PIX_FMT_RGB32:
1336 dev->vsettings.depth = 32;
1337 dev->vsettings.palette = MICRODIA_PALETTE_RGB32;
1340 case V4L2_PIX_FMT_BGR24:
1341 dev->vsettings.depth = 24;
1342 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1345 case V4L2_PIX_FMT_BGR32:
1346 dev->vsettings.depth = 32;
1347 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
1350 case V4L2_PIX_FMT_UYVY:
1351 dev->vsettings.depth = 16;
1352 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
1355 case V4L2_PIX_FMT_YUYV:
1356 dev->vsettings.depth = 16;
1357 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
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");
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
);
1398 dev_microdia_camera_settings(dev
);
1402 case VIDIOC_QUERYSTD
:
1404 UDIA_DEBUG("QUERY STD\n");
1411 v4l2_std_id
*std
= arg
;
1413 UDIA_DEBUG("GET STD\n");
1415 *std
= V4L2_STD_UNKNOWN
;
1421 v4l2_std_id
*std
= arg
;
1423 UDIA_DEBUG("SET STD\n");
1425 if (*std
!= V4L2_STD_UNKNOWN
)
1430 case VIDIOC_ENUMSTD
:
1432 struct v4l2_standard
*std
= arg
;
1434 UDIA_DEBUG("VIDIOC_ENUMSTD\n");
1436 if (std
->index
!= 0)
1439 std
->id
= V4L2_STD_UNKNOWN
;
1440 strncpy(std
->name
, "webcam", sizeof(std
->name
));
1445 case VIDIOC_REQBUFS
:
1448 struct v4l2_requestbuffers
*rb
= arg
;
1450 if (rb
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1453 if (rb
->memory
!= V4L2_MEMORY_MMAP
)
1456 nbuffers
= rb
->count
;
1460 else if (nbuffers
> dev
->nbuffers
)
1461 nbuffers
= dev
->nbuffers
;
1463 rb
->count
= dev
->nbuffers
;
1467 case VIDIOC_QUERYBUF
:
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
)
1477 if (buf
->memory
!= V4L2_MEMORY_MMAP
)
1482 if (index
< 0 || index
>= dev
->nbuffers
)
1485 memset(buf
, 0, sizeof(struct v4l2_buffer
));
1487 buf
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
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
;
1499 struct v4l2_buffer
*buf
= arg
;
1501 UDIA_DEBUG("VIDIOC_QBUF\n");
1503 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1506 if (buf
->memory
!= V4L2_MEMORY_MMAP
)
1509 if (buf
->index
< 0 || buf
->index
>= dev
->nbuffers
)
1512 buf
->flags
|= V4L2_BUF_FLAG_QUEUED
;
1513 buf
->flags
&= ~V4L2_BUF_FLAG_DONE
;
1520 struct v4l2_buffer
*buf
= arg
;
1522 UDIA_DEBUG("VIDIOC_DQBUF\n");
1524 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
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
);
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
);
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
);
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
);
1577 case VIDIOC_STREAMON
:
1579 UDIA_DEBUG("VIDIOC_STREAMON\n");
1581 usb_microdia_isoc_init(dev
);
1585 case VIDIOC_STREAMOFF
:
1587 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1589 usb_microdia_isoc_cleanup(dev
);
1595 struct v4l2_streamparm
*sp
= arg
;
1597 UDIA_DEBUG("GET PARM %d\n", sp
->type
);
1599 if (sp
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
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;
1612 case VIDIOC_G_AUDIO
:
1613 UDIA_DEBUG("GET AUDIO\n");
1617 case VIDIOC_S_AUDIO
:
1618 UDIA_DEBUG("SET AUDIO\n");
1622 case VIDIOC_S_TUNER
:
1623 UDIA_DEBUG("SET TUNER\n");
1629 case VIDIOC_OVERLAY
:
1633 case VIDIOC_G_TUNER
:
1634 case VIDIOC_G_FREQUENCY
:
1635 case VIDIOC_S_FREQUENCY
:
1639 case VIDIOC_QUERYMENU
:
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;
1652 cc.bounds.width = 640;
1653 cc.bounds.height = 480;
1655 cc.defrect.left = 0;
1656 cc.defrect.width = 640;
1657 cc.defrect.height = 480;
1659 memcpy(arg, &cc, sizeof(cc));
1664 UDIA_DEBUG("IOCTL unknown !\n");
1665 return -ENOIOCTLCMD
;
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
)
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
);
1702 err
= v4l_microdia_do_ioctl(inode
, fp
, cmd
, (void __user
*) arg
);
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
)
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
;
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);
1738 UDIA_ERROR("Video register fail !\n");
1740 UDIA_INFO("Microdia USB2.0 Camera is now controlling video device /dev/video%d\n", dev
->vdev
->minor
);
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
);
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
,