SyntekUSBVideoCamera
stk11xx-v4l.c
Go to the documentation of this file.
00001 
00034 #include <linux/module.h>
00035 #include <linux/init.h>
00036 #include <linux/kernel.h>
00037 #include <linux/version.h>
00038 #include <linux/errno.h>
00039 #include <linux/slab.h>
00040 #include <linux/kref.h>
00041 #include <linux/vmalloc.h>
00042 #include <linux/mm.h>
00043 
00044 
00045 #include <linux/usb.h>
00046 #include <media/v4l2-common.h>
00047 #include <media/v4l2-ioctl.h>
00048 
00049 #include "stk11xx.h"
00050 
00051 
00052 static struct v4l2_file_operations v4l_stk11xx_fops;
00053 
00054 
00059 const struct stk11xx_coord stk11xx_image_sizes[STK11XX_NBR_SIZES] = {
00060     {   80,   60 },
00061     {  128,   96 },
00062     {  160,  120 },
00063     {  213,  160 },
00064     {  320,  240 },
00065     {  640,  480 },
00066     {  800,  600 },
00067     { 1024,  768 },
00068     { 1280, 1024 }
00069 };
00070 
00071 
00077 static struct v4l2_queryctrl stk11xx_controls[] = {
00078     {
00079         .id      = V4L2_CID_BRIGHTNESS,
00080         .type    = V4L2_CTRL_TYPE_INTEGER,
00081         .name    = "Brightness",
00082         .minimum = 0,
00083         .maximum = 0xff00,
00084         .step    = 1,
00085         .default_value = 0x7f00,
00086     },
00087     {
00088         .id      = V4L2_CID_WHITENESS,
00089         .type    = V4L2_CTRL_TYPE_INTEGER,
00090         .name    = "Whiteness",
00091         .minimum = 0,
00092         .maximum = 0xff00,
00093         .step    = 1,
00094         .default_value = 0x7f00,
00095     },
00096     {
00097         .id      = V4L2_CID_SATURATION,
00098         .type    = V4L2_CTRL_TYPE_INTEGER,
00099         .name    = "Saturation",
00100         .minimum = 0,
00101         .maximum = 0xff00,
00102         .step    = 1,
00103         .default_value = 0x7f00,
00104     },
00105     {
00106         .id      = V4L2_CID_CONTRAST,
00107         .type    = V4L2_CTRL_TYPE_INTEGER,
00108         .name    = "Contrast",
00109         .minimum = 0,
00110         .maximum = 0xff00,
00111         .step    = 1,
00112         .default_value = 0x7f00,
00113     },
00114     {
00115         .id = V4L2_CID_HFLIP,
00116         .type   = V4L2_CTRL_TYPE_BOOLEAN,
00117         .name   = "Flip Horizontally",
00118         .minimum        = 0,
00119                 .maximum        = 1,
00120                 .step           = 1,
00121                 .default_value  = 0, // will be actually set later
00122     },
00123     {
00124         .id = V4L2_CID_VFLIP,
00125         .type   = V4L2_CTRL_TYPE_BOOLEAN,
00126         .name   = "Flip Vertically",
00127         .minimum        = 0,
00128                 .maximum        = 1,
00129                 .step           = 1,
00130                 .default_value  = 0, // will be actually set later
00131     }
00132 };
00133 
00134 
00146 int v4l_stk11xx_select_video_mode(struct usb_stk11xx *dev, int width, int height)
00147 {
00148     int i;
00149     int find;
00150 
00151 
00152     // Check width and height
00153     // Notice : this test is usefull for the Kopete application !
00154 
00155     // Driver can't build an image smaller than the minimal resolution !
00156     if ((width < stk11xx_image_sizes[0].x)
00157             || (height < stk11xx_image_sizes[0].y)) {
00158         width = stk11xx_image_sizes[0].x;
00159         height = stk11xx_image_sizes[0].y;
00160     }
00161 
00162     // Driver can't build an image bigger than the maximal resolution !
00163     switch (dev->webcam_type) {
00164         case STK11XX_SXGA:
00165             if ((width > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x)
00166                 || (height > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y)) {
00167                 width = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x;
00168                 height = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y;
00169             }
00170             break;
00171 
00172         case STK11XX_VGA:
00173             if ((width > stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].x)
00174                 || (height > stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].y)) {
00175                 width = stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].x;
00176                 height = stk11xx_image_sizes[STK11XX_NBR_SIZES-3-1].y;
00177             }
00178             break;
00179 
00180         default:
00181             return -1;
00182     }
00183 
00184 
00185     // Seek the best resolution
00186     switch (dev->webcam_type) {
00187         case STK11XX_SXGA:
00188             for (i=0, find=0; i<STK11XX_NBR_SIZES; i++) {
00189                 if (stk11xx_image_sizes[i].x <= width && stk11xx_image_sizes[i].y <= height)
00190                     find = i;
00191             }
00192             break;
00193 
00194         case STK11XX_VGA:
00195             for (i=0, find=0; i<STK11XX_NBR_SIZES-3; i++) {
00196                 if (stk11xx_image_sizes[i].x <= width && stk11xx_image_sizes[i].y <= height)
00197                     find = i;
00198             }
00199             break;
00200 
00201         default:
00202             return -1;
00203     }
00204 
00205     // Save the new resolution
00206     dev->resolution = find;
00207 
00208     STK_DEBUG("Set mode %d [%dx%d]\n", dev->resolution,
00209             stk11xx_image_sizes[dev->resolution].x, stk11xx_image_sizes[dev->resolution].y);
00210 
00211     // Save the new size
00212     dev->view.x = width;
00213     dev->view.y = height;
00214 
00215 
00216     // Calculate the frame size
00217     switch (dev->resolution) {
00218         case STK11XX_80x60:
00219         case STK11XX_128x96:
00220         case STK11XX_160x120:
00221         case STK11XX_213x160:
00222         case STK11XX_320x240:
00223         case STK11XX_640x480:
00224             dev->image.x = stk11xx_image_sizes[STK11XX_640x480].x;
00225             dev->image.y = stk11xx_image_sizes[STK11XX_640x480].y;
00226             dev->frame_size = dev->image.x * dev->image.y;
00227             break;
00228 
00229         case STK11XX_800x600:
00230         case STK11XX_1024x768:
00231         case STK11XX_1280x1024:
00232             dev->image.x = stk11xx_image_sizes[STK11XX_1280x1024].x;
00233             dev->image.y = stk11xx_image_sizes[STK11XX_1280x1024].y;
00234             dev->frame_size = dev->image.x * dev->image.y;
00235             break;
00236     }
00237 
00238 
00239     // Calculate the image size
00240         switch (dev->vsettings.palette) {
00241         case STK11XX_PALETTE_RGB24:
00242         case STK11XX_PALETTE_BGR24:
00243             dev->view_size = 3 * dev->view.x * dev->view.y;
00244             dev->image_size = 3 * dev->frame_size;
00245             break;
00246 
00247         case STK11XX_PALETTE_RGB32:
00248         case STK11XX_PALETTE_BGR32:
00249             dev->view_size = 3 * dev->view.x * dev->view.y;
00250             dev->image_size = 4 * dev->frame_size;
00251             break;
00252 
00253         case STK11XX_PALETTE_UYVY:
00254         case STK11XX_PALETTE_YUYV:
00255             dev->view_size = 2 * dev->view.x * dev->view.y;
00256             dev->image_size = 2 * dev->frame_size;
00257             break;
00258     }
00259 
00260     return 0;
00261 }
00262 
00263 
00273 static int v4l_stk11xx_open(struct file *fp)
00274 {
00275     int err;
00276 
00277     struct usb_stk11xx *dev;
00278     struct video_device *vdev;
00279     
00280     vdev = video_devdata(fp);
00281     dev = video_get_drvdata(video_devdata(fp));
00282 
00283     if (dev == NULL) {
00284         STK_ERROR("Device not initialized !!!\n");
00285         BUG();
00286     }
00287     mutex_lock(&dev->modlock);
00288 
00289     if (dev->vopen) {
00290         STK_DEBUG("Device is busy, someone is using the device\n");
00291         mutex_unlock(&dev->modlock);
00292         return -EBUSY;
00293     }
00294 
00295 
00296     // Allocate memory
00297     err = stk11xx_allocate_buffers(dev);
00298 
00299     if (err < 0) {
00300         STK_ERROR("Failed to allocate buffer memory !\n");
00301         mutex_unlock(&dev->modlock);
00302         return err;
00303     }
00304     
00305     // Reset buffers and parameters
00306     stk11xx_reset_buffers(dev);
00307 
00308     // Settings
00309     dev->error_status = 0;
00310     dev->visoc_errors = 0;
00311     dev->vframes_error = 0;
00312     dev->vframes_dumped = 0;
00313     dev->vsettings.hue = 0xffff;
00314     dev->vsettings.depth = 24;
00315     dev->vsettings.palette = STK11XX_PALETTE_BGR24;
00316 
00317     // Select the resolution by default
00318     v4l_stk11xx_select_video_mode(dev, 640, 480);
00319 
00320     // Initialize the device
00321     dev_stk11xx_init_camera(dev);
00322     dev_stk11xx_camera_on(dev);
00323     dev_stk11xx_reconf_camera(dev);
00324 
00325     // Init Isoc and URB
00326     err = usb_stk11xx_isoc_init(dev);
00327 
00328     if (err) {
00329         STK_ERROR("Failed to init ISOC stuff !\n");
00330         usb_stk11xx_isoc_cleanup(dev);
00331         stk11xx_free_buffers(dev);
00332         mutex_unlock(&dev->modlock);
00333         return err;
00334     }
00335 
00336     // Start the video stream
00337     dev_stk11xx_start_stream(dev);
00338 
00339     // Video settings
00340     dev_stk11xx_camera_settings(dev);
00341 
00342     // Register interface on power management
00343     usb_autopm_get_interface(dev->interface);
00344 
00345     dev->vopen++;
00346     fp->private_data = vdev;
00347 
00348     mutex_unlock(&dev->modlock);
00349 
00350     return 0;
00351 }
00352 
00353 
00363 static int v4l_stk11xx_release(struct file *fp)
00364 {
00365     struct usb_stk11xx *dev;
00366     struct video_device *vdev;
00367     
00368     vdev = video_devdata(fp);
00369     dev = video_get_drvdata(video_devdata(fp));
00370 
00371     if (dev->vopen == 0)
00372         STK_ERROR("v4l_release called on closed device\n");
00373 
00374     // Stop the video stream
00375     dev_stk11xx_stop_stream(dev);
00376 
00377     // ISOC and URB cleanup
00378     usb_stk11xx_isoc_cleanup(dev);
00379 
00380     // Free memory
00381     stk11xx_free_buffers(dev);
00382 
00383     // Switch off the camera
00384     dev_stk11xx_camera_off(dev);
00385 
00386     dev_stk11xx_camera_asleep(dev);
00387 
00388     // Unregister interface on power management
00389     usb_autopm_put_interface(dev->interface);
00390 
00391     dev->vopen--;
00392 
00393     return 0;
00394 }
00395 
00396 
00410 static ssize_t v4l_stk11xx_read(struct file *fp, char __user *buf,
00411         size_t count, loff_t *f_pos)
00412 {
00413     int noblock = fp->f_flags & O_NONBLOCK;
00414 
00415     struct usb_stk11xx *dev;
00416     struct video_device *vdev;
00417 
00418     int bytes_to_read;
00419     void *image_buffer_addr;
00420     
00421     DECLARE_WAITQUEUE(wait, current);
00422 
00423     vdev = video_devdata(fp);
00424     dev = video_get_drvdata(video_devdata(fp));
00425 
00426     STK_STREAM("Read vdev=0x%p, buf=0x%p, count=%zd\n", vdev, buf, count);
00427 
00428     if (dev == NULL)
00429         return -EFAULT;
00430 
00431     if (vdev == NULL)
00432         return -EFAULT;
00433 
00434     mutex_lock(&dev->modlock);
00435 
00436     if (dev->image_read_pos == 0) {
00437         add_wait_queue(&dev->wait_frame, &wait);
00438 
00439         while (dev->full_frames == NULL) {
00440             if (dev->error_status) {
00441                 remove_wait_queue(&dev->wait_frame, &wait);
00442                 set_current_state(TASK_RUNNING);
00443                 mutex_unlock(&dev->modlock);
00444                 return -dev->error_status ;
00445             }
00446 
00447             if (noblock) {
00448                 remove_wait_queue(&dev->wait_frame, &wait);
00449                 set_current_state(TASK_RUNNING);
00450                 mutex_unlock(&dev->modlock);
00451                 return -EWOULDBLOCK;
00452             }
00453 
00454             if (signal_pending(current)) {
00455                 remove_wait_queue(&dev->wait_frame, &wait);
00456                 set_current_state(TASK_RUNNING);
00457                 mutex_unlock(&dev->modlock);
00458                 return -ERESTARTSYS;
00459             }
00460 
00461             schedule();
00462             set_current_state(TASK_INTERRUPTIBLE);
00463         }
00464 
00465         remove_wait_queue(&dev->wait_frame, &wait);
00466         set_current_state(TASK_RUNNING);
00467 
00468         if (stk11xx_handle_frame(dev)) {
00469             mutex_unlock(&dev->modlock);
00470             return -EFAULT;
00471         }
00472     }
00473 
00474     bytes_to_read = dev->view_size;
00475 
00476     if (count + dev->image_read_pos > bytes_to_read)
00477         count = bytes_to_read - dev->image_read_pos;
00478 
00479     image_buffer_addr = dev->image_data;
00480     image_buffer_addr += dev->images[dev->fill_image].offset;
00481     image_buffer_addr += dev->image_read_pos;
00482 
00483     if (copy_to_user(buf, image_buffer_addr, count)) {
00484         mutex_unlock(&dev->modlock);
00485         return -EFAULT;
00486     }
00487     
00488     dev->image_read_pos += count;
00489     
00490     if (dev->image_read_pos >= bytes_to_read) {
00491         dev->image_read_pos = 0;
00492         stk11xx_next_image(dev);
00493     }
00494 
00495     mutex_unlock(&dev->modlock);
00496 
00497     return count;
00498 }
00499 
00500 
00509 static unsigned int v4l_stk11xx_poll(struct file *fp, poll_table *wait)
00510 {
00511     struct usb_stk11xx *dev;
00512     struct video_device *vdev;
00513     
00514     vdev = video_devdata(fp);
00515     dev = video_get_drvdata(video_devdata(fp));
00516 
00517     STK_STREAM("Poll\n");
00518 
00519     if (vdev == NULL)
00520         return -EFAULT;
00521 
00522     if (dev == NULL)
00523         return -EFAULT;
00524 
00525     poll_wait(fp, &dev->wait_frame, wait);
00526 
00527     if (dev->error_status)
00528         return POLLERR;
00529 
00530     if (dev->full_frames != NULL)
00531         return (POLLIN | POLLRDNORM);
00532 
00533     return 0;
00534 }
00535 
00536 
00547 static int v4l_stk11xx_mmap(struct file *fp, struct vm_area_struct *vma)
00548 {
00549     unsigned int i;
00550 
00551     unsigned long size;
00552     unsigned long start;
00553     unsigned long pos;
00554     unsigned long page;
00555 
00556     struct usb_stk11xx *dev;
00557 
00558     struct video_device *vdev;
00559     
00560     vdev = video_devdata(fp);
00561     dev = video_get_drvdata(video_devdata(fp));
00562 
00563     STK_STREAM("mmap\n");
00564 
00565     start = vma->vm_start;
00566     size = vma->vm_end - vma->vm_start;
00567 
00568     // Find the buffer for this mapping...
00569     for (i=0; i<dev->nbuffers; i++) {
00570         pos = dev->images[i].offset;
00571 
00572         if ((pos >> PAGE_SHIFT) == vma->vm_pgoff)
00573             break;
00574     }
00575 
00576     // If no buffer found !
00577     if (i == STK11XX_MAX_IMAGES) {
00578         STK_ERROR("mmap no buffer found !\n");
00579         return -EINVAL;
00580     }
00581 
00582     if (i == 0) {
00583         unsigned long total_size;
00584 
00585         total_size = dev->nbuffers * dev->len_per_image;
00586 
00587         if (size != dev->len_per_image && size != total_size) {
00588             STK_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n",
00589                 size, dev->len_per_image, total_size);
00590                 
00591             return -EINVAL;
00592         }
00593     }
00594     else if (size > dev->len_per_image)
00595         return -EINVAL;
00596 
00597     vma->vm_flags |= VM_IO;
00598 
00599     pos = (unsigned long) dev->image_data;
00600 
00601     while (size > 0) {
00602         page = vmalloc_to_pfn((void *) pos);
00603 
00604         if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
00605             return -EAGAIN;
00606 
00607         start += PAGE_SIZE;
00608         pos += PAGE_SIZE;
00609 
00610         if (size > PAGE_SIZE)
00611             size -= PAGE_SIZE;
00612         else
00613             size = 0;
00614     }
00615 
00616     return 0;
00617 }
00618 
00619 
00631 static long v4l_stk11xx_do_ioctl(struct file *fp,
00632         unsigned int cmd, void __user *arg)
00633 {
00634     struct usb_stk11xx *dev;
00635     struct video_device *vdev;
00636 
00637     DECLARE_WAITQUEUE(wait, current);
00638     
00639     vdev = video_devdata(fp);
00640     dev = video_get_drvdata(video_devdata(fp));
00641 
00642 #if (CONFIG_STK11XX_DEBUG == 1)
00643     v4l_printk_ioctl(cmd);
00644 #endif
00645 
00646     switch (cmd) {
00647         // Video 4 Linux v2
00648 
00649         case VIDIOC_QUERYCAP:
00650             {
00651                 struct v4l2_capability *cap = arg;
00652 
00653                 STK_DEBUG("VIDIOC_QUERYCAP\n");
00654 
00655                 memset(cap, 0, sizeof(*cap));
00656                 strlcpy(cap->driver, "stk11xx", sizeof(cap->driver));
00657 
00658                 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
00659                 cap->version = (__u32) DRIVER_VERSION_NUM, strlcpy(cap->card, dev->vdev->name, sizeof(cap->card));
00660             
00661                 if (usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)) < 0)
00662                     strlcpy(cap->bus_info, dev->vdev->name, sizeof(cap->bus_info));
00663             }
00664             break;
00665 
00666         case VIDIOC_ENUMINPUT:
00667             {
00668                 struct v4l2_input *i = arg;
00669 
00670                 STK_DEBUG("VIDIOC_ENUMINPUT %d\n", i->index);
00671 
00672                 if (i->index)
00673                     return -EINVAL;
00674 
00675                 strlcpy(i->name, "USB", sizeof(i->name));
00676                 i->type = V4L2_INPUT_TYPE_CAMERA;
00677             }
00678             break;
00679 
00680         case VIDIOC_G_INPUT:
00681             {
00682                 struct v4l2_input *i = arg;
00683 
00684                 STK_DEBUG("GET INPUT %d\n", i->index);
00685 
00686                 if (i->index)
00687                     return -EINVAL;
00688             }
00689             break;
00690 
00691         case VIDIOC_S_INPUT:
00692             {
00693                 struct v4l2_input *i = arg;
00694 
00695                 STK_DEBUG("SET INPUT %d\n", i->index);
00696 
00697                 if (i->index != 0)
00698                     return -EINVAL;
00699             }
00700             break;
00701 
00702         case VIDIOC_QUERYCTRL:
00703             {
00704                 int i;
00705                 int nbr;
00706                 struct v4l2_queryctrl *c = arg;
00707 
00708                 STK_DEBUG("VIDIOC_QUERYCTRL id = %d\n", c->id);
00709 
00710                 nbr = sizeof(stk11xx_controls)/sizeof(struct v4l2_queryctrl);
00711 
00712                 for (i=0; i<nbr; i++) {
00713                     if (stk11xx_controls[i].id == c->id) {
00714                         STK_DEBUG("VIDIOC_QUERYCTRL found\n");
00715                         memcpy(c, &stk11xx_controls[i], sizeof(struct v4l2_queryctrl));
00716                         switch(c->id)
00717                         {
00718                             case V4L2_CID_BRIGHTNESS:
00719                                 c->default_value = dev->vsettings.default_brightness;
00720                                 break;
00721                             case V4L2_CID_WHITENESS:
00722                                 c->default_value = dev->vsettings.default_whiteness;
00723                                 break;
00724                             case V4L2_CID_SATURATION:
00725                                 c->default_value = dev->vsettings.default_colour;
00726                                 break;
00727                             case V4L2_CID_CONTRAST:
00728                                 c->default_value = dev->vsettings.default_contrast;
00729                                 break;
00730                             case V4L2_CID_HFLIP:
00731                                 c->default_value = dev->vsettings.default_hflip;
00732                                 break;
00733                             case V4L2_CID_VFLIP:
00734                                 c->default_value = dev->vsettings.default_vflip;
00735                                 break;
00736                         }
00737                         break;
00738                     }
00739                 }
00740 
00741                 if (i >= nbr)
00742                     return -EINVAL;
00743             }
00744             break;
00745 
00746         case VIDIOC_G_CTRL:
00747             {
00748                 struct v4l2_control *c = arg;
00749 
00750                 STK_DEBUG("GET CTRL id=%d\n", c->id);
00751 
00752                 switch (c->id) {
00753                     case V4L2_CID_BRIGHTNESS:
00754                         c->value = dev->vsettings.brightness;
00755                         break;
00756 
00757                     case V4L2_CID_WHITENESS:
00758                         c->value = dev->vsettings.whiteness;
00759                         break;
00760 
00761                     case V4L2_CID_SATURATION:
00762                         c->value = dev->vsettings.colour;
00763                         break;
00764 
00765                     case V4L2_CID_CONTRAST:
00766                         c->value = dev->vsettings.contrast;
00767                         break;
00768 
00769                     case V4L2_CID_HFLIP:
00770                         c->value = dev->vsettings.hflip;
00771                         break;
00772 
00773                     case V4L2_CID_VFLIP:
00774                         c->value = dev->vsettings.vflip;
00775                         break;
00776 
00777                     default:
00778                         return -EINVAL;
00779                 }
00780             }
00781             break;
00782 
00783         case VIDIOC_S_CTRL:
00784             {
00785                 struct v4l2_control *c = arg;
00786 
00787                 STK_DEBUG("SET CTRL id=%d value=%d\n", c->id, c->value);
00788 
00789                 switch (c->id) {
00790                     case V4L2_CID_BRIGHTNESS:
00791                         dev->vsettings.brightness = (0xff00 & c->value);
00792                         break;
00793 
00794                     case V4L2_CID_WHITENESS:
00795                         dev->vsettings.whiteness = (0xff00 & c->value);
00796                         break;
00797 
00798                     case V4L2_CID_SATURATION:
00799                         dev->vsettings.colour = (0xff00 & c->value);
00800                         break;
00801 
00802                     case V4L2_CID_CONTRAST:
00803                         dev->vsettings.contrast = (0xff00 & c->value);
00804                         break;
00805 
00806                     case V4L2_CID_HFLIP:
00807                         dev->vsettings.hflip = c->value ? 1: 0;
00808                         break;
00809 
00810                     case V4L2_CID_VFLIP:
00811                         dev->vsettings.vflip = c->value ? 1: 0;
00812                         break;
00813 
00814                     default:
00815                         return -EINVAL;
00816                 }
00817 
00818                 dev_stk11xx_camera_settings(dev);
00819             }
00820             break;
00821 
00822         case VIDIOC_ENUM_FMT:
00823             {
00824                 int index;
00825                 struct v4l2_fmtdesc *fmtd = arg;
00826 
00827                 STK_DEBUG("VIDIOC_ENUM_FMT %d\n", fmtd->index);
00828 
00829                 if (fmtd->index != 0)
00830                     return -EINVAL;
00831 
00832                 index = fmtd->index;
00833 
00834                 memset(fmtd, 0, sizeof(*fmtd));
00835 
00836                 fmtd->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
00837                 fmtd->index = index;
00838 
00839                 switch (index) {
00840                     case 0:
00841                         fmtd->flags = 0;
00842                         fmtd->pixelformat = V4L2_PIX_FMT_RGB24;
00843 
00844                         strcpy(fmtd->description, "rgb24");
00845                         break;
00846 
00847                     case 1:
00848                         fmtd->flags = 0;
00849                         fmtd->pixelformat = V4L2_PIX_FMT_RGB32;
00850 
00851                         strcpy(fmtd->description, "rgb32");
00852                         break;
00853 
00854                     case 2:
00855                         fmtd->flags = 0;
00856                         fmtd->pixelformat = V4L2_PIX_FMT_BGR24;
00857 
00858                         strcpy(fmtd->description, "bgr24");
00859                         break;
00860 
00861                     case 3:
00862                         fmtd->flags = 0;
00863                         fmtd->pixelformat = V4L2_PIX_FMT_BGR32;
00864 
00865                         strcpy(fmtd->description, "bgr32");
00866                         break;
00867 
00868                     case 4:
00869                         fmtd->flags = 0;
00870                         fmtd->pixelformat = V4L2_PIX_FMT_UYVY;
00871 
00872                         strcpy(fmtd->description, "uyvy");
00873                         break;
00874 
00875                     case 5:
00876                         fmtd->flags = 0;
00877                         fmtd->pixelformat = V4L2_PIX_FMT_YUYV;
00878 
00879                         strcpy(fmtd->description, "yuyv");
00880                         break;
00881 
00882                     default:
00883                         return -EINVAL;
00884                 }
00885             }
00886             break;
00887 
00888         case VIDIOC_G_FMT:
00889             {
00890                 struct v4l2_format *fmtd = arg;
00891                 struct v4l2_pix_format pix_format;
00892 
00893                 STK_DEBUG("GET FMT %d\n", fmtd->type);
00894 
00895                 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
00896                     return -EINVAL;
00897 
00898                 pix_format.width = dev->view.x;
00899                 pix_format.height = dev->view.y;
00900                 pix_format.field = V4L2_FIELD_NONE;
00901                 pix_format.colorspace = V4L2_COLORSPACE_SRGB;
00902                 pix_format.priv = 0;
00903 
00904                                 switch (dev->vsettings.palette) {
00905                     case STK11XX_PALETTE_RGB24:
00906                         pix_format.pixelformat = V4L2_PIX_FMT_RGB24;
00907                         pix_format.sizeimage = pix_format.width * pix_format.height * 3;
00908                         pix_format.bytesperline = 3 * pix_format.width;
00909                         break;
00910 
00911                     case STK11XX_PALETTE_RGB32:
00912                         pix_format.pixelformat = V4L2_PIX_FMT_RGB32;
00913                         pix_format.sizeimage = pix_format.width * pix_format.height * 4;
00914                         pix_format.bytesperline = 4 * pix_format.width;
00915                         break;
00916 
00917                     case STK11XX_PALETTE_BGR24:
00918                         pix_format.pixelformat = V4L2_PIX_FMT_BGR24;
00919                         pix_format.sizeimage = pix_format.width * pix_format.height * 3;
00920                         pix_format.bytesperline = 3 * pix_format.width;
00921                         break;
00922 
00923                     case STK11XX_PALETTE_BGR32:
00924                         pix_format.pixelformat = V4L2_PIX_FMT_BGR32;
00925                         pix_format.sizeimage = pix_format.width * pix_format.height * 4;
00926                         pix_format.bytesperline = 4 * pix_format.width;
00927                         break;
00928 
00929                     case STK11XX_PALETTE_UYVY:
00930                         pix_format.pixelformat = V4L2_PIX_FMT_UYVY;
00931                         pix_format.sizeimage = pix_format.width * pix_format.height * 2;
00932                         pix_format.bytesperline = 2 * pix_format.width;
00933                         break;
00934 
00935                     case STK11XX_PALETTE_YUYV:
00936                         pix_format.pixelformat = V4L2_PIX_FMT_YUYV;
00937                         pix_format.sizeimage = pix_format.width * pix_format.height * 2;
00938                         pix_format.bytesperline = 2 * pix_format.width;
00939                         break;
00940                 }
00941 
00942                 memcpy(&(fmtd->fmt.pix), &pix_format, sizeof(pix_format));
00943             }
00944             break;
00945 
00946         case VIDIOC_TRY_FMT:
00947             {
00948                 struct v4l2_format *fmtd = arg;
00949 
00950                 STK_DEBUG("TRY FMT %d\n", fmtd->type);
00951 
00952                 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
00953                     return -EINVAL;
00954 
00955 
00956                 switch (dev->webcam_type) {
00957                     case STK11XX_SXGA:
00958                         if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x)
00959                             fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].x;
00960                         else if (fmtd->fmt.pix.width < stk11xx_image_sizes[0].x)
00961                             fmtd->fmt.pix.width = stk11xx_image_sizes[0].x;
00962     
00963                         if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y)
00964                             fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_NBR_SIZES-1].y;
00965                         else if (fmtd->fmt.pix.height < stk11xx_image_sizes[0].y)
00966                             fmtd->fmt.pix.height = stk11xx_image_sizes[0].y;
00967                         break;
00968 
00969                     case STK11XX_VGA:
00970                         if (fmtd->fmt.pix.width > stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].x)
00971                             fmtd->fmt.pix.width = stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].x;
00972                         else if (fmtd->fmt.pix.width < stk11xx_image_sizes[0].x)
00973                             fmtd->fmt.pix.width = stk11xx_image_sizes[0].x;
00974     
00975                         if (fmtd->fmt.pix.height > stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].y)
00976                             fmtd->fmt.pix.height = stk11xx_image_sizes[STK11XX_NBR_SIZES-1-3].y;
00977                         else if (fmtd->fmt.pix.height < stk11xx_image_sizes[0].y)
00978                             fmtd->fmt.pix.height = stk11xx_image_sizes[0].y;
00979                         break;
00980                 }
00981                                 fmtd->fmt.pix.field = V4L2_FIELD_NONE;
00982                                 fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
00983                                 fmtd->fmt.pix.priv = 0;
00984                 switch (fmtd->fmt.pix.pixelformat) {
00985                     case V4L2_PIX_FMT_RGB24:
00986                         dev->vsettings.depth = 24;
00987                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 3;
00988                                                 fmtd->fmt.pix.bytesperline = 3 * fmtd->fmt.pix.width;
00989 
00990                         break;
00991 
00992                     case V4L2_PIX_FMT_RGB32:
00993                         dev->vsettings.depth = 32;
00994                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 4;
00995                                                 fmtd->fmt.pix.bytesperline = 4 * fmtd->fmt.pix.width;
00996 
00997                         break;
00998 
00999                     case V4L2_PIX_FMT_BGR24:
01000                         dev->vsettings.depth = 24;
01001                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 3;
01002                                                 fmtd->fmt.pix.bytesperline = 3 * fmtd->fmt.pix.width;
01003 
01004                         break;
01005 
01006                     case V4L2_PIX_FMT_BGR32:
01007                         dev->vsettings.depth = 32;
01008                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 4;
01009                                                 fmtd->fmt.pix.bytesperline = 4 * fmtd->fmt.pix.width;
01010 
01011                         break;
01012 
01013                     case V4L2_PIX_FMT_UYVY:
01014                         dev->vsettings.depth = 16;
01015                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 2;
01016                                                 fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
01017 
01018                         break;
01019 
01020                     case V4L2_PIX_FMT_YUYV:
01021                         dev->vsettings.depth = 16;
01022                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 2;
01023                                                 fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
01024 
01025                         break;
01026 
01027                     default:
01028                         return -EINVAL;
01029                 }
01030 
01031             }
01032             break;
01033 
01034         case VIDIOC_S_FMT:
01035             {
01036                 struct v4l2_format *fmtd = arg;
01037 
01038                 STK_DEBUG("SET FMT %d : %d\n", fmtd->type, fmtd->fmt.pix.pixelformat);
01039 
01040                 if (fmtd->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
01041                     return -EINVAL;
01042 
01043                                 // need to also set the fields as in G_FMT, conform v4l2 specs
01044                                 fmtd->fmt.pix.field = V4L2_FIELD_NONE;
01045                                 fmtd->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
01046                                 fmtd->fmt.pix.priv = 0;
01047 
01048 
01049                 switch (fmtd->fmt.pix.pixelformat) {
01050                     case V4L2_PIX_FMT_RGB24:
01051                         dev->vsettings.depth = 24;
01052                                                 dev->vsettings.palette = STK11XX_PALETTE_RGB24;
01053                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 3;
01054                                                 fmtd->fmt.pix.bytesperline = 3 * fmtd->fmt.pix.width;
01055 
01056                         break;
01057 
01058                     case V4L2_PIX_FMT_RGB32:
01059                         dev->vsettings.depth = 32;
01060                         dev->vsettings.palette = STK11XX_PALETTE_RGB32;
01061                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 4;
01062                                                 fmtd->fmt.pix.bytesperline = 4 * fmtd->fmt.pix.width;
01063 
01064                         break;
01065 
01066                     case V4L2_PIX_FMT_BGR24:
01067                         dev->vsettings.depth = 24;
01068                         dev->vsettings.palette = STK11XX_PALETTE_BGR24;
01069                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 3;
01070                                                 fmtd->fmt.pix.bytesperline = 3 * fmtd->fmt.pix.width;
01071 
01072                         break;
01073 
01074                     case V4L2_PIX_FMT_BGR32:
01075                         dev->vsettings.depth = 32;
01076                         dev->vsettings.palette = STK11XX_PALETTE_BGR32;
01077                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 4;
01078                                                 fmtd->fmt.pix.bytesperline = 4 * fmtd->fmt.pix.width;
01079 
01080                         break;
01081 
01082                     case V4L2_PIX_FMT_UYVY:
01083                         dev->vsettings.depth = 16;
01084                         dev->vsettings.palette = STK11XX_PALETTE_UYVY;
01085                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 2;
01086                                                 fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
01087 
01088                         break;
01089 
01090                     case V4L2_PIX_FMT_YUYV:
01091                         dev->vsettings.depth = 16;
01092                         dev->vsettings.palette = STK11XX_PALETTE_YUYV;
01093                                                 fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.width * fmtd->fmt.pix.height * 2;
01094                                                 fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
01095 
01096                         break;
01097 
01098                     default:
01099                         return -EINVAL;
01100                 }
01101 
01102                 STK_DEBUG("Set width=%d, height=%d\n", fmtd->fmt.pix.width, fmtd->fmt.pix.height);
01103 
01104                 // Stop the video stream
01105                 dev_stk11xx_stop_stream(dev);
01106             
01107                 // ISOC and URB cleanup
01108                 usb_stk11xx_isoc_cleanup(dev);
01109 
01110                 // Switch off the camera
01111                 dev_stk11xx_camera_off(dev);
01112 
01113                 dev_stk11xx_camera_asleep(dev);
01114 
01115                 // Select the new video mode
01116                 if (v4l_stk11xx_select_video_mode(dev, fmtd->fmt.pix.width, fmtd->fmt.pix.height)) {
01117                     STK_ERROR("Select video mode failed !\n");
01118                     return -EAGAIN;
01119                 }
01120 
01121                 // Clear the buffers
01122                 stk11xx_clear_buffers(dev);
01123 
01124                 // Initialize the device
01125                 dev_stk11xx_init_camera(dev);
01126                 dev_stk11xx_camera_on(dev);
01127                 dev_stk11xx_reconf_camera(dev);
01128 
01129                 // ISOC and URB init
01130                 usb_stk11xx_isoc_init(dev);
01131 
01132                 // Re-start the stream
01133                 dev_stk11xx_start_stream(dev);
01134 
01135                 // Video settings
01136                 dev_stk11xx_camera_settings(dev);
01137             }
01138             break;
01139 
01140         case VIDIOC_QUERYSTD:
01141             {
01142                 STK_DEBUG("QUERY STD\n");
01143                 return -EINVAL;
01144             }
01145             break;
01146 
01147         case VIDIOC_G_STD:
01148             {
01149                 v4l2_std_id *std = arg;
01150 
01151                 STK_DEBUG("GET STD\n");
01152         
01153                 *std = V4L2_STD_UNKNOWN;
01154             }
01155             break;
01156 
01157         case VIDIOC_S_STD:
01158             {
01159                 v4l2_std_id *std = arg;
01160 
01161                 STK_DEBUG("SET STD\n");
01162                 
01163                 if (*std != V4L2_STD_UNKNOWN)
01164                     return -EINVAL;
01165             }
01166             break;
01167 
01168         case VIDIOC_ENUMSTD:
01169             {
01170                 struct v4l2_standard *std = arg;
01171 
01172                 STK_DEBUG("VIDIOC_ENUMSTD\n");
01173 
01174                 if (std->index != 0)
01175                     return -EINVAL;
01176 
01177                 std->id = V4L2_STD_UNKNOWN;
01178                 strncpy(std->name, "webcam", sizeof(std->name));
01179 
01180                 break;
01181             }
01182 
01183         case VIDIOC_REQBUFS:
01184             {
01185                 int nbuffers;
01186                 struct v4l2_requestbuffers *rb = arg;
01187 
01188                 if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
01189                     return -EINVAL;
01190 
01191                 if (rb->memory != V4L2_MEMORY_MMAP)
01192                     return -EINVAL;
01193 
01194                 nbuffers = rb->count;
01195 
01196                 if (nbuffers < 2)
01197                     nbuffers = 2;
01198                 else if (nbuffers > dev->nbuffers)
01199                     nbuffers = dev->nbuffers;
01200 
01201                 rb->count = dev->nbuffers;
01202             }
01203             break;
01204 
01205         case VIDIOC_QUERYBUF:
01206             {
01207                 int index;
01208                 struct v4l2_buffer *buf = arg;
01209 
01210                 STK_DEBUG("QUERY BUFFERS %d %d\n", buf->index, dev->nbuffers);
01211 
01212                 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
01213                     return -EINVAL;
01214 
01215                 if (buf->memory != V4L2_MEMORY_MMAP) 
01216                     return -EINVAL;
01217 
01218                 index = buf->index;
01219 
01220                 if (index < 0 || index >= dev->nbuffers)
01221                     return -EINVAL;
01222 
01223                 memset(buf, 0, sizeof(struct v4l2_buffer));
01224 
01225                 buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
01226                 buf->index = index;
01227                 buf->m.offset = index * dev->len_per_image;
01228                 buf->bytesused = dev->view_size;
01229                 buf->field = V4L2_FIELD_NONE;
01230                 buf->memory = V4L2_MEMORY_MMAP;
01231                 buf->length = dev->len_per_image;
01232             }
01233             break;
01234 
01235         case VIDIOC_QBUF:
01236             {
01237                 struct v4l2_buffer *buf = arg;
01238 
01239                 STK_DEBUG("VIDIOC_QBUF\n");
01240 
01241                 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
01242                     return -EINVAL;
01243 
01244                 if (buf->memory != V4L2_MEMORY_MMAP)
01245                     return -EINVAL;
01246 
01247                 if (buf->index < 0 || buf->index >= dev->nbuffers)
01248                     return -EINVAL;
01249 
01250                 buf->flags |= V4L2_BUF_FLAG_QUEUED;
01251                 buf->flags &= ~V4L2_BUF_FLAG_DONE;
01252             }
01253             break;
01254 
01255         case VIDIOC_DQBUF:
01256             {
01257                 int ret;
01258                 struct v4l2_buffer *buf = arg;
01259 
01260                 STK_DEBUG("VIDIOC_DQBUF\n");
01261                 
01262                 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
01263                     return -EINVAL;
01264 
01265                 add_wait_queue(&dev->wait_frame, &wait);
01266 
01267                 while (dev->full_frames == NULL) {
01268                     if (dev->error_status) {
01269                         remove_wait_queue(&dev->wait_frame, &wait);
01270                         set_current_state(TASK_RUNNING);
01271 
01272                         return -dev->error_status;
01273                     }
01274 
01275                     if (signal_pending(current)) {
01276                         remove_wait_queue(&dev->wait_frame, &wait);
01277                         set_current_state(TASK_RUNNING);
01278 
01279                         return -ERESTARTSYS;
01280                     }
01281 
01282                     schedule();
01283                     set_current_state(TASK_INTERRUPTIBLE);
01284                 }
01285 
01286                 remove_wait_queue(&dev->wait_frame, &wait);
01287                 set_current_state(TASK_RUNNING);
01288 
01289                 STK_DEBUG("VIDIOC_DQBUF : frame ready.\n");
01290 
01291                 ret = stk11xx_handle_frame(dev);
01292 
01293                 if (ret)
01294                     return -EFAULT;
01295 
01296                 buf->index = dev->fill_image;
01297                 buf->bytesused = dev->view_size;
01298                 buf->flags = V4L2_BUF_FLAG_MAPPED;
01299                 buf->field = V4L2_FIELD_NONE;
01300                 do_gettimeofday(&buf->timestamp);
01301                 buf->sequence = 0;
01302                 buf->memory = V4L2_MEMORY_MMAP;
01303                 buf->m.offset = dev->fill_image * dev->len_per_image;
01304                 buf->length = dev->len_per_image; //buf->bytesused;
01305 
01306                 stk11xx_next_image(dev);
01307             }
01308             break;
01309 
01310         case VIDIOC_STREAMON:
01311             {
01312                 STK_DEBUG("VIDIOC_STREAMON\n");
01313 
01314                 usb_stk11xx_isoc_init(dev);
01315             }
01316             break;
01317 
01318         case VIDIOC_STREAMOFF:
01319             {
01320                 STK_DEBUG("VIDIOC_STREAMOFF\n");
01321 
01322                 usb_stk11xx_isoc_cleanup(dev);
01323             }
01324             break;
01325 
01326         case VIDIOC_G_PARM:
01327             {
01328                 struct v4l2_streamparm *sp = arg;
01329 
01330                 STK_DEBUG("GET PARM %d\n", sp->type);
01331 
01332                 if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
01333                     return -EINVAL;
01334 
01335                 sp->parm.capture.capability = 0;
01336                 sp->parm.capture.capturemode = 0;
01337                 sp->parm.capture.timeperframe.numerator = 1;
01338                 sp->parm.capture.timeperframe.denominator = 30;
01339                 sp->parm.capture.readbuffers = 2;
01340                 sp->parm.capture.extendedmode = 0;
01341             }
01342             break;
01343 
01344 
01345         case VIDIOC_G_AUDIO:
01346             STK_DEBUG("GET AUDIO\n");
01347             return -EINVAL;
01348             break;
01349 
01350         case VIDIOC_S_AUDIO:
01351             STK_DEBUG("SET AUDIO\n");
01352             return -EINVAL;
01353             break;
01354 
01355         case VIDIOC_S_TUNER:
01356             STK_DEBUG("SET TUNER\n");
01357             return -EINVAL;
01358             break;
01359 
01360         case VIDIOC_G_FBUF:
01361         case VIDIOC_S_FBUF:
01362         case VIDIOC_OVERLAY:
01363             return -EINVAL;
01364             break;
01365 
01366         case VIDIOC_G_TUNER:
01367         case VIDIOC_G_FREQUENCY:
01368         case VIDIOC_S_FREQUENCY:
01369             return -EINVAL;
01370             break;
01371 
01372         case VIDIOC_QUERYMENU:
01373             return -EINVAL;
01374             break;
01375 /*
01376         case VIDIOC_CROPCAP:
01377             {
01378                 struct v4l2_cropcap cc;
01379 
01380                 cc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
01381                 cc.pixelaspect.numerator = 1;
01382                 cc.pixelaspect.denominator = 1;
01383                 cc.bounds.top = 0;
01384                 cc.bounds.left = 0;
01385                 cc.bounds.width = 640;
01386                 cc.bounds.height = 480;
01387                 cc.defrect.top = 0;
01388                 cc.defrect.left = 0;
01389                 cc.defrect.width = 640;
01390                 cc.defrect.height = 480;
01391 
01392                 memcpy(arg, &cc, sizeof(cc));
01393             }
01394             break;
01395 */
01396         default:
01397             STK_DEBUG("IOCTL unknown !\n");
01398             return -ENOIOCTLCMD;
01399     }
01400 
01401     return 0;
01402 }
01403 
01404 
01416 static long v4l_stk11xx_ioctl(struct file *fp,
01417         unsigned int cmd, unsigned long arg)
01418 {
01419     long err;
01420     struct usb_stk11xx *dev;
01421     struct video_device *vdev;
01422     
01423     vdev = video_devdata(fp);
01424     dev = video_get_drvdata(video_devdata(fp));
01425 
01426     STK_DEBUG("v4l_stk11xx_ioctl %02X\n", (unsigned char) cmd);
01427 
01428     if (dev == NULL)
01429         return -EFAULT;
01430 
01431     if (vdev == NULL)
01432         return -EFAULT;
01433 
01434     mutex_lock(&dev->modlock); 
01435 
01436     err = video_usercopy(fp, cmd, arg, v4l_stk11xx_do_ioctl);
01437 
01438     mutex_unlock(&dev->modlock);
01439 
01440     return err;
01441 }
01442 
01443 
01453 int v4l_stk11xx_register_video_device(struct usb_stk11xx *dev)
01454 {
01455     int err;
01456 
01457     strcpy(dev->vdev->name, DRIVER_DESC);
01458 
01459     dev->vdev->dev = dev->interface->dev;
01460     dev->vdev->fops = &v4l_stk11xx_fops;
01461     dev->vdev->release = video_device_release;
01462     dev->vdev->minor = -1;
01463 
01464     video_set_drvdata(dev->vdev, dev);
01465 
01466     err = video_register_device(dev->vdev, VFL_TYPE_GRABBER, -1);
01467 
01468     if (err)
01469         STK_ERROR("Video register fail !\n");
01470     else
01471         STK_INFO("Syntek USB2.0 Camera is now controlling video device /dev/video%d\n", dev->vdev->minor);
01472 
01473     return err;
01474 }
01475 
01476 
01486 int v4l_stk11xx_unregister_video_device(struct usb_stk11xx *dev)
01487 {
01488     STK_INFO("Syntek USB2.0 Camera release resources video device /dev/video%d\n", dev->vdev->minor);
01489 
01490     video_set_drvdata(dev->vdev, NULL);
01491     video_unregister_device(dev->vdev);
01492 
01493     return 0;
01494 }
01495 
01496 
01502 static struct v4l2_file_operations v4l_stk11xx_fops = {
01503     .owner = THIS_MODULE,
01504     .open = v4l_stk11xx_open,
01505     .release = v4l_stk11xx_release,
01506     .read = v4l_stk11xx_read,
01507     .poll = v4l_stk11xx_poll,
01508     .mmap = v4l_stk11xx_mmap,
01509     .ioctl = v4l_stk11xx_ioctl,
01510 };
01511