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