summaryrefslogtreecommitdiff
path: root/drivers/staging/easycap/easycap_main.c
diff options
context:
space:
mode:
authorMike Thomas <rmthomas@sciolus.org>2010-11-07 20:11:36 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2010-11-09 16:31:16 -0800
commit268dfede46e24eef55a2ef7a10a462617936771e (patch)
tree18887c7c87c3c5a512a1fbd55530bf7cf2716e50 /drivers/staging/easycap/easycap_main.c
parentae59dad4fef271222d65ac6afe2889eb12ea6ca9 (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.c161
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)");