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,
93 .id
= V4L2_CID_SATURATION
,
94 .type
= V4L2_CTRL_TYPE_INTEGER
,
99 .default_value
= 0x7f00,
102 .id
= V4L2_CID_CONTRAST
,
103 .type
= V4L2_CTRL_TYPE_INTEGER
,
108 .default_value
= 0x7f00,
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
)
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
) {
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
;
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
;
164 // Seek the best resolution
165 switch (dev
->webcam_type
) {
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
)
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
)
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
);
192 dev
->view
.y
= height
;
195 // Calculate the frame size
196 switch (dev
->resolution
) {
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
;
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
;
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
;
225 case MICRODIA_PALETTE_RGB32
:
226 case MICRODIA_PALETTE_BGR32
:
227 dev
->view_size
= 4 * dev
->view
.x
* dev
->view
.y
;
230 case MICRODIA_PALETTE_UYVY
:
231 case MICRODIA_PALETTE_YUYV
:
232 dev
->view_size
= 2 * dev
->view
.x
* dev
->view
.y
;
234 case MICRODIA_PALETTE_I420
:
235 dev
->view_size
= dev
->view
.x
* dev
->view
.y
+
236 (dev
->view
.x
* dev
->view
.y
) / 2;
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
)
257 struct usb_microdia
*dev
;
258 struct video_device
*vdev
;
260 vdev
= video_devdata(fp
);
261 dev
= video_get_drvdata(video_devdata(fp
));
264 UDIA_ERROR("Device not initialized !!!\n");
269 UDIA_DEBUG("Device is busy, someone is using the device\n");
274 err
= microdia_allocate_buffers(dev
);
277 UDIA_ERROR("Failed to allocate buffer memory !\n");
281 // Reset buffers and parameters
282 microdia_reset_buffers(dev
);
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
);
301 err
= usb_microdia_isoc_init(dev
);
304 UDIA_ERROR("Failed to init ISOC stuff !\n");
305 usb_microdia_isoc_cleanup(dev
);
306 microdia_free_buffers(dev
);
310 // Start the video stream
311 dev_microdia_start_stream(dev
);
314 fp
->private_data
= vdev
;
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
));
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
);
348 microdia_free_buffers(dev
);
350 // Switch off the camera
351 dev_microdia_camera_off(dev
);
353 // dev_microdia_camera_asleep(dev);
362 * @param fp File pointer
364 * @retval buf Buffer in user space
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
;
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
);
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
;
409 remove_wait_queue(&dev
->wait_frame
, &wait
);
410 set_current_state(TASK_RUNNING
);
414 if (signal_pending(current
)) {
415 remove_wait_queue(&dev
->wait_frame
, &wait
);
416 set_current_state(TASK_RUNNING
);
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
))
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
))
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
);
455 * @param fp File pointer
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");
478 poll_wait(fp
, &dev
->wait_frame
, wait
);
480 if (dev
->error_status
)
483 if (dev
->full_frames
!= NULL
)
484 return (POLLIN
| POLLRDNORM
);
491 * @param fp File pointer
492 * @param vma VMA structure
494 * @returns 0 if all is OK
498 * This function permits to map a memory space.
500 static int v4l_microdia_mmap(struct file
*fp
, struct vm_area_struct
*vma
)
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
)
529 // If no buffer found !
530 if (i
== MICRODIA_MAX_IMAGES
) {
531 UDIA_ERROR("mmap no buffer found !\n");
536 unsigned long total_size
;
538 total_size
= dev
->nbuffers
* dev
->len_per_image
;
540 if (size
!= dev
->len_per_image
&& size
!= total_size
)
543 else if (size
> dev
->len_per_image
)
546 vma
->vm_flags
|= VM_IO
;
548 pos
= (unsigned long) dev
->image_data
;
551 page
= vmalloc_to_pfn((void *) pos
);
553 if (remap_pfn_range(vma
, start
, page
, PAGE_SIZE
, PAGE_SHARED
))
559 if (size
> PAGE_SIZE
)
570 * @param inode Inode pointer
571 * @param fp File pointer
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
);
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
;
611 switch (dev
->webcam_type
) {
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
;
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
;
631 struct video_channel
*v
= arg
;
633 UDIA_DEBUG("VIDIOCGCHAN\n");
640 v
->type
= VIDEO_TYPE_CAMERA
;
641 strcpy(v
->name
, "Webcam");
647 struct video_channel
*v
= arg
;
649 UDIA_DEBUG("VIDIOCSCHAN\n");
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
;
675 case MICRODIA_PALETTE_BGR24
:
676 p
->palette
= VIDEO_PALETTE_RGB24
;
679 case MICRODIA_PALETTE_BGR32
:
680 p
->palette
= VIDEO_PALETTE_RGB32
;
683 case MICRODIA_PALETTE_UYVY
:
684 p
->palette
= VIDEO_PALETTE_UYVY
;
687 case MICRODIA_PALETTE_YUYV
:
688 p
->palette
= VIDEO_PALETTE_YUYV
;
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
;
713 case VIDEO_PALETTE_RGB24
:
714 dev
->vsettings
.depth
= 24;
715 dev
->vsettings
.palette
= MICRODIA_PALETTE_BGR24
;
718 /*case VIDEO_PALETTE_RGB32:
719 dev->vsettings.depth = 32;
720 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
723 case VIDEO_PALETTE_UYVY:
724 dev->vsettings.depth = 16;
725 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
728 case VIDEO_PALETTE_YUYV:
729 dev->vsettings.depth = 16;
730 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
738 // dev_microdia_camera_settings(dev);
740 UDIA_DEBUG("VIDIOCSPICT done\n");
746 struct video_window
*vw
= arg
;
748 UDIA_DEBUG("VIDIOCGWIN\n");
752 vw
->width
= dev
->view
.x
;
753 vw
->height
= dev
->view
.y
;
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");
786 microdia_clear_buffers(dev
);
788 // Initialize the device
789 dev_microdia_init_camera(dev
);
790 dev_microdia_camera_on(dev
);
793 usb_microdia_isoc_init(dev
);
795 // Re-start the stream
796 dev_microdia_start_stream(dev
);
799 // dev_microdia_camera_settings(dev);
805 struct video_buffer
*vb
= arg
;
807 UDIA_DEBUG("VIDIOCGFBUF\n");
809 memset(vb
, 0, sizeof(*vb
));
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
;
832 struct video_mmap
*vm
= arg
;
834 UDIA_DEBUG("VIDIOCMCAPTURE format=%d\n", vm
->format
);
836 if (vm
->frame
< 0 || vm
->frame
>= dev
->nbuffers
)
840 switch (vm
->format
) {
841 case VIDEO_PALETTE_YUV420P
:
844 case VIDEO_PALETTE_RGB24
:
847 /*case VIDEO_PALETTE_RGB32:
850 case VIDEO_PALETTE_UYVY:
853 case VIDEO_PALETTE_YUYV:
861 if ((vm
->width
!= dev
->view
.x
) || (vm
->height
!= dev
->view
.y
))
864 if (dev
->image_used
[vm
->frame
])
867 dev
->image_used
[vm
->frame
] = 1;
869 UDIA_DEBUG("VIDIOCMCAPTURE done\n");
878 UDIA_DEBUG("VIDIOCSYNC\n");
880 if (*mbuf
< 0 || *mbuf
>= dev
->nbuffers
)
883 if (dev
->image_used
[*mbuf
] == 0)
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
);
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
);
915 UDIA_ERROR("VIDIOCSYNC error !\n");
917 dev
->image_used
[*mbuf
] = 0;
922 UDIA_DEBUG("VIDIOCGAUDIO\n");
927 UDIA_DEBUG("VIDIOCSAUDIO\n");
933 struct video_unit
*vu
= arg
;
935 vu
->video
= dev
->vdev
->minor
& 0x3f;
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
));
963 case VIDIOC_ENUMINPUT
:
965 struct v4l2_input
*i
= arg
;
967 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", i
->index
);
972 strlcpy(i
->name
, "Webcam", sizeof(i
->name
));
973 i
->type
= V4L2_INPUT_TYPE_CAMERA
;
979 struct v4l2_input
*i
= arg
;
981 UDIA_DEBUG("GET INPUT %d\n", i
->index
);
990 struct v4l2_input
*i
= arg
;
992 UDIA_DEBUG("SET INPUT %d\n", i
->index
);
999 case VIDIOC_QUERYCTRL
:
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
, µdia_controls
[i
], sizeof(struct v4l2_queryctrl
));
1024 struct v4l2_control
*c
= arg
;
1026 UDIA_DEBUG("GET CTRL id=%d\n", c
->id
);
1029 case V4L2_CID_BRIGHTNESS
:
1030 c
->value
= dev
->vsettings
.brightness
;
1033 case V4L2_CID_WHITENESS
:
1034 c
->value
= dev
->vsettings
.whiteness
;
1037 case V4L2_CID_SATURATION
:
1038 c
->value
= dev
->vsettings
.colour
;
1041 case V4L2_CID_CONTRAST
:
1042 c
->value
= dev
->vsettings
.contrast
;
1053 struct v4l2_control
*c
= arg
;
1055 UDIA_DEBUG("SET CTRL id=%d value=%d\n", c
->id
, c
->value
);
1058 case V4L2_CID_BRIGHTNESS
:
1059 dev
->vsettings
.brightness
= (0xff00 & c
->value
);
1062 case V4L2_CID_WHITENESS
:
1063 dev
->vsettings
.whiteness
= (0xff00 & c
->value
);
1066 case V4L2_CID_SATURATION
:
1067 dev
->vsettings
.colour
= (0xff00 & c
->value
);
1070 case V4L2_CID_CONTRAST
:
1071 dev
->vsettings
.contrast
= (0xff00 & c
->value
);
1078 // dev_microdia_camera_settings(dev);
1082 case VIDIOC_ENUM_FMT
:
1085 struct v4l2_fmtdesc
*fmtd
= arg
;
1087 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd
->index
);
1089 if (fmtd
->index
!= 0)
1092 index
= fmtd
->index
;
1094 memset(fmtd
, 0, sizeof(*fmtd
));
1096 fmtd
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1097 fmtd
->index
= index
;
1102 fmtd
->pixelformat
= V4L2_PIX_FMT_YUV420
;
1103 strcpy(fmtd
->description
, "i420");
1106 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1108 strcpy(fmtd->description, "rgb24");
1113 fmtd
->pixelformat
= V4L2_PIX_FMT_BGR24
;
1115 strcpy(fmtd
->description
, "bgr24");
1120 fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
1122 strcpy(fmtd->description, "bgr24");
1127 fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
1129 strcpy(fmtd->description, "bgr32");
1134 fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
1136 strcpy(fmtd->description, "uyvy");
1141 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1143 strcpy(fmtd->description, "yuyv");
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
)
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
;
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;
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;
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;
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;
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;
1211 memcpy(&(fmtd
->fmt
.pix
), &pix_format
, sizeof(pix_format
));
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
)
1224 switch (fmtd
->fmt
.pix
.pixelformat
) {
1225 case V4L2_PIX_FMT_BGR24
:
1226 /*case V4L2_PIX_FMT_BGR24:*/
1227 dev
->vsettings
.depth
= 24;
1230 /*case V4L2_PIX_FMT_RGB32:
1231 case V4L2_PIX_FMT_BGR32:
1232 dev->vsettings.depth = 32;
1235 case V4L2_PIX_FMT_UYVY:
1236 case V4L2_PIX_FMT_YUYV:
1237 dev->vsettings.depth = 16;
1240 case V4L2_PIX_FMT_YUV420
:
1241 dev
->vsettings
.depth
= 12;
1248 switch (dev
->webcam_type
) {
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
;
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
;
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
)
1286 switch (fmtd
->fmt
.pix
.pixelformat
) {
1287 case V4L2_PIX_FMT_YUV420
:
1288 dev
->vsettings
.depth
= 12;
1289 dev
->vsettings
.palette
= MICRODIA_PALETTE_I420
;
1292 case V4L2_PIX_FMT_BGR24
:
1293 dev
->vsettings
.depth
= 24;
1294 dev
->vsettings
.palette
= MICRODIA_PALETTE_BGR24
;
1297 /*case V4L2_PIX_FMT_RGB32:
1298 dev->vsettings.depth = 32;
1299 dev->vsettings.palette = MICRODIA_PALETTE_RGB32;
1302 case V4L2_PIX_FMT_BGR24:
1303 dev->vsettings.depth = 24;
1304 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1307 case V4L2_PIX_FMT_BGR32:
1308 dev->vsettings.depth = 32;
1309 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
1312 case V4L2_PIX_FMT_UYVY:
1313 dev->vsettings.depth = 16;
1314 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
1317 case V4L2_PIX_FMT_YUYV:
1318 dev->vsettings.depth = 16;
1319 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
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");
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
);
1360 // dev_microdia_camera_settings(dev);
1364 case VIDIOC_QUERYSTD
:
1366 UDIA_DEBUG("QUERY STD\n");
1373 v4l2_std_id
*std
= arg
;
1375 UDIA_DEBUG("GET STD\n");
1377 *std
= V4L2_STD_UNKNOWN
;
1383 v4l2_std_id
*std
= arg
;
1385 UDIA_DEBUG("SET STD\n");
1387 if (*std
!= V4L2_STD_UNKNOWN
)
1392 case VIDIOC_ENUMSTD
:
1394 struct v4l2_standard
*std
= arg
;
1396 UDIA_DEBUG("VIDIOC_ENUMSTD\n");
1398 if (std
->index
!= 0)
1401 std
->id
= V4L2_STD_UNKNOWN
;
1402 strncpy(std
->name
, "webcam", sizeof(std
->name
));
1407 case VIDIOC_REQBUFS
:
1410 struct v4l2_requestbuffers
*rb
= arg
;
1412 if (rb
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1415 if (rb
->memory
!= V4L2_MEMORY_MMAP
)
1418 nbuffers
= rb
->count
;
1422 else if (nbuffers
> dev
->nbuffers
)
1423 nbuffers
= dev
->nbuffers
;
1425 rb
->count
= dev
->nbuffers
;
1429 case VIDIOC_QUERYBUF
:
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
)
1439 if (buf
->memory
!= V4L2_MEMORY_MMAP
)
1444 if (index
< 0 || index
>= dev
->nbuffers
)
1447 memset(buf
, 0, sizeof(struct v4l2_buffer
));
1449 buf
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
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
;
1461 struct v4l2_buffer
*buf
= arg
;
1463 UDIA_DEBUG("VIDIOC_QBUF\n");
1465 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1468 if (buf
->memory
!= V4L2_MEMORY_MMAP
)
1471 if (buf
->index
< 0 || buf
->index
>= dev
->nbuffers
)
1474 buf
->flags
|= V4L2_BUF_FLAG_QUEUED
;
1475 buf
->flags
&= ~V4L2_BUF_FLAG_DONE
;
1482 struct v4l2_buffer
*buf
= arg
;
1484 UDIA_DEBUG("VIDIOC_DQBUF\n");
1486 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
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
;
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
);
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
);
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
);
1534 case VIDIOC_STREAMON
:
1536 UDIA_DEBUG("VIDIOC_STREAMON\n");
1538 usb_microdia_isoc_init(dev
);
1542 case VIDIOC_STREAMOFF
:
1544 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1546 usb_microdia_isoc_cleanup(dev
);
1552 struct v4l2_streamparm
*sp
= arg
;
1554 UDIA_DEBUG("GET PARM %d\n", sp
->type
);
1556 if (sp
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
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;
1569 case VIDIOC_G_AUDIO
:
1570 UDIA_DEBUG("GET AUDIO\n");
1574 case VIDIOC_S_AUDIO
:
1575 UDIA_DEBUG("SET AUDIO\n");
1579 case VIDIOC_S_TUNER
:
1580 UDIA_DEBUG("SET TUNER\n");
1586 case VIDIOC_OVERLAY
:
1590 case VIDIOC_G_TUNER
:
1591 case VIDIOC_G_FREQUENCY
:
1592 case VIDIOC_S_FREQUENCY
:
1596 case VIDIOC_QUERYMENU
:
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;
1609 cc.bounds.width = 640;
1610 cc.bounds.height = 480;
1612 cc.defrect.left = 0;
1613 cc.defrect.width = 640;
1614 cc.defrect.height = 480;
1616 memcpy(arg, &cc, sizeof(cc));
1621 UDIA_DEBUG("IOCTL unknown !\n");
1622 return -ENOIOCTLCMD
;
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
)
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
);
1659 err
= v4l_microdia_do_ioctl(inode
, fp
, cmd
, (void __user
*) arg
);
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
)
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
;
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);
1695 UDIA_ERROR("Video register fail !\n");
1697 UDIA_INFO("Microdia USB2.0 Camera is now controlling video device /dev/video%d\n", dev
->vdev
->minor
);
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
);
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
,