diff options
author | Mike Thomas <rmthomas@sciolus.org> | 2010-11-07 20:11:36 +0000 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-09 16:31:16 -0800 |
commit | 268dfede46e24eef55a2ef7a10a462617936771e (patch) | |
tree | 18887c7c87c3c5a512a1fbd55530bf7cf2716e50 /drivers/staging/easycap/easycap_main.c | |
parent | ae59dad4fef271222d65ac6afe2889eb12ea6ca9 (diff) |
staging/easycap: Improve interface to the videodev module
The changes here represent an intermediate step towards bringing the
driver within the V4L2 framework.
Signed-off-by: Mike Thomas <rmthomas@sciolus.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/easycap/easycap_main.c')
-rw-r--r-- | drivers/staging/easycap/easycap_main.c | 161 |
1 files changed, 135 insertions, 26 deletions
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c index 67ae755fcfac..25e41784f4e5 100644 --- a/drivers/staging/easycap/easycap_main.c +++ b/drivers/staging/easycap/easycap_main.c @@ -93,16 +93,15 @@ const struct file_operations easycap_fops = { .llseek = no_llseek, }; struct vm_operations_struct easycap_vm_ops = { -.open = easycap_vma_open, -.close = easycap_vma_close, -.fault = easycap_vma_fault, + .open = easycap_vma_open, + .close = easycap_vma_close, + .fault = easycap_vma_fault, }; struct usb_class_driver easycap_class = { -.name = "usb/easycap%d", -.fops = &easycap_fops, -.minor_base = USB_SKEL_MINOR_BASE, + .name = "usb/easycap%d", + .fops = &easycap_fops, + .minor_base = USB_SKEL_MINOR_BASE, }; - /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_NEEDS_V4L2_FOPS) @@ -121,7 +120,6 @@ const struct v4l2_file_operations v4l2_fops = { #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ - /*--------------------------------------------------------------------------*/ /* * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE @@ -147,7 +145,7 @@ struct usb_class_driver easysnd_class = { /****************************************************************************/ /*---------------------------------------------------------------------------*/ /* - * THIS ROUTINE DOES NOT DETECT MULTIPLE OCCURRENCES OF POINTER peasycap + * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap */ /*---------------------------------------------------------------------------*/ int @@ -215,6 +213,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return -EFAULT; +} if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; @@ -838,6 +840,10 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -EFAULT; } +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return -EFAULT; +} if (0 != kill_video_urbs(peasycap)) { SAM("ERROR: kill_video_urbs() failed\n"); return -EFAULT; @@ -867,6 +873,10 @@ if (NULL == peasycap) { SAY("ending unsuccessfully\n"); return -EFAULT; } +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return -EFAULT; +} if (0 != kill_video_urbs(peasycap)) { SAM("ERROR: kill_video_urbs() failed\n"); return -EFAULT; @@ -904,6 +914,10 @@ if (NULL == peasycap) { SAM("ERROR: peasycap is NULL: cannot perform deletions\n"); return; } +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return; +} kd = isdongle(peasycap); /*---------------------------------------------------------------------------*/ /* @@ -1026,8 +1040,6 @@ if ((struct list_head *)NULL != peasycap->purb_audio_head) { JOM(4, "%i audio data_urb structures freed\n", m); JOM(4, "setting peasycap->purb_audio_head=NULL\n"); peasycap->purb_audio_head = (struct list_head *)NULL; -} else { -JOM(4, "peasycap->purb_audio_head is NULL\n"); } /*---------------------------------------------------------------------------*/ JOM(4, "freeing audio isoc buffers.\n"); @@ -1108,6 +1120,10 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return -EFAULT; +} if (NULL == peasycap->pusb_device) { SAY("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; @@ -1140,10 +1156,16 @@ if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); return -ERESTARTSYS; } + if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", \ + (unsigned long int) peasycap); + mutex_unlock(&easycap_dongle[kd].mutex_video); + return -ERESTARTSYS; + } if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); mutex_unlock(&easycap_dongle[kd].mutex_video); - return -ERESTARTSYS; + return -ERESTARTSYS; } } else /*-------------------------------------------------------------------*/ @@ -2687,11 +2709,16 @@ easycap_vma_open(struct vm_area_struct *pvma) struct easycap *peasycap; peasycap = pvma->vm_private_data; -if (NULL != peasycap) - peasycap->vma_many++; - +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return; +} +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return; +} +peasycap->vma_many++; JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); - return; } /*****************************************************************************/ @@ -2701,10 +2728,16 @@ easycap_vma_close(struct vm_area_struct *pvma) struct easycap *peasycap; peasycap = pvma->vm_private_data; -if (NULL != peasycap) { - peasycap->vma_many--; - JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return; +} +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return; } +peasycap->vma_many--; +JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); return; } /*****************************************************************************/ @@ -2820,10 +2853,12 @@ if (NULL == peasycap) { SAY("ERROR: easycap_complete(): peasycap is NULL\n"); return; } - +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return; +} if (peasycap->video_eof) return; - for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) break; @@ -3545,6 +3580,7 @@ if (0 == bInterfaceNumber) { * PERFORM URGENT INTIALIZATIONS ... */ /*---------------------------------------------------------------------------*/ + strcpy(&peasycap->telltale[0], TELLTALE); kref_init(&peasycap->kref); JOM(8, "intf[%i]: after kref_init(..._video) " \ "%i=peasycap->kref.refcount.counter\n", \ @@ -4299,6 +4335,26 @@ case 0: { */ /*--------------------------------------------------------------------------*/ usb_set_intfdata(pusb_interface, peasycap); +/*---------------------------------------------------------------------------*/ +/* + * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER, + * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE + * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH. + * BEWARE. +*/ +/*---------------------------------------------------------------------------*/ +#if defined(PREFER_NTSC) + peasycap->ntsc = true; + JOM(8, "defaulting initially to NTSC\n"); +#else + peasycap->ntsc = false; + JOM(8, "defaulting initially to PAL\n"); +#endif /*PREFER_NTSC*/ + rc = reset(peasycap); + if (0 != rc) { + SAM("ERROR: reset() returned %i\n", rc); + return -EFAULT; + } /*--------------------------------------------------------------------------*/ /* * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. @@ -4687,6 +4743,13 @@ struct easycap *peasycap; struct list_head *plist_head; struct data_urb *pdata_urb; int minor, m, kd; +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#if defined(EASYCAP_IS_VIDEODEV_CLIENT) +#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) +struct v4l2_device *pv4l2_device; +#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ JOT(4, "\n"); @@ -4717,6 +4780,38 @@ if (NULL == peasycap) { return; } /*---------------------------------------------------------------------------*/ +#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) +# +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +#else +#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) +/*---------------------------------------------------------------------------*/ +/* + * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS + * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), + * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. + * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. +*/ +/*---------------------------------------------------------------------------*/ +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + pv4l2_device = usb_get_intfdata(pusb_interface); + if ((struct v4l2_device *)NULL == pv4l2_device) { + SAY("ERROR: pv4l2_device is NULL\n"); + return; + } + peasycap = (struct easycap *) \ + container_of(pv4l2_device, struct easycap, v4l2_device); +} +#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ +# +#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ +/*---------------------------------------------------------------------------*/ +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + return; +} +/*---------------------------------------------------------------------------*/ /* * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE. */ @@ -4806,14 +4901,28 @@ case 0: { JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); SAM("easycap detached from minor #%d\n", minor); } -/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ +/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #else +#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) + if (!peasycap->v4l2_device.name[0]) { + SAM("ERROR: peasycap->v4l2_device.name is empty\n"); + if (0 <= kd && DONGLE_MANY > kd) + mutex_unlock(&easycap_dongle[kd].mutex_video); + return; + } + v4l2_device_disconnect(&peasycap->v4l2_device); + JOM(4, "v4l2_device_disconnect() OK\n"); + v4l2_device_unregister(&peasycap->v4l2_device); + JOM(4, "v4l2_device_unregister() OK\n"); +#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ + video_unregister_device(&peasycap->video_device); - JOM(4, "unregistered with videodev: %i=minor\n", \ - peasycap->video_device.minor); + JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber); (peasycap->registered_video)--; -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + JOM(4, "unregistered with videodev: %i=minor\n", minor); #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ +/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ + if (0 <= kd && DONGLE_MANY > kd) { mutex_unlock(&easycap_dongle[kd].mutex_video); JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); @@ -4941,7 +5050,7 @@ MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); MODULE_VERSION(EASYCAP_DRIVER_VERSION); #if defined(EASYCAP_DEBUG) -MODULE_PARM_DESC(debug, "Debug level: 0 (default),1,2,..."); +MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9"); #endif /*EASYCAP_DEBUG*/ MODULE_PARM_DESC(bars, \ "Testcard bars on input signal failure: 0=>no, 1=>yes(default)"); |