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 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/kernel.h>
31 #include <linux/version.h>
32 #include <linux/errno.h>
33 #include <linux/slab.h>
34 #include <linux/kref.h>
35 #include <linux/vmalloc.h>
37 #include <linux/usb.h>
38 #include <media/v4l2-common.h>
43 static struct file_operations v4l_microdia_fops
;
47 * @var microdia_image_sizes
48 * List of all resolutions supported by the driver
50 const struct microdia_coord microdia_image_sizes
[MICRODIA_NBR_SIZES
] = {
64 * @var microdia_controls
65 * List of all V4Lv2 controls supported by the driver
67 static struct v4l2_queryctrl microdia_controls
[] = {
69 .id
= V4L2_CID_BRIGHTNESS
,
70 .type
= V4L2_CTRL_TYPE_INTEGER
,
75 .default_value
= 0x7f00,
78 .id
= V4L2_CID_WHITENESS
,
79 .type
= V4L2_CTRL_TYPE_INTEGER
,
84 .default_value
= 0x7f00,
88 .id = V4L2_CID_SATURATION,
89 .type = V4L2_CTRL_TYPE_INTEGER,
94 .default_value = 0x7f00,
98 .id
= V4L2_CID_CONTRAST
,
99 .type
= V4L2_CTRL_TYPE_INTEGER
,
104 .default_value
= 0x0000,
107 .id
= V4L2_CID_EXPOSURE
,
108 .type
= V4L2_CTRL_TYPE_INTEGER
,
113 .default_value
= 0x1000,
116 .id
= V4L2_CID_HFLIP
,
117 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
118 .name
= "Horizontal flip",
125 .id
= V4L2_CID_VFLIP
,
126 .type
= V4L2_CTRL_TYPE_BOOLEAN
,
127 .name
= "Vertical flip",
138 * @param width Width of wished resolution
139 * @param height Height of wished resolution
141 * @returns 0 if all is OK
143 * @brief Select a video mode
145 * This function permits to check and select a video mode.
147 int v4l_microdia_select_video_mode(struct usb_microdia
*dev
, int width
, int height
)
153 // Check width and height
154 // Notice : this test is usefull for the Kopete application !
155 printk( KERN_INFO
"Changing resolution to %d by %d\n", width
, height
);
157 // Driver can't build an image smaller than the minimal resolution !
158 if ((width
< microdia_image_sizes
[0].x
)
159 || (height
< microdia_image_sizes
[0].y
)) {
160 width
= microdia_image_sizes
[0].x
;
161 height
= microdia_image_sizes
[0].y
;
164 // Driver can't build an image bigger than the maximal resolution !
165 switch (dev
->webcam_type
) {
167 if ((width
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].x
)
168 || (height
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].y
)) {
169 width
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].x
;
170 height
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].y
;
175 if ((width
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-3-1].x
)
176 || (height
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-3-1].y
)) {
177 width
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-3-1].x
;
178 height
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-3-1].y
;
187 // Seek the best resolution
188 switch (dev
->webcam_type
) {
190 for (i
=0, find
=0; i
<MICRODIA_NBR_SIZES
; i
++) {
191 if (microdia_image_sizes
[i
].x
<= width
&& microdia_image_sizes
[i
].y
<= height
)
197 for (i
=0, find
=0; i
<MICRODIA_NBR_SIZES
-3; i
++) {
198 if (microdia_image_sizes
[i
].x
<= width
&& microdia_image_sizes
[i
].y
<= height
)
207 // Save the new resolution
208 dev
->resolution
= find
;
210 UDIA_DEBUG("Set mode %d [%dx%d]\n", dev
->resolution
,
211 microdia_image_sizes
[dev
->resolution
].x
, microdia_image_sizes
[dev
->resolution
].y
);
215 dev
->view
.y
= height
;
218 // Calculate the frame size
219 switch (dev
->resolution
) {
221 /*case MICRODIA_128x96:*/
222 case MICRODIA_160x120
:
223 /*case MICRODIA_213x160:*/
224 case MICRODIA_320x240
:
225 case MICRODIA_640x480
:
226 dev
->image
.x
= microdia_image_sizes
[MICRODIA_640x480
].x
;
227 dev
->image
.y
= microdia_image_sizes
[MICRODIA_640x480
].y
;
228 dev
->frame_size
= dev
->image
.x
* dev
->image
.y
;
231 case MICRODIA_800x600
:
232 case MICRODIA_1024x768
:
233 case MICRODIA_1280x1024
:
234 dev
->image
.x
= microdia_image_sizes
[MICRODIA_1280x1024
].x
;
235 dev
->image
.y
= microdia_image_sizes
[MICRODIA_1280x1024
].y
;
236 dev
->frame_size
= dev
->image
.x
* dev
->image
.y
;
241 // Calculate the image size
242 switch (dev
->vsettings
.palette
) {
243 case MICRODIA_PALETTE_RGB24
:
244 dev
->view_size
= 3 * dev
->view
.x
* dev
->view
.y
;
246 case MICRODIA_PALETTE_BGR24
:
247 dev
->view_size
= 3 * dev
->view
.x
* dev
->view
.y
;
250 case MICRODIA_PALETTE_RGB32
:
251 case MICRODIA_PALETTE_BGR32
:
252 dev
->view_size
= 4 * dev
->view
.x
* dev
->view
.y
;
255 case MICRODIA_PALETTE_UYVY
:
256 case MICRODIA_PALETTE_YUYV
:
257 dev
->view_size
= 2 * dev
->view
.x
* dev
->view
.y
;
259 case MICRODIA_PALETTE_I420
:
260 dev
->view_size
= dev
->view
.x
* dev
->view
.y
+
261 (dev
->view
.x
* dev
->view
.y
) / 2;
269 * @param inode Pointer on an inode
270 * @param fp File pointer
272 * @returns 0 if all is OK
274 * @brief Open the video device
276 * This function permits to open a video device (/dev/videoX)
278 static int v4l_microdia_open(struct inode
*inode
, struct file
*fp
)
282 struct usb_microdia
*dev
;
283 struct video_device
*vdev
;
285 vdev
= video_devdata(fp
);
286 dev
= video_get_drvdata(video_devdata(fp
));
289 UDIA_ERROR("Device not initialized !!!\n");
294 UDIA_DEBUG("Device is busy, someone is using the device\n");
299 err
= microdia_allocate_buffers(dev
);
302 UDIA_ERROR("Failed to allocate buffer memory !\n");
306 // Reset buffers and parameters
307 microdia_reset_buffers(dev
);
310 dev
->error_status
= 0;
311 dev
->visoc_errors
= 0;
312 dev
->vframes_error
= 0;
313 dev
->vframes_dumped
= 0;
314 dev
->vsettings
.hue
= 0xffff;
315 dev
->vsettings
.depth
= 24;
318 dev
->vsettings
.palette
= MICRODIA_PALETTE_I420
;
321 // Select the resolution by default
322 v4l_microdia_select_video_mode(dev
, 640, 480);
324 // Initialize the device
325 dev_microdia_init_camera(dev
);
326 dev_microdia_camera_on(dev
);
329 err
= usb_microdia_isoc_init(dev
);
332 UDIA_ERROR("Failed to init ISOC stuff !\n");
333 usb_microdia_isoc_cleanup(dev
);
334 microdia_free_buffers(dev
);
338 // Start the video stream
339 dev_microdia_start_stream(dev
);
340 dev_microdia_camera_settings(dev
);
343 fp
->private_data
= vdev
;
350 * @param inode Pointer on inode
351 * @param fp File pointer
353 * @returns 0 if all is OK
355 * @brief Release an opened file.
357 * This function permits to release an opened file with the 'open' method.
359 static int v4l_microdia_release(struct inode
*inode
, struct file
*fp
)
361 struct usb_microdia
*dev
;
362 struct video_device
*vdev
;
364 vdev
= video_devdata(fp
);
365 dev
= video_get_drvdata(video_devdata(fp
));
368 UDIA_ERROR("v4l_release called on closed device\n");
370 // Stop the video stream
371 dev_microdia_stop_stream(dev
);
373 // ISOC and URB cleanup
374 usb_microdia_isoc_cleanup(dev
);
377 microdia_free_buffers(dev
);
379 // Switch off the camera
380 dev_microdia_camera_off(dev
);
382 // dev_microdia_camera_asleep(dev);
391 * @param fp File pointer
393 * @retval buf Buffer in user space
397 * @returns Count value
399 * @brief Read the video device
401 * This function is called by the application is reading the video device.
403 static ssize_t
v4l_microdia_read(struct file
*fp
, char __user
*buf
,
404 size_t count
, loff_t
*f_pos
)
406 int noblock
= fp
->f_flags
& O_NONBLOCK
;
408 struct usb_microdia
*dev
;
409 struct video_device
*vdev
;
412 void *image_buffer_addr
;
414 DECLARE_WAITQUEUE(wait
, current
);
416 vdev
= video_devdata(fp
);
417 dev
= video_get_drvdata(video_devdata(fp
));
419 UDIA_STREAM("Read vdev=0x%p, buf=0x%p, count=%zd\n", vdev
, buf
, count
);
427 if (dev
->image_read_pos
== 0) {
428 add_wait_queue(&dev
->wait_frame
, &wait
);
430 while (dev
->full_frames
== NULL
) {
431 if (dev
->error_status
) {
432 remove_wait_queue(&dev
->wait_frame
, &wait
);
433 set_current_state(TASK_RUNNING
);
434 return -dev
->error_status
;
438 remove_wait_queue(&dev
->wait_frame
, &wait
);
439 set_current_state(TASK_RUNNING
);
443 if (signal_pending(current
)) {
444 remove_wait_queue(&dev
->wait_frame
, &wait
);
445 set_current_state(TASK_RUNNING
);
450 set_current_state(TASK_INTERRUPTIBLE
);
453 remove_wait_queue(&dev
->wait_frame
, &wait
);
454 set_current_state(TASK_RUNNING
);
456 if (microdia_handle_frame(dev
))
460 bytes_to_read
= dev
->view_size
;
462 if (count
+ dev
->image_read_pos
> bytes_to_read
)
463 count
= bytes_to_read
- dev
->image_read_pos
;
465 image_buffer_addr
= dev
->image_data
;
466 image_buffer_addr
+= dev
->images
[dev
->fill_image
].offset
;
467 image_buffer_addr
+= dev
->image_read_pos
;
469 if (copy_to_user(buf
, image_buffer_addr
, count
))
472 dev
->image_read_pos
+= count
;
474 if (dev
->image_read_pos
>= bytes_to_read
) {
475 dev
->image_read_pos
= 0;
476 microdia_next_image(dev
);
484 * @param fp File pointer
487 * @returns 0 if all is OK
489 * @brief Polling function
491 static unsigned int v4l_microdia_poll(struct file
*fp
, poll_table
*wait
)
493 struct usb_microdia
*dev
;
494 struct video_device
*vdev
;
496 vdev
= video_devdata(fp
);
497 dev
= video_get_drvdata(video_devdata(fp
));
499 UDIA_STREAM("Poll\n");
507 poll_wait(fp
, &dev
->wait_frame
, wait
);
509 if (dev
->error_status
)
512 if (dev
->full_frames
!= NULL
)
513 return (POLLIN
| POLLRDNORM
);
520 * @param fp File pointer
521 * @param vma VMA structure
523 * @returns 0 if all is OK
527 * This function permits to map a memory space.
529 static int v4l_microdia_mmap(struct file
*fp
, struct vm_area_struct
*vma
)
538 struct usb_microdia
*dev
;
540 struct video_device
*vdev
;
542 vdev
= video_devdata(fp
);
543 dev
= video_get_drvdata(video_devdata(fp
));
545 UDIA_STREAM("mmap\n");
547 start
= vma
->vm_start
;
548 size
= vma
->vm_end
- vma
->vm_start
;
550 // Find the buffer for this mapping...
551 for (i
=0; i
<dev
->nbuffers
; i
++) {
552 pos
= dev
->images
[i
].offset
;
554 if ((pos
>> PAGE_SHIFT
) == vma
->vm_pgoff
)
558 // If no buffer found !
559 if (i
== MICRODIA_MAX_IMAGES
) {
560 UDIA_ERROR("mmap no buffer found !\n");
565 unsigned long total_size
;
567 total_size
= dev
->nbuffers
* dev
->len_per_image
;
569 if (size
!= dev
->len_per_image
&& size
!= total_size
)
572 else if (size
> dev
->len_per_image
)
575 vma
->vm_flags
|= VM_IO
;
577 pos
= (unsigned long) dev
->image_data
;
580 page
= vmalloc_to_pfn((void *) pos
);
582 if (remap_pfn_range(vma
, start
, page
, PAGE_SIZE
, PAGE_SHARED
))
588 if (size
> PAGE_SIZE
)
599 * @param inode Inode pointer
600 * @param fp File pointer
602 * @param arg Arguments of the command
604 * @returns 0 if all is OK
606 * @brief Manage IOCTL
608 * This function permits to manage all the IOCTL from the application.
610 static int v4l_microdia_do_ioctl(struct inode
*inode
, struct file
*fp
,
611 unsigned int cmd
, void __user
*arg
)
613 struct usb_microdia
*dev
;
614 struct video_device
*vdev
;
616 DECLARE_WAITQUEUE(wait
, current
);
618 vdev
= video_devdata(fp
);
619 dev
= video_get_drvdata(video_devdata(fp
));
621 #if (CONFIG_MICRODIA_DEBUG == 1)
622 v4l_printk_ioctl(cmd
);
630 struct video_capability
*cap
= arg
;
632 UDIA_DEBUG("VIDIOCGCAP\n");
634 memset(cap
, 0, sizeof(*cap
));
635 strlcpy(cap
->name
, "microdia", sizeof(cap
->name
));
636 cap
->type
= VID_TYPE_CAPTURE
;
640 switch (dev
->webcam_type
) {
642 cap
->minwidth
= microdia_image_sizes
[MICRODIA_80x60
].x
;
643 cap
->minheight
= microdia_image_sizes
[MICRODIA_80x60
].y
;
644 cap
->maxwidth
= microdia_image_sizes
[MICRODIA_1280x1024
].x
;
645 cap
->maxheight
= microdia_image_sizes
[MICRODIA_1280x1024
].y
;
649 cap
->minwidth
= microdia_image_sizes
[MICRODIA_80x60
].x
;
650 cap
->minheight
= microdia_image_sizes
[MICRODIA_80x60
].y
;
651 cap
->maxwidth
= microdia_image_sizes
[MICRODIA_640x480
].x
;
652 cap
->maxheight
= microdia_image_sizes
[MICRODIA_640x480
].y
;
660 struct video_channel
*v
= arg
;
662 UDIA_DEBUG("VIDIOCGCHAN\n");
669 v
->type
= VIDEO_TYPE_CAMERA
;
670 strcpy(v
->name
, "Webcam");
676 struct video_channel
*v
= arg
;
678 UDIA_DEBUG("VIDIOCSCHAN\n");
687 struct video_picture
*p
= arg
;
689 UDIA_DEBUG("VIDIOCGPICT\n");
691 p
->brightness
= dev
->vsettings
.brightness
;
692 p
->contrast
= dev
->vsettings
.contrast
;
693 p
->whiteness
= dev
->vsettings
.whiteness
;
694 p
->colour
= dev
->vsettings
.colour
;
695 p
->depth
= dev
->vsettings
.depth
;
696 p
->palette
= dev
->vsettings
.palette
;
697 p
->hue
= dev
->vsettings
.hue
;
698 //p->exposure = dev->vsettings.exposure;
700 switch (dev
->vsettings
.palette
) {
701 case MICRODIA_PALETTE_I420
:
702 p
->palette
= VIDEO_PALETTE_YUV420P
;
705 case MICRODIA_PALETTE_BGR24
:
706 p
->palette
= VIDEO_PALETTE_RGB24
;
709 case MICRODIA_PALETTE_BGR32
:
710 p
->palette
= VIDEO_PALETTE_RGB32
;
713 case MICRODIA_PALETTE_UYVY
:
714 p
->palette
= VIDEO_PALETTE_UYVY
;
717 case MICRODIA_PALETTE_YUYV
:
718 p
->palette
= VIDEO_PALETTE_YUYV
;
726 struct video_picture
*p
= arg
;
728 UDIA_DEBUG("VIDIOCSPICT\n");
730 dev
->vsettings
.brightness
= p
->brightness
;
731 dev
->vsettings
.contrast
= p
->contrast
;
732 dev
->vsettings
.whiteness
= p
->whiteness
;
733 dev
->vsettings
.colour
= p
->colour
;
734 dev
->vsettings
.hue
= p
->hue
;
735 //dev->vsettings.exposure = p->exposure;
736 //dev->vsettings.gamma = p->gamma;
738 if (p
->palette
&& p
->palette
!= dev
->vsettings
.palette
) {
739 switch (p
->palette
) {
740 case VIDEO_PALETTE_YUV420P
:
741 dev
->vsettings
.depth
= 12;
742 dev
->vsettings
.palette
= MICRODIA_PALETTE_I420
;
745 case VIDEO_PALETTE_RGB24
:
746 //Set BGR decoding for V4L1 RGB24 palette
747 dev
->vsettings
.depth
= 24;
748 dev
->vsettings
.palette
= MICRODIA_PALETTE_BGR24
;
751 /*case VIDEO_PALETTE_RGB32:
752 dev->vsettings.depth = 32;
753 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
756 case VIDEO_PALETTE_UYVY:
757 dev->vsettings.depth = 16;
758 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
761 case VIDEO_PALETTE_YUYV:
762 dev->vsettings.depth = 16;
763 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
771 dev_microdia_camera_settings(dev
);
773 UDIA_DEBUG("VIDIOCSPICT done\n");
779 struct video_window
*vw
= arg
;
781 UDIA_DEBUG("VIDIOCGWIN\n");
785 vw
->width
= dev
->view
.x
;
786 vw
->height
= dev
->view
.y
;
793 struct video_window
*vw
= arg
;
795 UDIA_DEBUG("VIDIOCSWIN\n");
797 UDIA_DEBUG("Set x=%d, y=%d\n", vw
->x
, vw
->y
);
798 UDIA_DEBUG("Set width=%d, height=%d\n", vw
->width
, vw
->height
);
799 UDIA_DEBUG("Flags = %X\n", vw
->flags
);
801 // Stop the video stream
802 dev_microdia_stop_stream(dev
);
804 // ISOC and URB cleanup
805 usb_microdia_isoc_cleanup(dev
);
807 // Switch off the camera
808 dev_microdia_camera_off(dev
);
810 // dev_microdia_camera_asleep(dev);
812 // Select the new video mode
813 if (v4l_microdia_select_video_mode(dev
, vw
->width
, vw
->height
)) {
814 UDIA_ERROR("Select video mode failed !\n");
819 microdia_clear_buffers(dev
);
821 // Initialize the device
822 dev_microdia_init_camera(dev
);
823 dev_microdia_camera_on(dev
);
826 usb_microdia_isoc_init(dev
);
828 // Re-start the stream
829 dev_microdia_start_stream(dev
);
832 dev_microdia_camera_settings(dev
);
838 struct video_buffer
*vb
= arg
;
840 UDIA_DEBUG("VIDIOCGFBUF\n");
842 memset(vb
, 0, sizeof(*vb
));
849 struct video_mbuf
*vm
= arg
;
851 UDIA_DEBUG("VIDIOCGMBUF\n");
853 memset(vm
, 0, sizeof(*vm
));
855 vm
->size
= dev
->nbuffers
* dev
->len_per_image
;
856 vm
->frames
= dev
->nbuffers
;
858 for (i
=0; i
<dev
->nbuffers
; i
++)
859 vm
->offsets
[i
] = i
* dev
->len_per_image
;
865 struct video_mmap
*vm
= arg
;
867 UDIA_DEBUG("VIDIOCMCAPTURE format=%d\n", vm
->format
);
869 if (vm
->frame
< 0 || vm
->frame
>= dev
->nbuffers
)
873 switch (vm
->format
) {
874 case VIDEO_PALETTE_YUV420P
:
877 case VIDEO_PALETTE_RGB24
:
880 /*case VIDEO_PALETTE_RGB32:
883 case VIDEO_PALETTE_UYVY:
886 case VIDEO_PALETTE_YUYV:
894 if ((vm
->width
!= dev
->view
.x
) || (vm
->height
!= dev
->view
.y
))
897 if (dev
->image_used
[vm
->frame
])
900 dev
->image_used
[vm
->frame
] = 1;
902 UDIA_DEBUG("VIDIOCMCAPTURE done\n");
911 UDIA_DEBUG("VIDIOCSYNC\n");
913 if (*mbuf
< 0 || *mbuf
>= dev
->nbuffers
)
916 if (dev
->image_used
[*mbuf
] == 0)
919 add_wait_queue(&dev
->wait_frame
, &wait
);
921 while (dev
->full_frames
== NULL
) {
922 if (dev
->error_status
) {
923 remove_wait_queue(&dev
->wait_frame
, &wait
);
924 set_current_state(TASK_RUNNING
);
925 return -dev
->error_status
;
928 if (signal_pending(current
)) {
929 remove_wait_queue(&dev
->wait_frame
, &wait
);
930 set_current_state(TASK_RUNNING
);
935 set_current_state(TASK_INTERRUPTIBLE
);
938 remove_wait_queue(&dev
->wait_frame
, &wait
);
939 set_current_state(TASK_RUNNING
);
941 UDIA_DEBUG("VIDIOCSYNC: frame ready\n");
943 dev
->fill_image
= *mbuf
;
945 ret
= microdia_handle_frame(dev
);
948 UDIA_ERROR("VIDIOCSYNC error !\n");
950 dev
->image_used
[*mbuf
] = 0;
955 UDIA_DEBUG("VIDIOCGAUDIO\n");
960 UDIA_DEBUG("VIDIOCSAUDIO\n");
966 struct video_unit
*vu
= arg
;
968 vu
->video
= dev
->vdev
->minor
& 0x3f;
979 case VIDIOC_QUERYCAP
:
981 struct v4l2_capability
*cap
= arg
;
983 UDIA_DEBUG("VIDIOC_QUERYCAP\n");
985 memset(cap
, 0, sizeof(*cap
));
986 strlcpy(cap
->driver
, "microdia", sizeof(cap
->driver
));
988 cap
->capabilities
= V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_READWRITE
| V4L2_CAP_STREAMING
;
989 cap
->version
= (__u32
) DRIVER_VERSION_NUM
, strlcpy(cap
->card
, dev
->vdev
->name
, sizeof(cap
->card
));
991 if (usb_make_path(dev
->udev
, cap
->bus_info
, sizeof(cap
->bus_info
)) < 0)
992 strlcpy(cap
->bus_info
, dev
->vdev
->name
, sizeof(cap
->bus_info
));
996 case VIDIOC_ENUMINPUT
:
998 struct v4l2_input
*i
= arg
;
1000 UDIA_DEBUG("VIDIOC_ENUMINPUT %d\n", i
->index
);
1005 strlcpy(i
->name
, "Webcam", sizeof(i
->name
));
1006 i
->type
= V4L2_INPUT_TYPE_CAMERA
;
1010 case VIDIOC_G_INPUT
:
1012 struct v4l2_input
*i
= arg
;
1014 UDIA_DEBUG("GET INPUT %d\n", i
->index
);
1021 case VIDIOC_S_INPUT
:
1023 struct v4l2_input
*i
= arg
;
1025 UDIA_DEBUG("SET INPUT %d\n", i
->index
);
1032 case VIDIOC_QUERYCTRL
:
1036 struct v4l2_queryctrl
*c
= arg
;
1038 UDIA_DEBUG("VIDIOC_QUERYCTRL id = %d\n", c
->id
);
1040 nbr
= sizeof(microdia_controls
)/sizeof(struct v4l2_queryctrl
);
1042 for (i
=0; i
<nbr
; i
++) {
1043 if (microdia_controls
[i
].id
== c
->id
) {
1044 UDIA_DEBUG("VIDIOC_QUERYCTRL found\n");
1045 memcpy(c
, µdia_controls
[i
], sizeof(struct v4l2_queryctrl
));
1057 struct v4l2_control
*c
= arg
;
1059 UDIA_DEBUG("GET CTRL id=%d\n", c
->id
);
1062 case V4L2_CID_BRIGHTNESS
:
1063 c
->value
= dev
->vsettings
.brightness
;
1066 case V4L2_CID_EXPOSURE
:
1067 c
->value
= dev
->vsettings
.exposure
;
1070 case V4L2_CID_WHITENESS
:
1071 c
->value
= dev
->vsettings
.whiteness
;
1074 case V4L2_CID_SATURATION:
1075 c->value = dev->vsettings.colour;
1078 case V4L2_CID_CONTRAST
:
1079 c
->value
= dev
->vsettings
.contrast
;
1082 case V4L2_CID_HFLIP
:
1083 c
->value
= dev
->vsettings
.hflip
;
1086 case V4L2_CID_VFLIP
:
1087 c
->value
= dev
->vsettings
.vflip
;
1098 struct v4l2_control
*c
= arg
;
1100 UDIA_DEBUG("SET CTRL id=%d value=%d\n", c
->id
, c
->value
);
1103 case V4L2_CID_BRIGHTNESS
:
1104 dev
->vsettings
.brightness
= (0xff00 & c
->value
);
1105 dev_microdia_camera_set_brightness(dev
);
1108 case V4L2_CID_WHITENESS
:
1109 dev
->vsettings
.whiteness
= (0xff00 & c
->value
);
1110 dev_microdia_camera_set_gamma(dev
);
1113 /*case V4L2_CID_SATURATION:
1114 dev->vsettings.colour = (0xff00 & c->value);
1116 case V4L2_CID_EXPOSURE
:
1117 dev
->vsettings
.exposure
= (0xff00 & c
->value
);
1118 dev_microdia_camera_set_exposure(dev
);
1121 case V4L2_CID_CONTRAST
:
1122 dev
->vsettings
.contrast
= (0xff00 & c
->value
);
1123 dev_microdia_camera_set_contrast(dev
);
1126 case V4L2_CID_HFLIP
:
1127 dev
->vsettings
.hflip
= c
->value
;
1128 dev_microdia_camera_set_hvflip(dev
);
1131 case V4L2_CID_VFLIP
:
1132 dev
->vsettings
.vflip
= c
->value
;
1133 dev_microdia_camera_set_hvflip(dev
);
1140 // dev_microdia_camera_settings(dev);
1144 case VIDIOC_ENUM_FMT
:
1147 struct v4l2_fmtdesc
*fmtd
= arg
;
1149 UDIA_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd
->index
);
1151 if (fmtd
->index
!= 0)
1154 index
= fmtd
->index
;
1156 memset(fmtd
, 0, sizeof(*fmtd
));
1158 fmtd
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1159 fmtd
->index
= index
;
1164 fmtd
->pixelformat
= V4L2_PIX_FMT_YUV420
;
1165 strcpy(fmtd
->description
, "i420");
1168 fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
1170 strcpy(fmtd->description, "rgb24");
1175 fmtd
->pixelformat
= V4L2_PIX_FMT_BGR24
;
1177 strcpy(fmtd
->description
, "bgr24");
1182 fmtd
->pixelformat
= V4L2_PIX_FMT_RGB24
;
1184 strcpy(fmtd
->description
, "rgb24");
1189 fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
1191 strcpy(fmtd->description, "bgr32");
1196 fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
1198 strcpy(fmtd->description, "uyvy");
1203 fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
1205 strcpy(fmtd->description, "yuyv");
1216 struct v4l2_format
*fmtd
= arg
;
1217 struct v4l2_pix_format pix_format
;
1219 UDIA_DEBUG("GET FMT %d\n", fmtd
->type
);
1221 if (fmtd
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1224 pix_format
.width
= dev
->view
.x
;
1225 pix_format
.height
= dev
->view
.y
;
1226 pix_format
.field
= V4L2_FIELD_NONE
;
1227 pix_format
.colorspace
= V4L2_COLORSPACE_SRGB
;
1228 pix_format
.priv
= 0;
1230 switch (dev
->vsettings
.palette
) {
1231 case MICRODIA_PALETTE_I420
:
1232 pix_format
.pixelformat
= V4L2_PIX_FMT_YUV420
;
1233 pix_format
.sizeimage
= pix_format
.width
* pix_format
.height
+
1234 (pix_format
.width
* pix_format
.height
) / 2;
1235 case MICRODIA_PALETTE_BGR24
:
1236 pix_format
.pixelformat
= V4L2_PIX_FMT_BGR24
;
1237 pix_format
.sizeimage
= pix_format
.width
* pix_format
.height
* 3;
1238 pix_format
.bytesperline
= 3 * pix_format
.width
;
1240 case MICRODIA_PALETTE_RGB24
:
1241 pix_format
.pixelformat
= V4L2_PIX_FMT_RGB24
;
1242 pix_format
.sizeimage
= pix_format
.width
* pix_format
.height
* 3;
1243 pix_format
.bytesperline
= 3 * pix_format
.width
;
1245 /*case MICRODIA_PALETTE_RGB32:
1246 pix_format.pixelformat = V4L2_PIX_FMT_RGB32;
1247 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1248 pix_format.bytesperline = 4 * pix_format.width;
1251 case MICRODIA_PALETTE_BGR24:
1252 pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
1253 pix_format.sizeimage = pix_format.width * pix_format.height * 3;
1254 pix_format.bytesperline = 3 * pix_format.width;
1257 case MICRODIA_PALETTE_BGR32:
1258 pix_format.pixelformat = V4L2_PIX_FMT_BGR32;
1259 pix_format.sizeimage = pix_format.width * pix_format.height * 4;
1260 pix_format.bytesperline = 4 * pix_format.width;
1263 case MICRODIA_PALETTE_UYVY:
1264 pix_format.pixelformat = V4L2_PIX_FMT_UYVY;
1265 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1266 pix_format.bytesperline = 2 * pix_format.width;
1269 case MICRODIA_PALETTE_YUYV:
1270 pix_format.pixelformat = V4L2_PIX_FMT_YUYV;
1271 pix_format.sizeimage = pix_format.width * pix_format.height * 2;
1272 pix_format.bytesperline = 2 * pix_format.width;
1277 memcpy(&(fmtd
->fmt
.pix
), &pix_format
, sizeof(pix_format
));
1281 case VIDIOC_TRY_FMT
:
1283 struct v4l2_format
*fmtd
= arg
;
1285 UDIA_DEBUG("TRY FMT %d\n", fmtd
->type
);
1287 if (fmtd
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1290 switch (fmtd
->fmt
.pix
.pixelformat
) {
1291 case V4L2_PIX_FMT_BGR24
:
1292 /*case V4L2_PIX_FMT_BGR24:*/
1293 dev
->vsettings
.depth
= 24;
1296 case V4L2_PIX_FMT_RGB24
:
1297 dev
->vsettings
.depth
= 24;
1299 /*case V4L2_PIX_FMT_RGB32:
1300 case V4L2_PIX_FMT_BGR32:
1301 dev->vsettings.depth = 32;
1304 case V4L2_PIX_FMT_UYVY:
1305 case V4L2_PIX_FMT_YUYV:
1306 dev->vsettings.depth = 16;
1309 case V4L2_PIX_FMT_YUV420
:
1310 dev
->vsettings
.depth
= 12;
1317 switch (dev
->webcam_type
) {
1319 if (fmtd
->fmt
.pix
.width
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].x
)
1320 fmtd
->fmt
.pix
.width
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].x
;
1321 else if (fmtd
->fmt
.pix
.width
< microdia_image_sizes
[0].x
)
1322 fmtd
->fmt
.pix
.width
= microdia_image_sizes
[0].x
;
1324 if (fmtd
->fmt
.pix
.height
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].y
)
1325 fmtd
->fmt
.pix
.height
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-1].y
;
1326 else if (fmtd
->fmt
.pix
.height
< microdia_image_sizes
[0].y
)
1327 fmtd
->fmt
.pix
.height
= microdia_image_sizes
[0].y
;
1331 if (fmtd
->fmt
.pix
.width
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-1-3].x
)
1332 fmtd
->fmt
.pix
.width
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-1-3].x
;
1333 else if (fmtd
->fmt
.pix
.width
< microdia_image_sizes
[0].x
)
1334 fmtd
->fmt
.pix
.width
= microdia_image_sizes
[0].x
;
1336 if (fmtd
->fmt
.pix
.height
> microdia_image_sizes
[MICRODIA_NBR_SIZES
-1-3].y
)
1337 fmtd
->fmt
.pix
.height
= microdia_image_sizes
[MICRODIA_NBR_SIZES
-1-3].y
;
1338 else if (fmtd
->fmt
.pix
.height
< microdia_image_sizes
[0].y
)
1339 fmtd
->fmt
.pix
.height
= microdia_image_sizes
[0].y
;
1348 struct v4l2_format
*fmtd
= arg
;
1350 UDIA_DEBUG("SET FMT %d : %d\n", fmtd
->type
, fmtd
->fmt
.pix
.pixelformat
);
1352 if (fmtd
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1355 switch (fmtd
->fmt
.pix
.pixelformat
) {
1356 case V4L2_PIX_FMT_YUV420
:
1357 dev
->vsettings
.depth
= 12;
1358 dev
->vsettings
.palette
= MICRODIA_PALETTE_I420
;
1361 case V4L2_PIX_FMT_BGR24
:
1362 //set the decoder BGR24 from application
1363 dev
->vsettings
.depth
= 24;
1364 dev
->vsettings
.palette
= MICRODIA_PALETTE_BGR24
;
1367 case V4L2_PIX_FMT_RGB24
:
1368 //set the decoder RGB24 from application
1369 dev
->vsettings
.depth
= 24;
1370 dev
->vsettings
.palette
= MICRODIA_PALETTE_RGB24
;
1373 /*case V4L2_PIX_FMT_RGB32:
1374 dev->vsettings.depth = 32;
1375 dev->vsettings.palette = MICRODIA_PALETTE_RGB32;
1378 case V4L2_PIX_FMT_BGR24:
1379 dev->vsettings.depth = 24;
1380 dev->vsettings.palette = MICRODIA_PALETTE_BGR24;
1383 case V4L2_PIX_FMT_BGR32:
1384 dev->vsettings.depth = 32;
1385 dev->vsettings.palette = MICRODIA_PALETTE_BGR32;
1388 case V4L2_PIX_FMT_UYVY:
1389 dev->vsettings.depth = 16;
1390 dev->vsettings.palette = MICRODIA_PALETTE_UYVY;
1393 case V4L2_PIX_FMT_YUYV:
1394 dev->vsettings.depth = 16;
1395 dev->vsettings.palette = MICRODIA_PALETTE_YUYV;
1403 UDIA_DEBUG("Set width=%d, height=%d\n", fmtd
->fmt
.pix
.width
, fmtd
->fmt
.pix
.height
);
1405 // Stop the video stream
1406 dev_microdia_stop_stream(dev
);
1408 // ISOC and URB cleanup
1409 usb_microdia_isoc_cleanup(dev
);
1411 // Switch off the camera
1412 dev_microdia_camera_off(dev
);
1414 // dev_microdia_camera_asleep(dev);
1416 // Select the new video mode
1417 if (v4l_microdia_select_video_mode(dev
, fmtd
->fmt
.pix
.width
, fmtd
->fmt
.pix
.height
)) {
1418 UDIA_ERROR("Select video mode failed !\n");
1422 // Clear the buffers
1423 microdia_clear_buffers(dev
);
1425 // Initialize the device
1426 dev_microdia_init_camera(dev
);
1427 dev_microdia_camera_on(dev
);
1429 // ISOC and URB init
1430 usb_microdia_isoc_init(dev
);
1432 // Re-start the stream
1433 dev_microdia_start_stream(dev
);
1436 dev_microdia_camera_settings(dev
);
1440 case VIDIOC_QUERYSTD
:
1442 UDIA_DEBUG("QUERY STD\n");
1449 v4l2_std_id
*std
= arg
;
1451 UDIA_DEBUG("GET STD\n");
1453 *std
= V4L2_STD_UNKNOWN
;
1459 v4l2_std_id
*std
= arg
;
1461 UDIA_DEBUG("SET STD\n");
1463 if (*std
!= V4L2_STD_UNKNOWN
)
1468 case VIDIOC_ENUMSTD
:
1470 struct v4l2_standard
*std
= arg
;
1472 UDIA_DEBUG("VIDIOC_ENUMSTD\n");
1474 if (std
->index
!= 0)
1477 std
->id
= V4L2_STD_UNKNOWN
;
1478 strncpy(std
->name
, "webcam", sizeof(std
->name
));
1483 case VIDIOC_REQBUFS
:
1486 struct v4l2_requestbuffers
*rb
= arg
;
1488 if (rb
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1491 if (rb
->memory
!= V4L2_MEMORY_MMAP
)
1494 nbuffers
= rb
->count
;
1498 else if (nbuffers
> dev
->nbuffers
)
1499 nbuffers
= dev
->nbuffers
;
1501 rb
->count
= dev
->nbuffers
;
1505 case VIDIOC_QUERYBUF
:
1508 struct v4l2_buffer
*buf
= arg
;
1510 UDIA_DEBUG("QUERY BUFFERS %d %d\n", buf
->index
, dev
->nbuffers
);
1512 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1515 if (buf
->memory
!= V4L2_MEMORY_MMAP
)
1520 if (index
< 0 || index
>= dev
->nbuffers
)
1523 memset(buf
, 0, sizeof(struct v4l2_buffer
));
1525 buf
->type
= V4L2_BUF_TYPE_VIDEO_CAPTURE
;
1527 buf
->m
.offset
= index
* dev
->len_per_image
;
1528 buf
->bytesused
= dev
->view_size
;
1529 buf
->field
= V4L2_FIELD_NONE
;
1530 buf
->memory
= V4L2_MEMORY_MMAP
;
1531 buf
->length
= dev
->len_per_image
;
1537 struct v4l2_buffer
*buf
= arg
;
1539 UDIA_DEBUG("VIDIOC_QBUF\n");
1541 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1544 if (buf
->memory
!= V4L2_MEMORY_MMAP
)
1547 if (buf
->index
< 0 || buf
->index
>= dev
->nbuffers
)
1550 buf
->flags
|= V4L2_BUF_FLAG_QUEUED
;
1551 buf
->flags
&= ~V4L2_BUF_FLAG_DONE
;
1558 struct v4l2_buffer
*buf
= arg
;
1560 UDIA_DEBUG("VIDIOC_DQBUF\n");
1562 if (buf
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1565 add_wait_queue(&dev
->wait_frame
, &wait
);
1567 while (dev
->full_frames
== NULL
) {
1568 if (dev
->error_status
) {
1569 remove_wait_queue(&dev
->wait_frame
, &wait
);
1570 set_current_state(TASK_RUNNING
);
1572 return -dev
->error_status
;
1575 if (signal_pending(current
)) {
1576 remove_wait_queue(&dev
->wait_frame
, &wait
);
1577 set_current_state(TASK_RUNNING
);
1579 return -ERESTARTSYS
;
1581 if (fp
->f_flags
& O_NONBLOCK
) {
1582 remove_wait_queue(&dev
->wait_frame
, &wait
);
1583 set_current_state(TASK_RUNNING
);
1588 set_current_state(TASK_INTERRUPTIBLE
);
1591 remove_wait_queue(&dev
->wait_frame
, &wait
);
1592 set_current_state(TASK_RUNNING
);
1594 UDIA_DEBUG("VIDIOC_DQBUF : frame ready.\n");
1596 ret
= microdia_handle_frame(dev
);
1601 buf
->index
= dev
->fill_image
;
1602 buf
->bytesused
= dev
->view_size
;
1603 buf
->flags
= V4L2_BUF_FLAG_MAPPED
;
1604 buf
->field
= V4L2_FIELD_NONE
;
1605 do_gettimeofday(&buf
->timestamp
);
1607 buf
->memory
= V4L2_MEMORY_MMAP
;
1608 buf
->m
.offset
= dev
->fill_image
* dev
->len_per_image
;
1609 buf
->length
= buf
->bytesused
;
1611 microdia_next_image(dev
);
1615 case VIDIOC_STREAMON
:
1617 UDIA_DEBUG("VIDIOC_STREAMON\n");
1619 usb_microdia_isoc_init(dev
);
1623 case VIDIOC_STREAMOFF
:
1625 UDIA_DEBUG("VIDIOC_STREAMOFF\n");
1627 usb_microdia_isoc_cleanup(dev
);
1633 struct v4l2_streamparm
*sp
= arg
;
1635 UDIA_DEBUG("GET PARM %d\n", sp
->type
);
1637 if (sp
->type
!= V4L2_BUF_TYPE_VIDEO_CAPTURE
)
1640 sp
->parm
.capture
.capability
= 0;
1641 sp
->parm
.capture
.capturemode
= 0;
1642 sp
->parm
.capture
.timeperframe
.numerator
= 1;
1643 sp
->parm
.capture
.timeperframe
.denominator
= 30;
1644 sp
->parm
.capture
.readbuffers
= 2;
1645 sp
->parm
.capture
.extendedmode
= 0;
1650 case VIDIOC_G_AUDIO
:
1651 UDIA_DEBUG("GET AUDIO\n");
1655 case VIDIOC_S_AUDIO
:
1656 UDIA_DEBUG("SET AUDIO\n");
1660 case VIDIOC_S_TUNER
:
1661 UDIA_DEBUG("SET TUNER\n");
1667 case VIDIOC_OVERLAY
:
1671 case VIDIOC_G_TUNER
:
1672 case VIDIOC_G_FREQUENCY
:
1673 case VIDIOC_S_FREQUENCY
:
1677 case VIDIOC_QUERYMENU
:
1681 case VIDIOC_CROPCAP:
1683 struct v4l2_cropcap cc;
1685 cc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1686 cc.pixelaspect.numerator = 1;
1687 cc.pixelaspect.denominator = 1;
1690 cc.bounds.width = 640;
1691 cc.bounds.height = 480;
1693 cc.defrect.left = 0;
1694 cc.defrect.width = 640;
1695 cc.defrect.height = 480;
1697 memcpy(arg, &cc, sizeof(cc));
1702 UDIA_DEBUG("IOCTL unknown !\n");
1703 return -ENOIOCTLCMD
;
1711 * @param inode Inode pointer
1712 * @param fp File pointer
1713 * @param cmd Command
1714 * @param arg Arguements of the command
1716 * @returns 0 if all is OK
1718 * @brief Manage IOCTL
1720 * This function permits to manage all the IOCTL from the application.
1722 static int v4l_microdia_ioctl(struct inode
*inode
, struct file
*fp
,
1723 unsigned int cmd
, unsigned long arg
)
1726 struct usb_microdia
*dev
;
1727 struct video_device
*vdev
;
1729 vdev
= video_devdata(fp
);
1730 dev
= video_get_drvdata(video_devdata(fp
));
1732 UDIA_DEBUG("v4l_microdia_ioctl %02X\n", (unsigned char) cmd
);
1740 err
= v4l_microdia_do_ioctl(inode
, fp
, cmd
, (void __user
*) arg
);
1747 * @param dev Device structure
1749 * @returns 0 if all is OK
1751 * @brief Register the video device
1753 * This function permits to register the USB device to the video device.
1755 int v4l_microdia_register_video_device(struct usb_microdia
*dev
)
1759 strcpy(dev
->vdev
->name
, DRIVER_DESC
);
1761 dev
->vdev
->dev
= &dev
->interface
->dev
;
1762 dev
->vdev
->owner
= THIS_MODULE
;
1763 dev
->vdev
->type
= VID_TYPE_CAPTURE
;
1764 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
1765 dev
->vdev
->hardware
= VID_HARDWARE_MICRODIA
;
1767 dev
->vdev
->fops
= &v4l_microdia_fops
;
1768 dev
->vdev
->release
= video_device_release
;
1769 dev
->vdev
->minor
= -1;
1771 video_set_drvdata(dev
->vdev
, dev
);
1773 err
= video_register_device(dev
->vdev
, VFL_TYPE_GRABBER
, -1);
1776 UDIA_ERROR("Video register fail !\n");
1778 UDIA_INFO("Microdia USB2.0 Camera is now controlling video device /dev/video%d\n", dev
->vdev
->minor
);
1785 * @param dev Device structure
1787 * @returns 0 if all is OK
1789 * @brief Unregister the video device
1791 * This function permits to unregister the video device.
1793 int v4l_microdia_unregister_video_device(struct usb_microdia
*dev
)
1795 UDIA_INFO("Microdia USB2.0 Camera release resources video device /dev/video%d\n", dev
->vdev
->minor
);
1797 video_set_drvdata(dev
->vdev
, NULL
);
1798 video_unregister_device(dev
->vdev
);
1805 * @var v4l_microdia_fops
1807 * This variable contains some callback
1809 static struct file_operations v4l_microdia_fops
= {
1810 .owner
= THIS_MODULE
,
1811 .open
= v4l_microdia_open
,
1812 .release
= v4l_microdia_release
,
1813 .read
= v4l_microdia_read
,
1814 .poll
= v4l_microdia_poll
,
1815 .mmap
= v4l_microdia_mmap
,
1816 .ioctl
= v4l_microdia_ioctl
,
1817 #ifdef CONFIG_COMPAT
1818 .compat_ioctl
= v4l_compat_ioctl32
,