summaryrefslogtreecommitdiff
path: root/drivers/staging/easycap/easycap_main.c
diff options
context:
space:
mode:
authorMike Thomas <rmthomas@sciolus.org>2011-01-10 18:41:11 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2011-01-21 12:25:55 -0800
commita9855917290fc40dbfd67d3ee06c190667d6c5b5 (patch)
treeb24a96d42526d681d04c6e678fe0649f4a25ba45 /drivers/staging/easycap/easycap_main.c
parentb54a28a418b2730bf61554864fee3fb24f79e182 (diff)
staging: easycap: add ALSA support
This is necessary because some distributions are disabling OSS entirely. 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.c394
1 files changed, 230 insertions, 164 deletions
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
index 22cf02b9e9d5..84128cf90007 100644
--- a/drivers/staging/easycap/easycap_main.c
+++ b/drivers/staging/easycap/easycap_main.c
@@ -29,30 +29,17 @@
/*****************************************************************************/
#include "easycap.h"
-#include "easycap_standard.h"
-#include "easycap_ioctl.h"
+#include "easycap_main.h"
int easycap_debug;
-static int easycap_bars;
+static int easycap_bars = 1;
int easycap_gain = 16;
module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
-/*---------------------------------------------------------------------------*/
-/*
- * dongle_this IS INDISPENSIBLY static BECAUSE FUNCTION easycap_usb_probe()
- * IS CALLED SUCCESSIVELY FOR INTERFACES 0, 1, 2 AND THE POINTER peasycap
- * ALLOCATED DURING THE PROBING OF INTERFACE 0 MUST BE REMEMBERED WHEN
- * PROBING INTERFACES 1 AND 2.
- *
- * IOCTL LOCKING IS DONE AT MODULE LEVEL, NOT DEVICE LEVEL.
-*/
-/*---------------------------------------------------------------------------*/
-
-struct easycap_dongle easycap_dongle[DONGLE_MANY];
-static int dongle_this;
-static int dongle_done;
+struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
+static struct mutex mutex_dongle;
/*---------------------------------------------------------------------------*/
/*
@@ -120,28 +107,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
- */
-/*--------------------------------------------------------------------------*/
-const struct file_operations easysnd_fops = {
- .owner = THIS_MODULE,
- .open = easysnd_open,
- .release = easysnd_release,
-#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
- .unlocked_ioctl = easysnd_ioctl_noinode,
-#else
- .ioctl = easysnd_ioctl,
-#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
- .read = easysnd_read,
- .llseek = no_llseek,
-};
-struct usb_class_driver easysnd_class = {
-.name = "usb/easysnd%d",
-.fops = &easysnd_fops,
-.minor_base = USB_SKEL_MINOR_BASE,
-};
/****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
@@ -155,7 +120,7 @@ int k;
if (NULL == peasycap)
return -2;
for (k = 0; k < DONGLE_MANY; k++) {
- if (easycap_dongle[k].peasycap == peasycap) {
+ if (easycapdc60_dongle[k].peasycap == peasycap) {
peasycap->isdongle = k;
return k;
}
@@ -1055,9 +1020,10 @@ for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
m++;
}
}
-JOM(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \
+JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n", \
m * (0x01 << AUDIO_ISOC_ORDER));
/*---------------------------------------------------------------------------*/
+#if !defined(EASYCAP_NEEDS_ALSA)
JOM(4, "freeing audio buffers.\n");
gone = 0;
for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
@@ -1068,7 +1034,8 @@ for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
gone++;
}
}
-JOM(4, "easysnd_delete(): audio buffers freed: %i pages\n", gone);
+JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
+#endif /*!EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
JOM(4, "freeing easycap structure.\n");
allocation_video_urb = peasycap->allocation_video_urb;
@@ -1081,12 +1048,20 @@ allocation_audio_struct = peasycap->allocation_audio_struct;
registered_audio = peasycap->registered_audio;
kfree(peasycap);
+
if (0 <= kd && DONGLE_MANY > kd) {
- easycap_dongle[kd].peasycap = (struct easycap *)NULL;
- JOT(4, " null-->easycap_dongle[%i].peasycap\n", kd);
- allocation_video_struct -= sizeof(struct easycap);
+ if (mutex_lock_interruptible(&mutex_dongle)) {
+ SAY("ERROR: cannot down mutex_dongle\n");
+ } else {
+ JOM(4, "locked mutex_dongle\n");
+ easycapdc60_dongle[kd].peasycap = (struct easycap *)NULL;
+ mutex_unlock(&mutex_dongle);
+ JOM(4, "unlocked mutex_dongle\n");
+ JOT(4, " null-->easycapdc60_dongle[%i].peasycap\n", kd);
+ allocation_video_struct -= sizeof(struct easycap);
+ }
} else {
- SAY("ERROR: cannot purge easycap_dongle[].peasycap");
+ SAY("ERROR: cannot purge easycapdc60_dongle[].peasycap");
}
/*---------------------------------------------------------------------------*/
SAY("%8i= video urbs after all deletions\n", allocation_video_urb);
@@ -1131,11 +1106,12 @@ if (NULL == peasycap->pusb_device) {
/*---------------------------------------------------------------------------*/
kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
- SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+ SAY("ERROR: cannot down "
+ "easycapdc60_dongle[%i].mutex_video\n", kd);
return -ERESTARTSYS;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
/*-------------------------------------------------------------------*/
/*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
@@ -1147,24 +1123,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
return -ERESTARTSYS;
if (NULL == file) {
SAY("ERROR: file is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
peasycap = file->private_data;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_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);
+ mutex_unlock(&easycapdc60_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);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
} else
@@ -1179,7 +1155,7 @@ if (0 <= kd && DONGLE_MANY > kd) {
/*---------------------------------------------------------------------------*/
rc = easycap_dqbuf(peasycap, 0);
peasycap->polled = 1;
-mutex_unlock(&easycap_dongle[kd].mutex_video);
+mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
if (0 == rc)
return POLLIN | POLLRDNORM;
else
@@ -3391,20 +3367,13 @@ return;
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
- *
- * FIXME
- *
- *
- * THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE EasyCAP
- * IS PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST.
- * IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops.
- *
- * THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE.
+ * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
+ * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
*/
/*---------------------------------------------------------------------------*/
int
easycap_usb_probe(struct usb_interface *pusb_interface, \
- const struct usb_device_id *id)
+ const struct usb_device_id *pusb_device_id)
{
struct usb_device *pusb_device, *pusb_device1;
struct usb_host_interface *pusb_host_interface;
@@ -3413,6 +3382,7 @@ struct usb_interface_descriptor *pusb_interface_descriptor;
struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
struct urb *purb;
struct easycap *peasycap;
+int ndong;
struct data_urb *pdata_urb;
size_t wMaxPacketSize;
int ISOCwMaxPacketSize;
@@ -3434,24 +3404,19 @@ int maxpacketsize;
__u16 mask;
__s32 value;
struct easycap_format *peasycap_format;
-
-JOT(4, "\n");
-
-if (!dongle_done) {
- dongle_done = 1;
- for (k = 0; k < DONGLE_MANY; k++) {
- easycap_dongle[k].peasycap = (struct easycap *)NULL;
- mutex_init(&easycap_dongle[k].mutex_video);
- mutex_init(&easycap_dongle[k].mutex_audio);
- }
-}
-
-peasycap = (struct easycap *)NULL;
+/*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*/
+/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
if ((struct usb_interface *)NULL == pusb_interface) {
SAY("ERROR: pusb_interface is NULL\n");
return -EFAULT;
}
+peasycap = (struct easycap *)NULL;
/*---------------------------------------------------------------------------*/
/*
* GET POINTER TO STRUCTURE usb_device
@@ -3472,9 +3437,7 @@ if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) {
JOT(4, "ERROR: pusb_device1 != pusb_device\n");
return -EFAULT;
}
-
JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
-
/*---------------------------------------------------------------------------*/
pusb_host_interface = pusb_interface->cur_altsetting;
if (NULL == pusb_host_interface) {
@@ -3553,9 +3516,6 @@ JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \
*
* THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
* INTERFACES 1 AND 2 ARE PROBED.
- *
- * IF TWO EasyCAPs ARE PLUGGED IN NEARLY SIMULTANEOUSLY THERE WILL
- * BE TROUBLE. BEWARE.
*/
/*---------------------------------------------------------------------------*/
if (0 == bInterfaceNumber) {
@@ -3580,6 +3540,7 @@ if (0 == bInterfaceNumber) {
* PERFORM URGENT INTIALIZATIONS ...
*/
/*---------------------------------------------------------------------------*/
+ peasycap->minor = -1;
strcpy(&peasycap->telltale[0], TELLTALE);
kref_init(&peasycap->kref);
JOM(8, "intf[%i]: after kref_init(..._video) " \
@@ -3588,29 +3549,43 @@ if (0 == bInterfaceNumber) {
init_waitqueue_head(&peasycap->wq_video);
init_waitqueue_head(&peasycap->wq_audio);
+ init_waitqueue_head(&peasycap->wq_trigger);
- for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) {
- if (NULL == easycap_dongle[dongle_this].peasycap) {
- if (0 == mutex_is_locked(&easycap_dongle\
- [dongle_this].mutex_video)) {
- if (0 == mutex_is_locked(&easycap_dongle\
- [dongle_this].mutex_audio)) {
- easycap_dongle\
- [dongle_this].peasycap = \
- peasycap;
- JOM(8, "intf[%i]: peasycap-->easycap" \
+ if (mutex_lock_interruptible(&mutex_dongle)) {
+ SAY("ERROR: cannot down mutex_dongle\n");
+ return -ERESTARTSYS;
+ } else {
+/*---------------------------------------------------------------------------*/
+ /*
+ * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
+ * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
+ *
+ * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
+ * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
+ * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
+ */
+/*---------------------------------------------------------------------------*/
+ for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+ if ((NULL == easycapdc60_dongle[ndong].peasycap) && \
+ (!mutex_is_locked(&easycapdc60_dongle\
+ [ndong].mutex_video)) && \
+ (!mutex_is_locked(&easycapdc60_dongle\
+ [ndong].mutex_audio))) {
+ easycapdc60_dongle[ndong].peasycap = peasycap;
+ peasycap->isdongle = ndong;
+ JOM(8, "intf[%i]: peasycap-->easycap" \
"_dongle[%i].peasycap\n", \
- bInterfaceNumber, dongle_this);
- break;
- }
+ bInterfaceNumber, ndong);
+ break;
}
}
+ if (DONGLE_MANY <= ndong) {
+ SAM("ERROR: too many dongles\n");
+ mutex_unlock(&mutex_dongle);
+ return -ENOMEM;
+ }
+ mutex_unlock(&mutex_dongle);
}
- if (DONGLE_MANY <= dongle_this) {
- SAM("ERROR: too many dongles\n");
- return -ENOMEM;
- }
-
peasycap->allocation_video_struct = sizeof(struct easycap);
peasycap->allocation_video_page = 0;
peasycap->allocation_video_urb = 0;
@@ -3778,26 +3753,56 @@ if (0 == bInterfaceNumber) {
JOM(4, "finished initialization\n");
} else {
/*---------------------------------------------------------------------------*/
- /*
- * FOR INTERFACES 1 AND 2 THE POINTER peasycap IS OBTAINED BY ASSUMING
- * THAT dongle_this HAS NOT CHANGED SINCE INTERFACE 0 WAS PROBED. IF
- * THIS IS NOT THE CASE, FOR EXAMPLE WHEN TWO EASYCAPs ARE PLUGGED IN
- * SIMULTANEOUSLY, THERE WILL BE SERIOUS TROUBLE.
- */
+/*
+ * FIXME
+ *
+ * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
+ * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
+ */
/*---------------------------------------------------------------------------*/
- if ((0 > dongle_this) || (DONGLE_MANY <= dongle_this)) {
- SAY("ERROR: bad dongle count\n");
- return -EFAULT;
+ for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+ if (pusb_device == easycapdc60_dongle[ndong].peasycap->\
+ pusb_device) {
+ peasycap = easycapdc60_dongle[ndong].peasycap;
+ JOT(8, "intf[%i]: easycapdc60_dongle[%i].peasycap-->" \
+ "peasycap\n", bInterfaceNumber, ndong);
+ break;
+ }
}
- peasycap = easycap_dongle[dongle_this].peasycap;
- JOT(8, "intf[%i]: easycap_dongle[%i].peasycap-->peasycap\n", \
- bInterfaceNumber, dongle_this);
-
- if ((struct easycap *)NULL == peasycap) {
+ if (DONGLE_MANY <= ndong) {
+ SAY("ERROR: peasycap is unknown when probing interface %i\n", \
+ bInterfaceNumber);
+ return -ENODEV;
+ }
+ if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL when probing interface %i\n", \
bInterfaceNumber);
- return -EFAULT;
+ return -ENODEV;
}
+#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 -ENODEV;
+ }
+ peasycap = (struct easycap *) \
+ container_of(pv4l2_device, struct easycap, v4l2_device);
+ }
+#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
+#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
}
/*---------------------------------------------------------------------------*/
if ((USB_CLASS_VIDEO == bInterfaceClass) || \
@@ -4368,6 +4373,7 @@ case 0: {
} else {
(peasycap->registered_video)++;
SAM("easycap attached to minor #%d\n", pusb_interface->minor);
+ peasycap->minor = pusb_interface->minor;
break;
}
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
@@ -4383,7 +4389,7 @@ case 0: {
}
/*---------------------------------------------------------------------------*/
/*
- * FIXME
+ * FIXME
*
*
* THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
@@ -4414,9 +4420,11 @@ case 0: {
(peasycap->registered_video)++;
SAM("registered with videodev: %i=minor\n", \
peasycap->video_device.minor);
+ peasycap->minor = peasycap->video_device.minor;
}
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
break;
}
/*--------------------------------------------------------------------------*/
@@ -4426,8 +4434,11 @@ case 0: {
*/
/*--------------------------------------------------------------------------*/
case 1: {
+#if defined(EASYCAP_SILENT)
+ return -ENOENT;
+#endif /*EASYCAP_SILENT*/
if (!peasycap) {
- SAM("ERROR: peasycap is NULL\n");
+ SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT;
}
/*--------------------------------------------------------------------------*/
@@ -4442,6 +4453,9 @@ case 1: {
}
/*--------------------------------------------------------------------------*/
case 2: {
+#if defined(EASYCAP_SILENT)
+ return -ENOENT;
+#endif /*EASYCAP_SILENT*/
if (!peasycap) {
SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT;
@@ -4467,14 +4481,14 @@ case 2: {
}
if (9 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk |= 0x02;
- SAM("hardware is FOUR-CVBS\n");
+ SAM("audio hardware is microphone\n");
peasycap->microphone = true;
- peasycap->audio_pages_per_fragment = 4;
+ peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
} else if (256 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk &= ~0x02;
- SAM("hardware is CVBS+S-VIDEO\n");
+ SAM("audio hardware is AC'97\n");
peasycap->microphone = false;
- peasycap->audio_pages_per_fragment = 4;
+ peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
} else {
SAM("hardware is unidentified:\n");
SAM("%i=audio_isoc_maxframesize\n", \
@@ -4496,7 +4510,7 @@ case 2: {
JOM(4, "%6i=audio_buffer_page_many\n", \
peasycap->audio_buffer_page_many);
- peasycap->audio_isoc_framesperdesc = 128;
+ peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
JOM(4, "%i=audio_isoc_framesperdesc\n", \
peasycap->audio_isoc_framesperdesc);
@@ -4548,6 +4562,7 @@ case 2: {
INIT_LIST_HEAD(&(peasycap->urb_audio_head));
peasycap->purb_audio_head = &(peasycap->urb_audio_head);
+#if !defined(EASYCAP_NEEDS_ALSA)
JOM(4, "allocating an audio buffer\n");
JOM(4, ".... scattered over %i pages\n", \
peasycap->audio_buffer_page_many);
@@ -4572,6 +4587,7 @@ case 2: {
peasycap->audio_fill = 0;
peasycap->audio_read = 0;
JOM(4, "allocation of audio buffer done: %i pages\n", k);
+#endif /*!EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i isoc audio buffers of size %i\n", \
AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
@@ -4646,7 +4662,11 @@ case 2: {
"peasycap->audio_isoc_buffer[.].pgo;\n");
JOM(4, " purb->transfer_buffer_length = %i;\n", \
peasycap->audio_isoc_buffer_size);
- JOM(4, " purb->complete = easysnd_complete;\n");
+#if defined(EASYCAP_NEEDS_ALSA)
+ JOM(4, " purb->complete = easycap_alsa_complete;\n");
+#else
+ JOM(4, " purb->complete = easyoss_complete;\n");
+#endif /*EASYCAP_NEEDS_ALSA*/
JOM(4, " purb->context = peasycap;\n");
JOM(4, " purb->start_frame = 0;\n");
JOM(4, " purb->number_of_packets = %i;\n", \
@@ -4669,7 +4689,11 @@ case 2: {
purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
purb->transfer_buffer_length = \
peasycap->audio_isoc_buffer_size;
- purb->complete = easysnd_complete;
+#if defined(EASYCAP_NEEDS_ALSA)
+ purb->complete = easycap_alsa_complete;
+#else
+ purb->complete = easyoss_complete;
+#endif /*EASYCAP_NEEDS_ALSA*/
purb->context = peasycap;
purb->start_frame = 0;
purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
@@ -4692,9 +4716,24 @@ case 2: {
* THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
*/
/*---------------------------------------------------------------------------*/
- rc = usb_register_dev(pusb_interface, &easysnd_class);
+#if defined(EASYCAP_NEEDS_ALSA)
+ JOM(4, "initializing ALSA card\n");
+
+ rc = easycap_alsa_probe(peasycap);
+ if (0 != rc) {
+ err("easycap_alsa_probe() returned %i\n", rc);
+ return -ENODEV;
+ } else {
+ JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",\
+ (int)peasycap->kref.refcount.counter);
+ kref_get(&peasycap->kref);
+ (peasycap->registered_audio)++;
+ }
+
+#else /*EASYCAP_NEEDS_ALSA*/
+ rc = usb_register_dev(pusb_interface, &easyoss_class);
if (0 != rc) {
- err("Not able to get a minor for this device.");
+ SAY("ERROR: usb_register_dev() failed\n");
usb_set_intfdata(pusb_interface, NULL);
return -ENODEV;
} else {
@@ -4708,7 +4747,9 @@ case 2: {
* LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
*/
/*---------------------------------------------------------------------------*/
- SAM("easysnd attached to minor #%d\n", pusb_interface->minor);
+ SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
+#endif /*EASYCAP_NEEDS_ALSA*/
+
break;
}
/*---------------------------------------------------------------------------*/
@@ -4721,7 +4762,7 @@ default: {
return -EINVAL;
}
}
-JOM(4, "ends successfully for interface %i\n", \
+SAM("ends successfully for interface %i\n", \
pusb_interface_descriptor->bInterfaceNumber);
return 0;
}
@@ -4730,6 +4771,8 @@ return 0;
/*
* WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
* UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
+ *
+ * THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
*/
/*---------------------------------------------------------------------------*/
void
@@ -4881,14 +4924,15 @@ switch (bInterfaceNumber) {
case 0: {
if (0 <= kd && DONGLE_MANY > kd) {
wake_up_interruptible(&peasycap->wq_video);
- JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].\
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", \
+ kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].\
mutex_video)) {
- SAY("ERROR: cannot lock easycap_dongle[%i]." \
+ SAY("ERROR: cannot lock easycapdc60_dongle[%i]." \
"mutex_video\n", kd);
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
} else
SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
/*---------------------------------------------------------------------------*/
@@ -4907,7 +4951,7 @@ case 0: {
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);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return;
}
v4l2_device_disconnect(&peasycap->v4l2_device);
@@ -4924,34 +4968,47 @@ case 0: {
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
if (0 <= kd && DONGLE_MANY > kd) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
- JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
}
break;
}
case 2: {
if (0 <= kd && DONGLE_MANY > kd) {
wake_up_interruptible(&peasycap->wq_audio);
- JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].\
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", \
+ kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].\
mutex_audio)) {
- SAY("ERROR: cannot lock easycap_dongle[%i]." \
+ SAY("ERROR: cannot lock easycapdc60_dongle[%i]." \
"mutex_audio\n", kd);
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
} else
SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
+#if defined(EASYCAP_NEEDS_ALSA)
- usb_deregister_dev(pusb_interface, &easysnd_class);
- (peasycap->registered_audio)--;
+
+ if (0 != snd_card_free(peasycap->psnd_card)) {
+ SAY("ERROR: snd_card_free() failed\n");
+ } else {
+ peasycap->psnd_card = (struct snd_card *)NULL;
+ (peasycap->registered_audio)--;
+ }
+
+
+#else /*EASYCAP_NEEDS_ALSA*/
+ usb_deregister_dev(pusb_interface, &easyoss_class);
+ (peasycap->registered_audio)--;
JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
- SAM("easysnd detached from minor #%d\n", minor);
+ SAM("easyoss detached from minor #%d\n", minor);
+#endif /*EASYCAP_NEEDS_ALSA*/
if (0 <= kd && DONGLE_MANY > kd) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
- JOM(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
}
break;
}
@@ -4961,6 +5018,7 @@ default:
/*---------------------------------------------------------------------------*/
/*
* CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
+ * (ALSO WHEN ALSA HAS BEEN IN USE)
*/
/*---------------------------------------------------------------------------*/
if (!peasycap->kref.refcount.counter) {
@@ -4970,32 +5028,34 @@ if (!peasycap->kref.refcount.counter) {
return;
}
if (0 <= kd && DONGLE_MANY > kd) {
- JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
- SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+ SAY("ERROR: cannot down "
+ "easycapdc60_dongle[%i].mutex_video\n", kd);
SAM("ending unsuccessfully: may cause memory leak\n");
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
- JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
- SAY("ERROR: cannot down easycap_dongle[%i].mutex_audio\n", kd);
- mutex_unlock(&(easycap_dongle[kd].mutex_video));
- JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
+ SAY("ERROR: cannot down "
+ "easycapdc60_dongle[%i].mutex_audio\n", kd);
+ mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
+ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
SAM("ending unsuccessfully: may cause memory leak\n");
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
}
JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", \
bInterfaceNumber, (int)peasycap->kref.refcount.counter);
kref_put(&peasycap->kref, easycap_delete);
JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
if (0 <= kd && DONGLE_MANY > kd) {
- mutex_unlock(&(easycap_dongle[kd].mutex_audio));
- JOT(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
- JOT(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+ mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
+ JOT(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+ JOT(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
}
/*---------------------------------------------------------------------------*/
JOM(4, "ends\n");
@@ -5005,25 +5065,31 @@ return;
int __init
easycap_module_init(void)
{
-int result;
+int k, rc;
SAY("========easycap=======\n");
JOT(4, "begins. %i=debug %i=bars %i=gain\n", easycap_debug, easycap_bars, \
easycap_gain);
SAY("version: " EASYCAP_DRIVER_VERSION "\n");
+
+mutex_init(&mutex_dongle);
+for (k = 0; k < DONGLE_MANY; k++) {
+ easycapdc60_dongle[k].peasycap = (struct easycap *)NULL;
+ mutex_init(&easycapdc60_dongle[k].mutex_video);
+ mutex_init(&easycapdc60_dongle[k].mutex_audio);
+}
/*---------------------------------------------------------------------------*/
/*
* REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
*/
/*---------------------------------------------------------------------------*/
JOT(4, "registering driver easycap\n");
-
-result = usb_register(&easycap_usb_driver);
-if (0 != result)
- SAY("ERROR: usb_register returned %i\n", result);
+rc = usb_register(&easycap_usb_driver);
+if (0 != rc)
+ SAY("ERROR: usb_register returned %i\n", rc);
JOT(4, "ends\n");
-return result;
+return rc;
}
/*****************************************************************************/
void __exit