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