[PATCH 086/961] staging: easycap: add ALSA support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Mike Thomas <rmthomas@xxxxxxxxxxx>

This is necessary because some distributions are disabling OSS entirely.

Signed-off-by: Mike Thomas <rmthomas@xxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>
---
 drivers/staging/easycap/Kconfig                    |    2 +-
 drivers/staging/easycap/Makefile                   |   11 +-
 drivers/staging/easycap/easycap.h                  |   84 ++-
 drivers/staging/easycap/easycap_ioctl.c            |  272 +++---
 drivers/staging/easycap/easycap_ioctl.h            |    9 +
 drivers/staging/easycap/easycap_low.c              |   17 +-
 .../easycap/{easycap_debug.h => easycap_low.h}     |    9 +-
 drivers/staging/easycap/easycap_main.c             |  394 ++++---
 .../easycap/{easycap_standard.h => easycap_main.h} |   18 +-
 drivers/staging/easycap/easycap_settings.c         |    2 +-
 .../{easycap_standard.h => easycap_settings.h}     |   11 +-
 drivers/staging/easycap/easycap_sound.c            | 1214 +++++++++++++++++---
 drivers/staging/easycap/easycap_sound.h            |   14 +
 drivers/staging/easycap/easycap_testcard.c         |    4 +-
 .../{easycap_debug.h => easycap_testcard.h}        |    9 +-
 15 files changed, 1568 insertions(+), 502 deletions(-)
 copy drivers/staging/easycap/{easycap_debug.h => easycap_low.h} (86%)
 copy drivers/staging/easycap/{easycap_standard.h => easycap_main.h} (67%)
 rename drivers/staging/easycap/{easycap_standard.h => easycap_settings.h} (82%)
 rename drivers/staging/easycap/{easycap_debug.h => easycap_testcard.h} (85%)

diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
index bd96f39..eaa8a86 100644
--- a/drivers/staging/easycap/Kconfig
+++ b/drivers/staging/easycap/Kconfig
@@ -1,6 +1,6 @@
 config EASYCAP
 	tristate "EasyCAP USB ID 05e1:0408 support"
-	depends on USB && VIDEO_DEV
+	depends on USB && VIDEO_DEV && SND
 
 	---help---
 	  This is an integrated audio/video driver for EasyCAP cards with
diff --git a/drivers/staging/easycap/Makefile b/drivers/staging/easycap/Makefile
index f1f2fbe..977e153 100644
--- a/drivers/staging/easycap/Makefile
+++ b/drivers/staging/easycap/Makefile
@@ -1,14 +1,13 @@
+easycap-objs      := easycap_main.o easycap_low.o easycap_sound.o \
+		     easycap_ioctl.o easycap_settings.o easycap_testcard.o
 
-obj-$(CONFIG_EASYCAP)	+= easycap.o
-
-easycap-y	:= easycap_main.o easycap_low.o easycap_sound.o
-easycap-y	+= easycap_ioctl.o easycap_settings.o
-easycap-y	+= easycap_testcard.o
+obj-$(CONFIG_EASYCAP)       += easycap.o
 
 ccflags-y := -Wall
-# Impose all or none of the following:
 ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT
 ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H
 ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS
 ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL
+ccflags-y += -DEASYCAP_NEEDS_ALSA
+ccflags-y += -DEASYCAP_NEEDS_CARD_CREATE
 
diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h
index 063d447..111f53c 100644
--- a/drivers/staging/easycap/easycap.h
+++ b/drivers/staging/easycap/easycap.h
@@ -34,6 +34,8 @@
  *                EASYCAP_NEEDS_V4L2_DEVICE_H
  *                EASYCAP_NEEDS_V4L2_FOPS
  *                EASYCAP_NEEDS_UNLOCKED_IOCTL
+ *                EASYCAP_NEEDS_ALSA
+ *                EASYCAP_SILENT
  *
  *  IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
  *  OPTIONS.
@@ -57,9 +59,9 @@
  */
 /*---------------------------------------------------------------------------*/
 #undef  EASYCAP_TESTCARD
+#if (!defined(EASYCAP_NEEDS_ALSA))
 #undef  EASYCAP_TESTTONE
-#undef  NOREADBACK
-#undef  AUDIOTIME
+#endif /*EASYCAP_NEEDS_ALSA*/
 /*---------------------------------------------------------------------------*/
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -79,6 +81,16 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 
+#if defined(EASYCAP_NEEDS_ALSA)
+#include <linux/vmalloc.h>
+#include <linux/sound.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#endif /*EASYCAP_NEEDS_ALSA*/
 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
 #include <media/v4l2-dev.h>
@@ -112,7 +124,7 @@
 #define USB_EASYCAP_VENDOR_ID	0x05e1
 #define USB_EASYCAP_PRODUCT_ID	0x0408
 
-#define EASYCAP_DRIVER_VERSION "0.8.41"
+#define EASYCAP_DRIVER_VERSION "0.9.01"
 #define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
 
 #define USB_SKEL_MINOR_BASE     192
@@ -158,7 +170,8 @@
  */
 /*---------------------------------------------------------------------------*/
 #define AUDIO_ISOC_BUFFER_MANY 16
-#define AUDIO_ISOC_ORDER 3
+#define AUDIO_ISOC_ORDER 1
+#define AUDIO_ISOC_FRAMESPERDESC 32
 #define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
 /*---------------------------------------------------------------------------*/
 /*
@@ -166,6 +179,7 @@
  */
 /*---------------------------------------------------------------------------*/
 #define AUDIO_FRAGMENT_MANY 32
+#define PAGES_PER_AUDIO_FRAGMENT 4
 /*---------------------------------------------------------------------------*/
 /*
  *  IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
@@ -296,6 +310,7 @@ struct easycap {
 #define TELLTALE "expectedstring"
 char telltale[16];
 int isdongle;
+int minor;
 
 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
@@ -328,6 +343,7 @@ int done[FRAME_BUFFER_MANY];
 
 wait_queue_head_t wq_video;
 wait_queue_head_t wq_audio;
+wait_queue_head_t wq_trigger;
 
 int input;
 int polled;
@@ -429,6 +445,20 @@ int allocation_video_struct;
 int registered_video;
 /*---------------------------------------------------------------------------*/
 /*
+ *  ALSA
+ */
+/*---------------------------------------------------------------------------*/
+#if defined(EASYCAP_NEEDS_ALSA)
+struct snd_pcm_hardware alsa_hardware;
+struct snd_card *psnd_card;
+struct snd_pcm *psnd_pcm;
+struct snd_pcm_substream *psubstream;
+int dma_fill;
+int dma_next;
+int dma_read;
+#endif /*EASYCAP_NEEDS_ALSA*/
+/*---------------------------------------------------------------------------*/
+/*
  *  SOUND PROPERTIES
  */
 /*---------------------------------------------------------------------------*/
@@ -455,10 +485,10 @@ struct list_head *purb_audio_head;
  *  BUFFER INDICATORS
  */
 /*---------------------------------------------------------------------------*/
-int audio_fill;		/* Audio buffer being filled by easysnd_complete().  */
-			/*   Bumped only by easysnd_complete().              */
-int audio_read;		/* Audio buffer page being read by easysnd_read().   */
-			/*   Set by easysnd_read() to trail audio_fill by    */
+int audio_fill;		/* Audio buffer being filled by easycap_complete().  */
+			/*   Bumped only by easycap_complete().              */
+int audio_read;		/* Audio buffer page being read by easycap_read().   */
+			/*   Set by easycap_read() to trail audio_fill by    */
 			/*   one fragment.                                   */
 /*---------------------------------------------------------------------------*/
 /*
@@ -532,19 +562,39 @@ int              adjust_volume(struct easycap *, int);
  *  AUDIO FUNCTION PROTOTYPES
  */
 /*---------------------------------------------------------------------------*/
-void             easysnd_complete(struct urb *);
-ssize_t          easysnd_read(struct file *, char __user *, size_t, loff_t *);
-int              easysnd_open(struct inode *, struct file *);
-int              easysnd_release(struct inode *, struct file *);
-long             easysnd_ioctl_noinode(struct file *, unsigned int, \
+#if defined(EASYCAP_NEEDS_ALSA)
+int		easycap_alsa_probe(struct easycap *);
+
+void            easycap_alsa_complete(struct urb *);
+int		easycap_alsa_open(struct snd_pcm_substream *);
+int		easycap_alsa_close(struct snd_pcm_substream *);
+int		easycap_alsa_hw_params(struct snd_pcm_substream *, \
+						struct snd_pcm_hw_params *);
+int             easycap_alsa_vmalloc(struct snd_pcm_substream *, size_t);
+int		easycap_alsa_hw_free(struct snd_pcm_substream *);
+int		easycap_alsa_prepare(struct snd_pcm_substream *);
+int		easycap_alsa_ack(struct snd_pcm_substream *);
+int		easycap_alsa_trigger(struct snd_pcm_substream *, int);
+snd_pcm_uframes_t \
+		easycap_alsa_pointer(struct snd_pcm_substream *);
+struct page	*easycap_alsa_page(struct snd_pcm_substream *, unsigned long);
+
+#else
+void             easyoss_complete(struct urb *);
+ssize_t          easyoss_read(struct file *, char __user *, size_t, loff_t *);
+int              easyoss_open(struct inode *, struct file *);
+int              easyoss_release(struct inode *, struct file *);
+long             easyoss_ioctl_noinode(struct file *, unsigned int, \
 								unsigned long);
-int              easysnd_ioctl(struct inode *, struct file *, unsigned int, \
+int              easyoss_ioctl(struct inode *, struct file *, unsigned int, \
 								unsigned long);
-unsigned int     easysnd_poll(struct file *, poll_table *);
-void             easysnd_delete(struct kref *);
+unsigned int     easyoss_poll(struct file *, poll_table *);
+void             easyoss_delete(struct kref *);
+#endif /*EASYCAP_NEEDS_ALSA*/
+int              easycap_sound_setup(struct easycap *);
 int              submit_audio_urbs(struct easycap *);
 int              kill_audio_urbs(struct easycap *);
-void             easysnd_testtone(struct easycap *, int);
+void             easyoss_testtone(struct easycap *, int);
 int              audio_setup(struct easycap *);
 /*---------------------------------------------------------------------------*/
 /*
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
index 447953a..20d3033 100644
--- a/drivers/staging/easycap/easycap_ioctl.c
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -27,8 +27,6 @@
 
 #include <linux/smp_lock.h>
 #include "easycap.h"
-#include "easycap_debug.h"
-#include "easycap_standard.h"
 #include "easycap_ioctl.h"
 
 /*--------------------------------------------------------------------------*/
@@ -910,7 +908,7 @@ return -ENOENT;
  *                              peasycap->audio_interface, \
  *                              peasycap->audio_altsetting_off);
  *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
- *  -ESHUTDOWN.  THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT
+ *  -ESHUTDOWN.  THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
  *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
  */
 /*---------------------------------------------------------------------------*/
@@ -991,11 +989,12 @@ if (NULL == p) {
 }
 kd = isdongle(peasycap);
 if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
-		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
+	if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+		SAY("ERROR: cannot lock " \
+				"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 peasycap,
@@ -1007,24 +1006,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\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	p = peasycap->pusb_device;
 	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 {
@@ -1048,7 +1047,7 @@ case VIDIOC_QUERYCAP: {
 
 	if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
 		SAM("ERROR: bad driver version string\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	strcpy(&version[0], EASYCAP_DRIVER_VERSION);
@@ -1066,7 +1065,8 @@ case VIDIOC_QUERYCAP: {
 			if (0 != rc) {
 				SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
 								rc, p1);
-				mutex_unlock(&easycap_dongle[kd].mutex_video);
+				mutex_unlock(&easycapdc60_dongle[kd].\
+								mutex_video);
 				return -EINVAL;
 			}
 			k[i] = (int)lng;
@@ -1097,7 +1097,7 @@ case VIDIOC_QUERYCAP: {
 	}
 	if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
 					sizeof(struct v4l2_capability))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1111,7 +1111,7 @@ case VIDIOC_ENUMINPUT: {
 
 	if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
 					sizeof(struct v4l2_input))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1193,14 +1193,14 @@ case VIDIOC_ENUMINPUT: {
 	}
 	default: {
 		JOM(8, "%i=index: exhausts inputs\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	}
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
 						sizeof(struct v4l2_input))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1213,7 +1213,7 @@ case VIDIOC_G_INPUT: {
 	index = (__u32)peasycap->input;
 	JOM(8, "user is told: %i\n", index);
 	if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1227,7 +1227,7 @@ case VIDIOC_S_INPUT:
 	JOM(8, "VIDIOC_S_INPUT\n");
 
 	if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1240,7 +1240,7 @@ case VIDIOC_S_INPUT:
 
 	if ((0 > index) || (INPUT_MANY <= index)) {
 		JOM(8, "ERROR:  bad requested input: %i\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 
@@ -1249,7 +1249,7 @@ case VIDIOC_S_INPUT:
 		JOM(8, "newinput(.,%i) OK\n", (int)index);
 	} else {
 		SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1257,7 +1257,7 @@ case VIDIOC_S_INPUT:
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_ENUMAUDIO: {
 	JOM(8, "VIDIOC_ENUMAUDIO\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -1268,12 +1268,12 @@ case VIDIOC_ENUMAUDOUT: {
 
 	if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
 					sizeof(struct v4l2_audioout))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (0 != v4l2_audioout.index) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
@@ -1282,7 +1282,7 @@ case VIDIOC_ENUMAUDOUT: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
 					sizeof(struct v4l2_audioout))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1296,7 +1296,7 @@ case VIDIOC_QUERYCTRL: {
 
 	if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
 					sizeof(struct v4l2_queryctrl))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1313,12 +1313,12 @@ case VIDIOC_QUERYCTRL: {
 	}
 	if (0xFFFFFFFF == easycap_control[i1].id) {
 		JOM(8, "%i=index: exhausts controls\n", i1);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
 					sizeof(struct v4l2_queryctrl))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1326,7 +1326,7 @@ case VIDIOC_QUERYCTRL: {
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_QUERYMENU: {
 	JOM(8, "VIDIOC_QUERYMENU unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -1337,13 +1337,13 @@ case VIDIOC_G_CTRL: {
 	pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
 	if (!pv4l2_control) {
 		SAM("ERROR: out of memory\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -ENOMEM;
 	}
 	if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
 					sizeof(struct v4l2_control))) {
 		kfree(pv4l2_control);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1385,14 +1385,14 @@ case VIDIOC_G_CTRL: {
 		SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
 							pv4l2_control->id);
 		kfree(pv4l2_control);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	}
 	if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
 					sizeof(struct v4l2_control))) {
 		kfree(pv4l2_control);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	kfree(pv4l2_control);
@@ -1412,7 +1412,7 @@ case VIDIOC_S_CTRL:
 
 	if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
 					sizeof(struct v4l2_control))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1463,7 +1463,7 @@ case VIDIOC_S_CTRL:
 	default: {
 		SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
 							v4l2_control.id);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	}
@@ -1472,7 +1472,7 @@ case VIDIOC_S_CTRL:
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_S_EXT_CTRLS: {
 	JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -1484,7 +1484,7 @@ case VIDIOC_ENUM_FMT: {
 
 	if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
 					sizeof(struct v4l2_fmtdesc))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1539,13 +1539,13 @@ case VIDIOC_ENUM_FMT: {
 	}
 	default: {
 		JOM(8, "%i=index: exhausts formats\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	}
 	if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
 					sizeof(struct v4l2_fmtdesc))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1564,7 +1564,7 @@ case VIDIOC_ENUM_FRAMESIZES: {
 
 	if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
 					sizeof(struct v4l2_frmsizeenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1616,7 +1616,7 @@ case VIDIOC_ENUM_FRAMESIZES: {
 		}
 		default: {
 			JOM(8, "%i=index: exhausts framesizes\n", index);
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -EINVAL;
 		}
 		}
@@ -1674,14 +1674,14 @@ case VIDIOC_ENUM_FRAMESIZES: {
 		}
 		default: {
 			JOM(8, "%i=index: exhausts framesizes\n", index);
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -EINVAL;
 		}
 		}
 	}
 	if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
 					sizeof(struct v4l2_frmsizeenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1710,7 +1710,7 @@ case VIDIOC_ENUM_FRAMEINTERVALS: {
 
 	if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
 					sizeof(struct v4l2_frmivalenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1737,13 +1737,13 @@ case VIDIOC_ENUM_FRAMEINTERVALS: {
 	}
 	default: {
 		JOM(8, "%i=index: exhausts frameintervals\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	}
 	if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
 					sizeof(struct v4l2_frmivalenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1757,28 +1757,28 @@ case VIDIOC_G_FMT: {
 	pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
 	if (!pv4l2_format) {
 		SAM("ERROR: out of memory\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -ENOMEM;
 	}
 	pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
 	if (!pv4l2_pix_format) {
 		SAM("ERROR: out of memory\n");
 		kfree(pv4l2_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -ENOMEM;
 	}
 	if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
 					sizeof(struct v4l2_format))) {
 		kfree(pv4l2_format);
 		kfree(pv4l2_pix_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		kfree(pv4l2_format);
 		kfree(pv4l2_pix_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 
@@ -1794,7 +1794,7 @@ case VIDIOC_G_FMT: {
 					sizeof(struct v4l2_format))) {
 		kfree(pv4l2_format);
 		kfree(pv4l2_pix_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	kfree(pv4l2_format);
@@ -1819,7 +1819,7 @@ case VIDIOC_S_FMT: {
 
 	if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
 					sizeof(struct v4l2_format))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1831,11 +1831,11 @@ case VIDIOC_S_FMT: {
 					try);
 	if (0 > best_format) {
 		if (-EBUSY == best_format) {
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -EBUSY;
 		}
 		JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -ENOENT;
 	}
 /*...........................................................................*/
@@ -1848,7 +1848,7 @@ case VIDIOC_S_FMT: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
 					sizeof(struct v4l2_format))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1861,7 +1861,7 @@ case VIDIOC_CROPCAP: {
 
 	if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
 					sizeof(struct v4l2_cropcap))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1885,7 +1885,7 @@ case VIDIOC_CROPCAP: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
 					sizeof(struct v4l2_cropcap))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1894,14 +1894,14 @@ case VIDIOC_CROPCAP: {
 case VIDIOC_G_CROP:
 case VIDIOC_S_CROP: {
 	JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_QUERYSTD: {
 	JOM(8, "VIDIOC_QUERYSTD: " \
 			"EasyCAP is incapable of detecting standard\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 	break;
 }
@@ -1923,7 +1923,7 @@ case VIDIOC_ENUMSTD: {
 
 	if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
 					sizeof(struct v4l2_standard))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	index = v4l2_standard.index;
@@ -1945,7 +1945,7 @@ case VIDIOC_ENUMSTD: {
 	}
 	if (0xFFFF == peasycap_standard->mask) {
 		JOM(8, "%i=index: exhausts standards\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	JOM(8, "%i=index: %s\n", index, \
@@ -1957,7 +1957,7 @@ case VIDIOC_ENUMSTD: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
 					sizeof(struct v4l2_standard))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -1972,13 +1972,13 @@ case VIDIOC_G_STD: {
 	if (0 > peasycap->standard_offset) {
 		JOM(8, "%i=peasycap->standard_offset\n", \
 					peasycap->standard_offset);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EBUSY;
 	}
 
 	if (0 != copy_from_user(&std_id, (void __user *)arg, \
 						sizeof(v4l2_std_id))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -1990,7 +1990,7 @@ case VIDIOC_G_STD: {
 
 	if (0 != copy_to_user((void __user *)arg, &std_id, \
 						sizeof(v4l2_std_id))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -2004,7 +2004,7 @@ case VIDIOC_S_STD: {
 
 	if (0 != copy_from_user(&std_id, (void __user *)arg, \
 						sizeof(v4l2_std_id))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -2015,7 +2015,7 @@ case VIDIOC_S_STD: {
 	rc = adjust_standard(peasycap, std_id);
 	if (0 > rc) {
 		JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -ENOENT;
 	}
 	break;
@@ -2029,16 +2029,16 @@ case VIDIOC_REQBUFS: {
 
 	if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
 				sizeof(struct v4l2_requestbuffers))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	nbuffers = v4l2_requestbuffers.count;
@@ -2059,7 +2059,7 @@ case VIDIOC_REQBUFS: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
 				sizeof(struct v4l2_requestbuffers))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -2074,18 +2074,18 @@ case VIDIOC_QUERYBUF: {
 	if (peasycap->video_eof) {
 		JOM(8, "returning -EIO because  %i=video_eof\n", \
 							peasycap->video_eof);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EIO;
 	}
 
 	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	index = v4l2_buffer.index;
@@ -2117,7 +2117,7 @@ case VIDIOC_QUERYBUF: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	break;
@@ -2130,21 +2130,21 @@ case VIDIOC_QBUF: {
 
 	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	if (v4l2_buffer.index < 0 || \
 		 (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
@@ -2154,7 +2154,7 @@ case VIDIOC_QBUF: {
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -2187,18 +2187,18 @@ case VIDIOC_DQBUF:
 		JOM(8, "returning -EIO because  " \
 				"%i=video_idle  %i=video_eof\n", \
 				peasycap->video_idle, peasycap->video_eof);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EIO;
 	}
 
 	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 
@@ -2222,7 +2222,7 @@ case VIDIOC_DQBUF:
 
 	if (!peasycap->video_isoc_streaming) {
 		JOM(16, "returning -EIO because video urbs not streaming\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EIO;
 	}
 /*---------------------------------------------------------------------------*/
@@ -2239,18 +2239,19 @@ case VIDIOC_DQBUF:
 			if (-EIO == rcdq) {
 				JOM(8, "returning -EIO because " \
 						"dqbuf() returned -EIO\n");
-				mutex_unlock(&easycap_dongle[kd].mutex_video);
+				mutex_unlock(&easycapdc60_dongle[kd].\
+								mutex_video);
 				return -EIO;
 			}
 		} while (0 != rcdq);
 	} else {
 		if (peasycap->video_eof) {
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -EIO;
 		}
 	}
 	if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
-		SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
+		JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n", \
 					peasycap->done[peasycap->frame_read]);
 	}
 	peasycap->polled = 0;
@@ -2337,7 +2338,7 @@ case VIDIOC_DQBUF:
 
 	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
 						sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
@@ -2370,7 +2371,7 @@ case VIDIOC_STREAMON: {
 		peasycap->merit[i] = 0;
 	if ((struct usb_device *)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 -EFAULT;
 	}
 	submit_video_urbs(peasycap);
@@ -2386,7 +2387,7 @@ case VIDIOC_STREAMOFF: {
 
 	if ((struct usb_device *)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 -EFAULT;
 	}
 
@@ -2400,7 +2401,12 @@ case VIDIOC_STREAMOFF: {
 /*---------------------------------------------------------------------------*/
 	JOM(8, "calling wake_up on wq_video and wq_audio\n");
 	wake_up_interruptible(&(peasycap->wq_video));
+#if defined(EASYCAP_NEEDS_ALSA)
+	if (NULL != peasycap->psubstream)
+		snd_pcm_period_elapsed(peasycap->psubstream);
+#else
 	wake_up_interruptible(&(peasycap->wq_audio));
+#endif /*EASYCAP_NEEDS_ALSA*/
 /*---------------------------------------------------------------------------*/
 	break;
 }
@@ -2412,19 +2418,19 @@ case VIDIOC_G_PARM: {
 	pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
 	if (!pv4l2_streamparm) {
 		SAM("ERROR: out of memory\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -ENOMEM;
 	}
 	if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
 					sizeof(struct v4l2_streamparm))) {
 		kfree(pv4l2_streamparm);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 
 	if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		kfree(pv4l2_streamparm);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
 	pv4l2_streamparm->parm.capture.capability = 0;
@@ -2450,7 +2456,7 @@ case VIDIOC_G_PARM: {
 	if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
 					sizeof(struct v4l2_streamparm))) {
 		kfree(pv4l2_streamparm);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	kfree(pv4l2_streamparm);
@@ -2459,25 +2465,25 @@ case VIDIOC_G_PARM: {
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_S_PARM: {
 	JOM(8, "VIDIOC_S_PARM unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_G_AUDIO: {
 	JOM(8, "VIDIOC_G_AUDIO unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_S_AUDIO: {
 	JOM(8, "VIDIOC_S_AUDIO unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_S_TUNER: {
 	JOM(8, "VIDIOC_S_TUNER unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
@@ -2485,45 +2491,46 @@ case VIDIOC_G_FBUF:
 case VIDIOC_S_FBUF:
 case VIDIOC_OVERLAY: {
 	JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 case VIDIOC_G_TUNER: {
 	JOM(8, "VIDIOC_G_TUNER unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 case VIDIOC_G_FREQUENCY:
 case VIDIOC_S_FREQUENCY: {
 	JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -EINVAL;
 }
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 default: {
 	JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 	return -ENOIOCTLCMD;
 }
 }
-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);
 return 0;
 }
 /*****************************************************************************/
+#if !defined(EASYCAP_NEEDS_ALSA)
 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
 	(defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
 long
-easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
-	return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
+easyoss_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
+	return (long)easyoss_ioctl((struct inode *)NULL, file, cmd, arg);
 }
 #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 /*---------------------------------------------------------------------------*/
 int
-easysnd_ioctl(struct inode *inode, struct file *file,
+easyoss_ioctl(struct inode *inode, struct file *file,
 					unsigned int cmd, unsigned long arg)
 {
 struct easycap *peasycap;
@@ -2550,11 +2557,12 @@ if (NULL == p) {
 }
 kd = isdongle(peasycap);
 if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
-		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
+	if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
+		SAY("ERROR: cannot lock "
+				"easycapdc60_dongle[%i].mutex_audio\n", kd);
 		return -ERESTARTSYS;
 	}
-	JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+	JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
 /*---------------------------------------------------------------------------*/
 /*
  *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
@@ -2566,24 +2574,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
 		return -ERESTARTSYS;
 	if (NULL == file) {
 		SAY("ERROR:  file is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 	peasycap = file->private_data;
 	if (NULL == peasycap) {
 		SAY("ERROR:  peasycap is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 		SAY("ERROR: bad peasycap\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	p = peasycap->pusb_device;
 	if (NULL == peasycap->pusb_device) {
 		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 } else {
@@ -2614,7 +2622,7 @@ case SNDCTL_DSP_GETCAPS: {
 #endif /*UPSAMPLE*/
 
 	if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2636,7 +2644,7 @@ case SNDCTL_DSP_GETFMTS: {
 #endif /*UPSAMPLE*/
 
 	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2645,7 +2653,7 @@ case SNDCTL_DSP_SETFMT: {
 	int incoming, outgoing;
 	JOM(8, "SNDCTL_DSP_SETFMT\n");
 	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	JOM(8, "........... %i=incoming\n", incoming);
@@ -2668,10 +2676,10 @@ case SNDCTL_DSP_SETFMT: {
 		JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
 		if (0 != copy_to_user((void __user *)arg, &outgoing, \
 								sizeof(int))) {
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 			return -EFAULT;
 		}
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EINVAL ;
 	}
 	break;
@@ -2680,7 +2688,7 @@ case SNDCTL_DSP_STEREO: {
 	int incoming;
 	JOM(8, "SNDCTL_DSP_STEREO\n");
 	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	JOM(8, "........... %i=incoming\n", incoming);
@@ -2698,7 +2706,7 @@ case SNDCTL_DSP_STEREO: {
 #endif /*UPSAMPLE*/
 
 	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2707,7 +2715,7 @@ case SNDCTL_DSP_SPEED: {
 	int incoming;
 	JOM(8, "SNDCTL_DSP_SPEED\n");
 	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	JOM(8, "........... %i=incoming\n", incoming);
@@ -2725,7 +2733,7 @@ case SNDCTL_DSP_SPEED: {
 #endif /*UPSAMPLE*/
 
 	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2734,14 +2742,14 @@ case SNDCTL_DSP_GETTRIGGER: {
 	int incoming;
 	JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
 	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	JOM(8, "........... %i=incoming\n", incoming);
 
 	incoming = PCM_ENABLE_INPUT;
 	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2750,7 +2758,7 @@ case SNDCTL_DSP_SETTRIGGER: {
 	int incoming;
 	JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
 	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	JOM(8, "........... %i=incoming\n", incoming);
@@ -2767,13 +2775,13 @@ case SNDCTL_DSP_GETBLKSIZE: {
 	int incoming;
 	JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
 	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	JOM(8, "........... %i=incoming\n", incoming);
 	incoming = peasycap->audio_bytes_per_fragment;
 	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2790,7 +2798,7 @@ case SNDCTL_DSP_GETISPACE: {
 
 	if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
 								sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	break;
@@ -2802,18 +2810,18 @@ case 0x00005404:
 case 0x00005405:
 case 0x00005406: {
 	JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 	return -ENOIOCTLCMD;
 }
 default: {
 	JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 	return -ENOIOCTLCMD;
 }
 }
-mutex_unlock(&easycap_dongle[kd].mutex_audio);
+mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 return 0;
 }
+#endif /*EASYCAP_NEEDS_ALSA*/
 /*****************************************************************************/
 
-
diff --git a/drivers/staging/easycap/easycap_ioctl.h b/drivers/staging/easycap/easycap_ioctl.h
index 210cd62..938de37 100644
--- a/drivers/staging/easycap/easycap_ioctl.h
+++ b/drivers/staging/easycap/easycap_ioctl.h
@@ -24,5 +24,14 @@
  *
 */
 /*****************************************************************************/
+#if !defined(EASYCAP_IOCTL_H)
+#define EASYCAP_IOCTL_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
+extern struct easycap_standard easycap_standard[];
 extern struct easycap_format easycap_format[];
 extern struct v4l2_queryctrl easycap_control[];
+
+#endif /*EASYCAP_IOCTL_H*/
diff --git a/drivers/staging/easycap/easycap_low.c b/drivers/staging/easycap/easycap_low.c
index 28c4d1e..b618d4b 100644
--- a/drivers/staging/easycap/easycap_low.c
+++ b/drivers/staging/easycap/easycap_low.c
@@ -39,7 +39,7 @@
 /****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
+#include "easycap_low.h"
 
 /*--------------------------------------------------------------------------*/
 const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
@@ -1052,9 +1052,18 @@ rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),	\
 			(int)50000);
 
 JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0]));
-if (rc != (int)length)
-	SAY("ERROR: usb_control_msg returned %i\n", rc);
-
+if (rc != (int)length) {
+	switch (rc) {
+	case -EPIPE: {
+		SAY("usb_control_msg returned -EPIPE\n");
+		break;
+	}
+	default: {
+		SAY("ERROR: usb_control_msg returned %i\n", rc);
+		break;
+	}
+	}
+}
 /*--------------------------------------------------------------------------*/
 /*
  *  REGISTER 500:  SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
diff --git a/drivers/staging/easycap/easycap_debug.h b/drivers/staging/easycap/easycap_low.h
similarity index 86%
copy from drivers/staging/easycap/easycap_debug.h
copy to drivers/staging/easycap/easycap_low.h
index b6b5718..d2b69e9 100644
--- a/drivers/staging/easycap/easycap_debug.h
+++ b/drivers/staging/easycap/easycap_low.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 *                                                                            *
-*  easycap_debug.h                                                           *
+*  easycap_low.h                                                             *
 *                                                                            *
 *****************************************************************************/
 /*
@@ -24,6 +24,11 @@
  *
 */
 /*****************************************************************************/
+#if !defined(EASYCAP_LOW_H)
+#define EASYCAP_LOW_H
+
 extern int easycap_debug;
 extern int easycap_gain;
-extern struct easycap_dongle easycap_dongle[];
+extern struct easycap_dongle easycapdc60_dongle[];
+
+#endif /*EASYCAP_LOW_H*/
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
index 22cf02b..84128cf 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
diff --git a/drivers/staging/easycap/easycap_standard.h b/drivers/staging/easycap/easycap_main.h
similarity index 67%
copy from drivers/staging/easycap/easycap_standard.h
copy to drivers/staging/easycap/easycap_main.h
index cadc8d2..11fcbbc 100644
--- a/drivers/staging/easycap/easycap_standard.h
+++ b/drivers/staging/easycap/easycap_main.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 *                                                                            *
-*  easycap_standard.h                                                        *
+*  easycap_main.h                                                           *
 *                                                                            *
 *****************************************************************************/
 /*
@@ -24,4 +24,20 @@
  *
 */
 /*****************************************************************************/
+#if !defined(EASYCAP_MAIN_H)
+#define EASYCAP_MAIN_H
+
 extern struct easycap_standard easycap_standard[];
+extern struct easycap_format easycap_format[];
+extern struct v4l2_queryctrl easycap_control[];
+extern struct usb_driver easycap_usb_driver;
+#if defined(EASYCAP_NEEDS_ALSA)
+extern struct snd_pcm_ops easycap_alsa_ops;
+extern struct snd_pcm_hardware easycap_pcm_hardware;
+extern struct snd_card *psnd_card;
+#else
+extern struct usb_class_driver easyoss_class;
+extern const struct file_operations easyoss_fops;
+#endif /*EASYCAP_NEEDS_ALSA*/
+
+#endif /*EASYCAP_MAIN_H*/
diff --git a/drivers/staging/easycap/easycap_settings.c b/drivers/staging/easycap/easycap_settings.c
index df3f17d..0a23e27 100644
--- a/drivers/staging/easycap/easycap_settings.c
+++ b/drivers/staging/easycap/easycap_settings.c
@@ -26,7 +26,7 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
+#include "easycap_settings.h"
 
 /*---------------------------------------------------------------------------*/
 /*
diff --git a/drivers/staging/easycap/easycap_standard.h b/drivers/staging/easycap/easycap_settings.h
similarity index 82%
rename from drivers/staging/easycap/easycap_standard.h
rename to drivers/staging/easycap/easycap_settings.h
index cadc8d2..5fe6f07 100644
--- a/drivers/staging/easycap/easycap_standard.h
+++ b/drivers/staging/easycap/easycap_settings.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 *                                                                            *
-*  easycap_standard.h                                                        *
+*  easycap_settings.h                                                        *
 *                                                                            *
 *****************************************************************************/
 /*
@@ -24,4 +24,11 @@
  *
 */
 /*****************************************************************************/
-extern struct easycap_standard easycap_standard[];
+#if !defined(EASYCAP_SETTINGS_H)
+#define EASYCAP_SETTINGS_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
+
+#endif /*EASYCAP_SETTINGS_H*/
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c
index 24d8bb4..0507ea1 100644
--- a/drivers/staging/easycap/easycap_sound.c
+++ b/drivers/staging/easycap/easycap_sound.c
@@ -29,9 +29,890 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
 #include "easycap_sound.h"
 
+#if defined(EASYCAP_NEEDS_ALSA)
+/*--------------------------------------------------------------------------*/
+/*
+ *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
+ */
+/*--------------------------------------------------------------------------*/
+static const struct snd_pcm_hardware alsa_hardware = {
+	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP           |
+		SNDRV_PCM_INFO_INTERLEAVED    |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
+	.rate_min = 32000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * \
+						AUDIO_FRAGMENT_MANY,
+	.period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
+	.period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
+	.periods_min = AUDIO_FRAGMENT_MANY,
+	.periods_max = AUDIO_FRAGMENT_MANY * 2,
+};
+
+static struct snd_pcm_ops easycap_alsa_pcm_ops = {
+	.open      = easycap_alsa_open,
+	.close     = easycap_alsa_close,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.hw_params = easycap_alsa_hw_params,
+	.hw_free   = easycap_alsa_hw_free,
+	.prepare   = easycap_alsa_prepare,
+	.ack       = easycap_alsa_ack,
+	.trigger   = easycap_alsa_trigger,
+	.pointer   = easycap_alsa_pointer,
+	.page      = easycap_alsa_page,
+};
+
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  THE FUNCTION snd_card_create() HAS  THIS_MODULE  AS AN ARGUMENT.  THIS
+ *  MEANS MODULE easycap.  BEWARE.
+*/
+/*---------------------------------------------------------------------------*/
+int
+easycap_alsa_probe(struct easycap *peasycap)
+{
+int rc;
+struct snd_card *psnd_card;
+struct snd_pcm *psnd_pcm;
+
+if (NULL == peasycap) {
+	SAY("ERROR: peasycap is NULL\n");
+	return -ENODEV;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return -EFAULT;
+}
+if (0 > peasycap->minor) {
+	SAY("ERROR: no minor\n");
+	return -ENODEV;
+}
+
+peasycap->alsa_hardware = alsa_hardware;
+if (true == peasycap->microphone) {
+	peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
+	peasycap->alsa_hardware.rate_min = 32000;
+	peasycap->alsa_hardware.rate_max = 32000;
+} else {
+	peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
+	peasycap->alsa_hardware.rate_min = 48000;
+	peasycap->alsa_hardware.rate_max = 48000;
+}
+
+#if defined(EASYCAP_NEEDS_CARD_CREATE)
+	if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa", \
+					THIS_MODULE, 0, \
+					&psnd_card)) {
+		SAY("ERROR: Cannot do ALSA snd_card_create()\n");
+		return -EFAULT;
+	}
+#else
+	psnd_card = snd_card_new(SNDRV_DEFAULT_IDX1, "easycap_alsa", \
+							THIS_MODULE, 0);
+	if (NULL == psnd_card) {
+		SAY("ERROR: Cannot do ALSA snd_card_new()\n");
+		return -EFAULT;
+	}
+#endif /*EASYCAP_NEEDS_CARD_CREATE*/
+
+	sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
+	strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
+	strcpy(&psnd_card->shortname[0], "easycap_alsa");
+	sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
+
+	psnd_card->dev = &peasycap->pusb_device->dev;
+	psnd_card->private_data = peasycap;
+	peasycap->psnd_card = psnd_card;
+
+	rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
+	if (0 != rc) {
+		SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
+		snd_card_free(psnd_card);
+		return -EFAULT;
+	}
+
+	snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE, \
+							&easycap_alsa_pcm_ops);
+	psnd_pcm->info_flags = 0;
+	strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
+	psnd_pcm->private_data = peasycap;
+	peasycap->psnd_pcm = psnd_pcm;
+	peasycap->psubstream = (struct snd_pcm_substream *)NULL;
+
+	rc = snd_card_register(psnd_card);
+	if (0 != rc) {
+		SAM("ERROR: Cannot do ALSA snd_card_register()\n");
+		snd_card_free(psnd_card);
+		return -EFAULT;
+	} else {
+	;
+	SAM("registered %s\n", &psnd_card->id[0]);
+	}
+return 0;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
+ *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
+ *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
+ */
+/*---------------------------------------------------------------------------*/
+void
+easycap_alsa_complete(struct urb *purb)
+{
+struct easycap *peasycap;
+struct snd_pcm_substream *pss;
+struct snd_pcm_runtime *prt;
+int dma_bytes, fragment_bytes;
+int isfragment;
+__u8 *p1, *p2;
+__s16 s16;
+int i, j, more, much, rc;
+#if defined(UPSAMPLE)
+int k;
+__s16 oldaudio, newaudio, delta;
+#endif /*UPSAMPLE*/
+
+JOT(16, "\n");
+
+if (NULL == purb) {
+	SAY("ERROR: purb is NULL\n");
+	return;
+}
+peasycap = purb->context;
+if (NULL == peasycap) {
+	SAY("ERROR: peasycap is NULL\n");
+	return;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return;
+}
+much = 0;
+if (peasycap->audio_idle) {
+	JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n", \
+			peasycap->audio_idle, peasycap->audio_isoc_streaming);
+	if (peasycap->audio_isoc_streaming)
+		goto resubmit;
+}
+/*---------------------------------------------------------------------------*/
+pss = peasycap->psubstream;
+if (NULL == pss)
+	goto resubmit;
+prt = pss->runtime;
+if (NULL == prt)
+	goto resubmit;
+dma_bytes = (int)prt->dma_bytes;
+if (0 == dma_bytes)
+	goto resubmit;
+fragment_bytes = 4 * ((int)prt->period_size);
+if (0 == fragment_bytes)
+	goto resubmit;
+/* -------------------------------------------------------------------------*/
+if (purb->status) {
+	if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
+		JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
+		return;
+	}
+	SAM("ERROR: non-zero urb status:\n");
+	switch (purb->status) {
+	case -EINPROGRESS: {
+		SAM("-EINPROGRESS\n");
+		break;
+	}
+	case -ENOSR: {
+		SAM("-ENOSR\n");
+		break;
+	}
+	case -EPIPE: {
+		SAM("-EPIPE\n");
+		break;
+	}
+	case -EOVERFLOW: {
+		SAM("-EOVERFLOW\n");
+		break;
+	}
+	case -EPROTO: {
+		SAM("-EPROTO\n");
+		break;
+	}
+	case -EILSEQ: {
+		SAM("-EILSEQ\n");
+		break;
+	}
+	case -ETIMEDOUT: {
+		SAM("-ETIMEDOUT\n");
+		break;
+	}
+	case -EMSGSIZE: {
+		SAM("-EMSGSIZE\n");
+		break;
+	}
+	case -EOPNOTSUPP: {
+		SAM("-EOPNOTSUPP\n");
+		break;
+	}
+	case -EPFNOSUPPORT: {
+		SAM("-EPFNOSUPPORT\n");
+		break;
+	}
+	case -EAFNOSUPPORT: {
+		SAM("-EAFNOSUPPORT\n");
+		break;
+	}
+	case -EADDRINUSE: {
+		SAM("-EADDRINUSE\n");
+		break;
+	}
+	case -EADDRNOTAVAIL: {
+		SAM("-EADDRNOTAVAIL\n");
+		break;
+	}
+	case -ENOBUFS: {
+		SAM("-ENOBUFS\n");
+		break;
+	}
+	case -EISCONN: {
+		SAM("-EISCONN\n");
+		break;
+	}
+	case -ENOTCONN: {
+		SAM("-ENOTCONN\n");
+		break;
+	}
+	case -ESHUTDOWN: {
+		SAM("-ESHUTDOWN\n");
+		break;
+	}
+	case -ENOENT: {
+		SAM("-ENOENT\n");
+		break;
+	}
+	case -ECONNRESET: {
+		SAM("-ECONNRESET\n");
+		break;
+	}
+	case -ENOSPC: {
+		SAM("ENOSPC\n");
+		break;
+	}
+	default: {
+		SAM("unknown error: %i\n", purb->status);
+		break;
+	}
+	}
+	goto resubmit;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ *  PROCEED HERE WHEN NO ERROR
+ */
+/*---------------------------------------------------------------------------*/
+
+#if defined(UPSAMPLE)
+oldaudio = peasycap->oldaudio;
+#endif /*UPSAMPLE*/
+
+for (i = 0;  i < purb->number_of_packets; i++) {
+	switch (purb->iso_frame_desc[i].status) {
+	case  0: {
+		break;
+	}
+	case -ENOENT: {
+		SAM("-ENOENT\n");
+		break;
+	}
+	case -EINPROGRESS: {
+		SAM("-EINPROGRESS\n");
+		break;
+	}
+	case -EPROTO: {
+		SAM("-EPROTO\n");
+		break;
+	}
+	case -EILSEQ: {
+		SAM("-EILSEQ\n");
+		break;
+	}
+	case -ETIME: {
+		SAM("-ETIME\n");
+		break;
+	}
+	case -ETIMEDOUT: {
+		SAM("-ETIMEDOUT\n");
+		break;
+	}
+	case -EPIPE: {
+		SAM("-EPIPE\n");
+		break;
+	}
+	case -ECOMM: {
+		SAM("-ECOMM\n");
+		break;
+	}
+	case -ENOSR: {
+		SAM("-ENOSR\n");
+		break;
+	}
+	case -EOVERFLOW: {
+		SAM("-EOVERFLOW\n");
+		break;
+	}
+	case -EREMOTEIO: {
+		SAM("-EREMOTEIO\n");
+		break;
+	}
+	case -ENODEV: {
+		SAM("-ENODEV\n");
+		break;
+	}
+	case -EXDEV: {
+		SAM("-EXDEV\n");
+		break;
+	}
+	case -EINVAL: {
+		SAM("-EINVAL\n");
+		break;
+	}
+	case -ECONNRESET: {
+		SAM("-ECONNRESET\n");
+		break;
+	}
+	case -ENOSPC: {
+		SAM("-ENOSPC\n");
+		break;
+	}
+	case -ESHUTDOWN: {
+		SAM("-ESHUTDOWN\n");
+		break;
+	}
+	case -EPERM: {
+		SAM("-EPERM\n");
+		break;
+	}
+	default: {
+		SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
+		break;
+	}
+	}
+	if (!purb->iso_frame_desc[i].status) {
+		more = purb->iso_frame_desc[i].actual_length;
+		if (!more)
+			peasycap->audio_mt++;
+		else {
+			if (peasycap->audio_mt) {
+				JOM(12, "%4i empty audio urb frames\n", \
+							peasycap->audio_mt);
+				peasycap->audio_mt = 0;
+			}
+
+			p1 = (__u8 *)(purb->transfer_buffer + \
+					purb->iso_frame_desc[i].offset);
+
+/*---------------------------------------------------------------------------*/
+/*
+ *  COPY more BYTES FROM ISOC BUFFER TO THE DMA BUFFER,
+ *  CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
+ */
+/*---------------------------------------------------------------------------*/
+			while (more) {
+				if (0 > more) {
+					SAM("MISTAKE: more is negative\n");
+					return;
+				}
+				much = dma_bytes - peasycap->dma_fill;
+				if (0 > much) {
+					SAM("MISTAKE: much is negative\n");
+					return;
+				}
+				if (0 == much) {
+					peasycap->dma_fill = 0;
+					peasycap->dma_next = fragment_bytes;
+					JOM(8, "wrapped dma buffer\n");
+				}
+				if (false == peasycap->microphone) {
+					if (much > more)
+						much = more;
+					memcpy(prt->dma_area + \
+						peasycap->dma_fill, \
+								p1, much);
+					p1 += much;
+					more -= much;
+				} else {
+#if defined(UPSAMPLE)
+					if (much % 16)
+						JOM(8, "MISTAKE? much" \
+						" is not divisible by 16\n");
+					if (much > (16 * \
+							more))
+						much = 16 * \
+							more;
+					p2 = (__u8 *)(prt->dma_area + \
+						peasycap->dma_fill);
+
+					for (j = 0;  j < (much/16);  j++) {
+						newaudio =  ((int) *p1) - 128;
+						newaudio = 128 * \
+								newaudio;
+
+						delta = (newaudio - oldaudio) \
+									/ 4;
+						s16 = oldaudio + delta;
+
+						for (k = 0;  k < 4;  k++) {
+							*p2 = (0x00FF & s16);
+							*(p2 + 1) = (0xFF00 & \
+								s16) >> 8;
+							p2 += 2;
+							*p2 = (0x00FF & s16);
+							*(p2 + 1) = (0xFF00 & \
+								s16) >> 8;
+							p2 += 2;
+							s16 += delta;
+						}
+						p1++;
+						more--;
+						oldaudio = s16;
+					}
+#else /*!UPSAMPLE*/
+					if (much > (2 * more))
+						much = 2 * more;
+					p2 = (__u8 *)(prt->dma_area + \
+						peasycap->dma_fill);
+
+					for (j = 0;  j < (much / 2);  j++) {
+						s16 =  ((int) *p1) - 128;
+						s16 = 128 * \
+								s16;
+						*p2 = (0x00FF & s16);
+						*(p2 + 1) = (0xFF00 & s16) >> \
+									8;
+						p1++;  p2 += 2;
+						more--;
+					}
+#endif /*UPSAMPLE*/
+				}
+				peasycap->dma_fill += much;
+				if (peasycap->dma_fill >= peasycap->dma_next) {
+					isfragment = peasycap->dma_fill / \
+						fragment_bytes;
+					if (0 > isfragment) {
+						SAM("MISTAKE: isfragment is " \
+							"negative\n");
+						return;
+					}
+					peasycap->dma_read = (isfragment \
+						- 1) * fragment_bytes;
+					peasycap->dma_next = (isfragment \
+						+ 1) * fragment_bytes;
+					if (dma_bytes < peasycap->dma_next) {
+						peasycap->dma_next = \
+								fragment_bytes;
+					}
+					if (0 <= peasycap->dma_read) {
+						JOM(8, "snd_pcm_period_elap" \
+							"sed(), %i=" \
+							"isfragment\n", \
+							isfragment);
+						snd_pcm_period_elapsed(pss);
+					}
+				}
+			}
+		}
+	} else {
+		JOM(12, "discarding audio samples because " \
+			"%i=purb->iso_frame_desc[i].status\n", \
+				purb->iso_frame_desc[i].status);
+	}
+
+#if defined(UPSAMPLE)
+peasycap->oldaudio = oldaudio;
+#endif /*UPSAMPLE*/
+
+}
+/*---------------------------------------------------------------------------*/
+/*
+ *  RESUBMIT THIS URB
+ */
+/*---------------------------------------------------------------------------*/
+resubmit:
+if (peasycap->audio_isoc_streaming) {
+	rc = usb_submit_urb(purb, GFP_ATOMIC);
+	if (0 != rc) {
+		if ((-ENODEV != rc) && (-ENOENT != rc)) {
+			SAM("ERROR: while %i=audio_idle, " \
+				"usb_submit_urb() failed " \
+				"with rc:\n", peasycap->audio_idle);
+		}
+		switch (rc) {
+		case -ENODEV:
+		case -ENOENT:
+			break;
+		case -ENOMEM: {
+			SAM("-ENOMEM\n");
+			break;
+		}
+		case -ENXIO: {
+			SAM("-ENXIO\n");
+			break;
+		}
+		case -EINVAL: {
+			SAM("-EINVAL\n");
+			break;
+		}
+		case -EAGAIN: {
+			SAM("-EAGAIN\n");
+			break;
+		}
+		case -EFBIG: {
+			SAM("-EFBIG\n");
+			break;
+		}
+		case -EPIPE: {
+			SAM("-EPIPE\n");
+			break;
+		}
+		case -EMSGSIZE: {
+			SAM("-EMSGSIZE\n");
+			break;
+		}
+		case -ENOSPC: {
+			SAM("-ENOSPC\n");
+			break;
+		}
+		case -EPERM: {
+			SAM("-EPERM\n");
+			break;
+		}
+		default: {
+			SAM("unknown error: %i\n", rc);
+			break;
+		}
+		}
+		if (0 < peasycap->audio_isoc_streaming)
+			(peasycap->audio_isoc_streaming)--;
+	}
+}
+return;
+}
+/*****************************************************************************/
+int
+easycap_alsa_open(struct snd_pcm_substream *pss)
+{
+struct snd_pcm *psnd_pcm;
+struct snd_card *psnd_card;
+struct easycap *peasycap;
+
+JOT(4, "\n");
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+psnd_pcm = pss->pcm;
+if (NULL == psnd_pcm) {
+	SAY("ERROR:  psnd_pcm is NULL\n");
+	return -EFAULT;
+}
+psnd_card = psnd_pcm->card;
+if (NULL == psnd_card) {
+	SAY("ERROR:  psnd_card is NULL\n");
+	return -EFAULT;
+}
+
+peasycap = psnd_card->private_data;
+if (NULL == peasycap) {
+	SAY("ERROR:  peasycap is NULL\n");
+	return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return -EFAULT;
+}
+if (peasycap->psnd_card != psnd_card) {
+	SAM("ERROR: bad peasycap->psnd_card\n");
+	return -EFAULT;
+}
+if (NULL != peasycap->psubstream) {
+	SAM("ERROR: bad peasycap->psubstream\n");
+	return -EFAULT;
+}
+pss->private_data = peasycap;
+peasycap->psubstream = pss;
+pss->runtime->hw = peasycap->alsa_hardware;
+pss->runtime->private_data = peasycap;
+pss->private_data = peasycap;
+
+if (0 != easycap_sound_setup(peasycap)) {
+	JOM(4, "ending unsuccessfully\n");
+	return -EFAULT;
+}
+JOM(4, "ending successfully\n");
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_close(struct snd_pcm_substream *pss)
+{
+struct easycap *peasycap;
+
+JOT(4, "\n");
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+	SAY("ERROR:  peasycap is NULL\n");
+	return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return -EFAULT;
+}
+pss->private_data = NULL;
+peasycap->psubstream = (struct snd_pcm_substream *)NULL;
+JOT(4, "ending successfully\n");
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_hw_params(struct snd_pcm_substream *pss, \
+						struct snd_pcm_hw_params *phw)
+{
+int rc;
+
+JOT(4, "%i\n", (params_buffer_bytes(phw)));
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
+if (0 != rc)
+	return rc;
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
+{
+struct snd_pcm_runtime *prt;
+JOT(4, "\n");
+
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+prt = pss->runtime;
+if (NULL == prt) {
+	SAY("ERROR: substream.runtime is NULL\n");
+	return -EFAULT;
+}
+if (prt->dma_area) {
+	if (prt->dma_bytes > sz)
+		return 0;
+	vfree(prt->dma_area);
+}
+prt->dma_area = vmalloc(sz);
+if (NULL == prt->dma_area)
+	return -ENOMEM;
+prt->dma_bytes = sz;
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_hw_free(struct snd_pcm_substream *pss)
+{
+struct snd_pcm_runtime *prt;
+JOT(4, "\n");
+
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+prt = pss->runtime;
+if (NULL == prt) {
+	SAY("ERROR: substream.runtime is NULL\n");
+	return -EFAULT;
+}
+if (NULL != prt->dma_area) {
+	JOT(8, "0x%08lX=prt->dma_area\n", (unsigned long int)prt->dma_area);
+	vfree(prt->dma_area);
+	prt->dma_area = NULL;
+} else
+	JOT(8, "dma_area already freed\n");
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_prepare(struct snd_pcm_substream *pss)
+{
+struct easycap *peasycap;
+struct snd_pcm_runtime *prt;
+
+JOT(4, "\n");
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+prt = pss->runtime;
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+	SAY("ERROR:  peasycap is NULL\n");
+	return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return -EFAULT;
+}
+
+JOM(16, "ALSA decides %8i Hz=rate\n", (int)pss->runtime->rate);
+JOM(16, "ALSA decides %8i   =period_size\n", (int)pss->runtime->period_size);
+JOM(16, "ALSA decides %8i   =periods\n", (int)pss->runtime->periods);
+JOM(16, "ALSA decides %8i   =buffer_size\n", (int)pss->runtime->buffer_size);
+JOM(16, "ALSA decides %8i   =dma_bytes\n", (int)pss->runtime->dma_bytes);
+JOM(16, "ALSA decides %8i   =boundary\n", (int)pss->runtime->boundary);
+JOM(16, "ALSA decides %8i   =period_step\n", (int)pss->runtime->period_step);
+JOM(16, "ALSA decides %8i   =sample_bits\n", (int)pss->runtime->sample_bits);
+JOM(16, "ALSA decides %8i   =frame_bits\n", (int)pss->runtime->frame_bits);
+JOM(16, "ALSA decides %8i   =min_align\n", (int)pss->runtime->min_align);
+JOM(12, "ALSA decides %8i   =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
+JOM(12, "ALSA decides %8i   =hw_ptr_interrupt\n", \
+					(int)pss->runtime->hw_ptr_interrupt);
+if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
+	SAY("MISTAKE:  unexpected ALSA parameters\n");
+	return -ENOENT;
+}
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_ack(struct snd_pcm_substream *pss)
+{
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
+{
+struct easycap *peasycap;
+int retval;
+
+JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START, \
+						SNDRV_PCM_TRIGGER_STOP);
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+	SAY("ERROR:  peasycap is NULL\n");
+	return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return -EFAULT;
+}
+
+switch (cmd) {
+case SNDRV_PCM_TRIGGER_START: {
+	peasycap->audio_idle = 0;
+	break;
+}
+case SNDRV_PCM_TRIGGER_STOP: {
+	peasycap->audio_idle = 1;
+	break;
+}
+default:
+	retval = -EINVAL;
+}
+return 0;
+}
+/*****************************************************************************/
+snd_pcm_uframes_t
+easycap_alsa_pointer(struct snd_pcm_substream *pss)
+{
+struct easycap *peasycap;
+snd_pcm_uframes_t offset;
+
+JOT(16, "\n");
+if (NULL == pss) {
+	SAY("ERROR:  pss is NULL\n");
+	return -EFAULT;
+}
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+	SAY("ERROR:  peasycap is NULL\n");
+	return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+	SAY("ERROR: bad peasycap\n");
+	return -EFAULT;
+}
+if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
+	JOM(8, "returning -EIO because  " \
+			"%i=audio_idle  %i=audio_eof\n", \
+			peasycap->audio_idle, peasycap->audio_eof);
+	return -EIO;
+}
+/*---------------------------------------------------------------------------*/
+if (0 > peasycap->dma_read) {
+	JOM(8, "returning -EBUSY\n");
+	return -EBUSY;
+}
+offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
+JOM(8, "ALSA decides %8i   =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
+JOM(8, "ALSA decides %8i   =hw_ptr_interrupt\n", \
+					(int)pss->runtime->hw_ptr_interrupt);
+JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n", \
+			(int)offset, peasycap->dma_read, peasycap->dma_next);
+return offset;
+}
+/*****************************************************************************/
+struct page *
+easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
+{
+return vmalloc_to_page(pss->runtime->dma_area + offset);
+}
+/*****************************************************************************/
+
+#else /*!EASYCAP_NEEDS_ALSA*/
+
+/*****************************************************************************/
+/****************************                       **************************/
+/****************************   Open Sound System   **************************/
+/****************************                       **************************/
+/*****************************************************************************/
+/*--------------------------------------------------------------------------*/
+/*
+ *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
+ */
+/*--------------------------------------------------------------------------*/
+const struct file_operations easyoss_fops = {
+	.owner		= THIS_MODULE,
+	.open		= easyoss_open,
+	.release	= easyoss_release,
+#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
+	.unlocked_ioctl	= easyoss_ioctl_noinode,
+#else
+	.ioctl		= easyoss_ioctl,
+#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
+	.read		= easyoss_read,
+	.llseek		= no_llseek,
+};
+struct usb_class_driver easyoss_class = {
+.name = "usb/easyoss%d",
+.fops = &easyoss_fops,
+.minor_base = USB_SKEL_MINOR_BASE,
+};
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
@@ -41,7 +922,7 @@
  */
 /*---------------------------------------------------------------------------*/
 void
-easysnd_complete(struct urb *purb)
+easyoss_complete(struct urb *purb)
 {
 struct easycap *peasycap;
 struct data_buffer *paudio_buffer;
@@ -68,27 +949,26 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 	SAY("ERROR: bad peasycap\n");
 	return;
 }
-
 much = 0;
-
 if (peasycap->audio_idle) {
 	JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n", \
 			peasycap->audio_idle, peasycap->audio_isoc_streaming);
 	if (peasycap->audio_isoc_streaming) {
 		rc = usb_submit_urb(purb, GFP_ATOMIC);
 		if (0 != rc) {
-			if (-ENODEV != rc)
+			if (-ENODEV != rc && -ENOENT != rc) {
 				SAM("ERROR: while %i=audio_idle, " \
 					"usb_submit_urb() failed with rc:\n", \
 							peasycap->audio_idle);
+			}
 			switch (rc) {
+			case -ENODEV:
+			case -ENOENT:
+				break;
 			case -ENOMEM: {
 				SAM("-ENOMEM\n");
 				break;
 			}
-			case -ENODEV: {
-				break;
-			}
 			case -ENXIO: {
 				SAM("-ENXIO\n");
 				break;
@@ -117,8 +997,12 @@ if (peasycap->audio_idle) {
 				SAM("-ENOSPC\n");
 				break;
 			}
+			case -EPERM: {
+				SAM("-EPERM\n");
+				break;
+			}
 			default: {
-				SAM("unknown error: 0x%08X\n", rc);
+				SAM("unknown error: %i\n", rc);
 				break;
 			}
 			}
@@ -214,63 +1098,16 @@ if (purb->status) {
 		SAM("ENOSPC\n");
 		break;
 	}
-	default: {
-		SAM("unknown error code 0x%08X\n", purb->status);
+	case -EPERM: {
+		SAM("-EPERM\n");
 		break;
 	}
+	default: {
+		SAM("unknown error: %i\n", purb->status);
+		break;
 	}
-/*---------------------------------------------------------------------------*/
-/*
- *  RESUBMIT THIS URB AFTER AN ERROR
- *
- *  (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH)
- */
-/*---------------------------------------------------------------------------*/
-	if (peasycap->audio_isoc_streaming) {
-		rc = usb_submit_urb(purb, GFP_ATOMIC);
-		if (0 != rc) {
-			SAM("ERROR: while %i=audio_idle, usb_submit_urb() "
-				"failed with rc:\n", peasycap->audio_idle);
-			switch (rc) {
-			case -ENOMEM: {
-				SAM("-ENOMEM\n");
-				break;
-			}
-			case -ENODEV: {
-				SAM("-ENODEV\n");
-				break;
-			}
-			case -ENXIO: {
-				SAM("-ENXIO\n");
-				break;
-			}
-			case -EINVAL: {
-				SAM("-EINVAL\n");
-				break;
-			}
-			case -EAGAIN: {
-				SAM("-EAGAIN\n");
-				break;
-			}
-			case -EFBIG: {
-				SAM("-EFBIG\n");
-				break;
-			}
-			case -EPIPE: {
-				SAM("-EPIPE\n");
-				break;
-			}
-			case -EMSGSIZE: {
-				SAM("-EMSGSIZE\n");
-				break;
-			}
-			default: {
-				SAM("0x%08X\n", rc); break;
-			}
-			}
-		}
 	}
-	return;
+	goto resubmit;
 }
 /*---------------------------------------------------------------------------*/
 /*
@@ -286,6 +1123,10 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 	case  0: {
 		break;
 	}
+	case -ENODEV: {
+		SAM("-ENODEV\n");
+		break;
+	}
 	case -ENOENT: {
 		SAM("-ENOENT\n");
 		break;
@@ -330,10 +1171,6 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 		SAM("-EREMOTEIO\n");
 		break;
 	}
-	case -ENODEV: {
-		SAM("-ENODEV\n");
-		break;
-	}
 	case -EXDEV: {
 		SAM("-EXDEV\n");
 		break;
@@ -354,8 +1191,12 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 		SAM("-ESHUTDOWN\n");
 		break;
 	}
+	case -EPERM: {
+		SAM("-EPERM\n");
+		break;
+	}
 	default: {
-		SAM("unknown error:0x%08X\n", purb->iso_frame_desc[i].status);
+		SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
 		break;
 	}
 	}
@@ -371,7 +1212,7 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 			peasycap->audio_mt++;
 		else {
 			if (peasycap->audio_mt) {
-				JOM(16, "%4i empty audio urb frames\n", \
+				JOM(12, "%4i empty audio urb frames\n", \
 							peasycap->audio_mt);
 				peasycap->audio_mt = 0;
 			}
@@ -390,8 +1231,7 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 /*---------------------------------------------------------------------------*/
 			while (more) {
 				if (0 > more) {
-					SAM("easysnd_complete: MISTAKE: " \
-							"more is negative\n");
+					SAM("MISTAKE: more is negative\n");
 					return;
 				}
 				if (peasycap->audio_buffer_page_many <= \
@@ -412,7 +1252,7 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 							paudio_buffer->pgo)) {
 
 #if defined(TESTTONE)
-					easysnd_testtone(peasycap, \
+					easyoss_testtone(peasycap, \
 							peasycap->audio_fill);
 #endif /*TESTTONE*/
 
@@ -424,7 +1264,7 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 							peasycap->audio_fill)
 						peasycap->audio_fill = 0;
 
-					JOM(12, "bumped peasycap->" \
+					JOM(8, "bumped peasycap->" \
 							"audio_fill to %i\n", \
 							peasycap->audio_fill);
 
@@ -497,7 +1337,7 @@ for (i = 0;  i < purb->number_of_packets; i++) {
 						more--;
 						oldaudio = s16;
 					}
-#else
+#else /*!UPSAMPLE*/
 					if (much > (2 * more))
 						much = 2 * more;
 					p2 = (__u8 *)paudio_buffer->pto;
@@ -530,25 +1370,26 @@ peasycap->oldaudio = oldaudio;
 }
 /*---------------------------------------------------------------------------*/
 /*
- *  RESUBMIT THIS URB AFTER NO ERROR
+ *  RESUBMIT THIS URB
  */
 /*---------------------------------------------------------------------------*/
+resubmit:
 if (peasycap->audio_isoc_streaming) {
 	rc = usb_submit_urb(purb, GFP_ATOMIC);
 	if (0 != rc) {
-		if (-ENODEV != rc) {
+		if (-ENODEV != rc && -ENOENT != rc) {
 			SAM("ERROR: while %i=audio_idle, " \
-					"usb_submit_urb() failed " \
-					"with rc:\n", peasycap->audio_idle);
+				"usb_submit_urb() failed " \
+				"with rc:\n", peasycap->audio_idle);
 		}
 		switch (rc) {
+		case -ENODEV:
+		case -ENOENT:
+			break;
 		case -ENOMEM: {
 			SAM("-ENOMEM\n");
 			break;
 		}
-		case -ENODEV: {
-			break;
-		}
 		case -ENXIO: {
 			SAM("-ENXIO\n");
 			break;
@@ -577,8 +1418,12 @@ if (peasycap->audio_isoc_streaming) {
 			SAM("-ENOSPC\n");
 			break;
 		}
+		case -EPERM: {
+			SAM("-EPERM\n");
+			break;
+		}
 		default: {
-			SAM("unknown error: 0x%08X\n", rc);
+			SAM("unknown error: %i\n", rc);
 			break;
 		}
 		}
@@ -590,16 +1435,16 @@ return;
 /*---------------------------------------------------------------------------*/
 /*
  *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
- *  STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
+ *  STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
  *  HAVE AN IOCTL INTERFACE.
  */
 /*---------------------------------------------------------------------------*/
 int
-easysnd_open(struct inode *inode, struct file *file)
+easyoss_open(struct inode *inode, struct file *file)
 {
 struct usb_interface *pusb_interface;
 struct easycap *peasycap;
-int subminor, rc;
+int subminor;
 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
@@ -660,59 +1505,15 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 
 file->private_data = peasycap;
 
-/*---------------------------------------------------------------------------*/
-/*
- *  INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-JOM(4, "starting initialization\n");
-
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -ENODEV;
-}
-JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
-
-rc = audio_setup(peasycap);
-if (0 <= rc)
-	JOM(8, "audio_setup() returned %i\n", rc);
-else
-	JOM(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc);
-
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device has become NULL\n");
-	return -ENODEV;
-}
-/*---------------------------------------------------------------------------*/
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device has become NULL\n");
-	return -ENODEV;
+if (0 != easycap_sound_setup(peasycap)) {
+	;
+	;
 }
-rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
-					peasycap->audio_altsetting_on);
-JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
-					peasycap->audio_altsetting_on, rc);
-
-rc = wakeup_device(peasycap->pusb_device);
-if (0 == rc)
-	JOM(8, "wakeup_device() returned %i\n", rc);
-else
-	JOM(8, "ERROR: wakeup_device() returned %i\n", rc);
-
-peasycap->audio_eof = 0;
-peasycap->audio_idle = 0;
-
-peasycap->timeval1.tv_sec  = 0;
-peasycap->timeval1.tv_usec = 0;
-
-submit_audio_urbs(peasycap);
-
-JOM(4, "finished initialization\n");
 return 0;
 }
 /*****************************************************************************/
 int
-easysnd_release(struct inode *inode, struct file *file)
+easyoss_release(struct inode *inode, struct file *file)
 {
 struct easycap *peasycap;
 
@@ -736,7 +1537,7 @@ return 0;
 }
 /*****************************************************************************/
 ssize_t
-easysnd_read(struct file *file, char __user *puserspacebuffer, \
+easyoss_read(struct file *file, char __user *puserspacebuffer, \
 						size_t kount, loff_t *poff)
 {
 struct timeval timeval;
@@ -760,7 +1561,7 @@ size_t szret;
  */
 /*---------------------------------------------------------------------------*/
 
-JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
+JOT(8, "%5i=kount  %5i=*poff\n", (int)kount, (int)(*poff));
 
 if (NULL == file) {
 	SAY("ERROR:  file is NULL\n");
@@ -768,7 +1569,7 @@ if (NULL == file) {
 }
 peasycap = file->private_data;
 if (NULL == peasycap) {
-	SAY("ERROR in easysnd_read(): peasycap is NULL\n");
+	SAY("ERROR in easyoss_read(): peasycap is NULL\n");
 	return -EFAULT;
 }
 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
@@ -776,16 +1577,17 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 	return -EFAULT;
 }
 if (NULL == peasycap->pusb_device) {
-	SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n");
+	SAY("ERROR: peasycap->pusb_device is NULL\n");
 	return -EFAULT;
 }
 kd = isdongle(peasycap);
 if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&(easycap_dongle[kd].mutex_audio))) {
-		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
+	if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
+		SAY("ERROR: "
+		"cannot lock easycapdc60_dongle[%i].mutex_audio\n", kd);
 		return -ERESTARTSYS;
 	}
-	JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+	JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
 /*---------------------------------------------------------------------------*/
 /*
  *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
@@ -797,24 +1599,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
 		return -ERESTARTSYS;
 	if (NULL == file) {
 		SAY("ERROR:  file is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 	peasycap = file->private_data;
 	if (NULL == peasycap) {
 		SAY("ERROR:  peasycap is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		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_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 	if (NULL == peasycap->pusb_device) {
 		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 } else {
@@ -835,13 +1637,13 @@ else
 if ((0 > peasycap->audio_read) || \
 		(peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
 	SAM("ERROR: peasycap->audio_read out of range\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 	return -EFAULT;
 }
 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
 if ((struct data_buffer *)NULL == pdata_buffer) {
 	SAM("ERROR: pdata_buffer is NULL\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 	return -EFAULT;
 }
 JOM(12, "before wait, %i=frag read  %i=frag fill\n", \
@@ -853,7 +1655,7 @@ while ((fragment == (peasycap->audio_fill / \
 		(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
 	if (file->f_flags & O_NONBLOCK) {
 		JOM(16, "returning -EAGAIN as instructed\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EAGAIN;
 	}
 	rc = wait_event_interruptible(peasycap->wq_audio, \
@@ -863,25 +1665,25 @@ while ((fragment == (peasycap->audio_fill / \
 		(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
 	if (0 != rc) {
 		SAM("aborted by signal\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 	if (peasycap->audio_eof) {
 		JOM(8, "returning 0 because  %i=audio_eof\n", \
 							peasycap->audio_eof);
 		kill_audio_urbs(peasycap);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return 0;
 	}
 	if (peasycap->audio_idle) {
 		JOM(16, "returning 0 because  %i=audio_idle\n", \
 							peasycap->audio_idle);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return 0;
 	}
 	if (!peasycap->audio_isoc_streaming) {
 		JOM(16, "returning 0 because audio urbs not streaming\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return 0;
 	}
 }
@@ -889,22 +1691,23 @@ JOM(12, "after  wait, %i=frag read  %i=frag fill\n", \
 		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
 		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
 szret = (size_t)0;
+fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
 while (fragment == (peasycap->audio_read / \
 				peasycap->audio_pages_per_fragment)) {
 	if (NULL == pdata_buffer->pgo) {
 		SAM("ERROR: pdata_buffer->pgo is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	if (NULL == pdata_buffer->pto) {
 		SAM("ERROR: pdata_buffer->pto is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
 	if (0 > kount1) {
-		SAM("easysnd_read: MISTAKE: kount1 is negative\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		SAM("MISTAKE: kount1 is negative\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -ERESTARTSYS;
 	}
 	if (!kount1) {
@@ -922,23 +1725,23 @@ while (fragment == (peasycap->audio_read / \
 			(peasycap->audio_buffer_page_many <= \
 					peasycap->audio_read)) {
 			SAM("ERROR: peasycap->audio_read out of range\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 			return -EFAULT;
 		}
 		pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
 		if ((struct data_buffer *)NULL == pdata_buffer) {
 			SAM("ERROR: pdata_buffer is NULL\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 			return -EFAULT;
 		}
 		if (NULL == pdata_buffer->pgo) {
 			SAM("ERROR: pdata_buffer->pgo is NULL\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 			return -EFAULT;
 		}
 		if (NULL == pdata_buffer->pto) {
 			SAM("ERROR: pdata_buffer->pto is NULL\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 			return -EFAULT;
 		}
 		kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
@@ -967,7 +1770,7 @@ while (fragment == (peasycap->audio_read / \
 	rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
 	if (0 != rc) {
 		SAM("ERROR: copy_to_user() returned %li\n", rc);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 		return -EFAULT;
 	}
 	*poff += (loff_t)more;
@@ -1029,11 +1832,75 @@ if (!peasycap->timeval1.tv_sec) {
 JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
 peasycap->dnbydt = sdr.quotient;
 
+mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
 JOM(8, "returning %li\n", (long int)szret);
-mutex_unlock(&easycap_dongle[kd].mutex_audio);
 return szret;
 }
 /*****************************************************************************/
+
+#endif /*!EASYCAP_NEEDS_ALSA*/
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  COMMON AUDIO INITIALIZATION
+ */
+/*---------------------------------------------------------------------------*/
+int
+easycap_sound_setup(struct easycap *peasycap)
+{
+int rc;
+
+JOM(4, "starting initialization\n");
+
+if (NULL == peasycap) {
+	SAY("ERROR:  peasycap is NULL.\n");
+	return -EFAULT;
+}
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+	SAM("ERROR: peasycap->pusb_device is NULL\n");
+	return -ENODEV;
+}
+JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
+
+rc = audio_setup(peasycap);
+JOM(8, "audio_setup() returned %i\n", rc);
+
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+	SAM("ERROR: peasycap->pusb_device has become NULL\n");
+	return -ENODEV;
+}
+/*---------------------------------------------------------------------------*/
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+	SAM("ERROR: peasycap->pusb_device has become NULL\n");
+	return -ENODEV;
+}
+rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
+					peasycap->audio_altsetting_on);
+JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
+					peasycap->audio_altsetting_on, rc);
+
+rc = wakeup_device(peasycap->pusb_device);
+JOM(8, "wakeup_device() returned %i\n", rc);
+
+peasycap->audio_eof = 0;
+peasycap->audio_idle = 0;
+
+peasycap->timeval1.tv_sec  = 0;
+peasycap->timeval1.tv_usec = 0;
+
+submit_audio_urbs(peasycap);
+
+JOM(4, "finished initialization\n");
+return 0;
+}
+/*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  SUBMIT ALL AUDIO URBS.
@@ -1087,7 +1954,11 @@ if (!peasycap->audio_isoc_streaming) {
 					peasycap->audio_isoc_buffer[isbuf].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 = \
@@ -1109,14 +1980,18 @@ if (!peasycap->audio_isoc_streaming) {
 					SAM("ERROR: usb_submit_urb() failed" \
 							" for urb with rc:\n");
 					switch (rc) {
-					case -ENOMEM: {
-						SAM("-ENOMEM\n");
-						break;
-					}
 					case -ENODEV: {
 						SAM("-ENODEV\n");
 						break;
 					}
+					case -ENOENT: {
+						SAM("-ENOENT\n");
+						break;
+					}
+					case -ENOMEM: {
+						SAM("-ENOMEM\n");
+						break;
+					}
 					case -ENXIO: {
 						SAM("-ENXIO\n");
 						break;
@@ -1145,9 +2020,12 @@ if (!peasycap->audio_isoc_streaming) {
 						nospc++;
 						break;
 					}
+					case -EPERM: {
+						SAM("-EPERM\n");
+						break;
+					}
 					default: {
-						SAM("unknown error code %i\n",\
-								 rc);
+						SAM("unknown error: %i\n", rc);
 						break;
 					}
 					}
@@ -1179,7 +2057,7 @@ if (!peasycap->audio_isoc_streaming) {
 		}
 		peasycap->audio_isoc_streaming = 0;
 	} else {
-		peasycap->audio_isoc_streaming = 1;
+		peasycap->audio_isoc_streaming = m;
 		JOM(4, "submitted %i audio urbs\n", m);
 	}
 } else
diff --git a/drivers/staging/easycap/easycap_sound.h b/drivers/staging/easycap/easycap_sound.h
index 4912739..82104c8 100644
--- a/drivers/staging/easycap/easycap_sound.h
+++ b/drivers/staging/easycap/easycap_sound.h
@@ -24,5 +24,19 @@
  *
 */
 /*****************************************************************************/
+#if !defined(EASYCAP_SOUND_H)
+#define EASYCAP_SOUND_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
 extern struct easycap *peasycap;
 extern struct usb_driver easycap_usb_driver;
+#if defined(EASYCAP_NEEDS_ALSA)
+extern struct snd_pcm_hardware easycap_pcm_hardware;
+#else
+extern struct usb_class_driver easyoss_class;
+extern const struct file_operations easyoss_fops;
+#endif /*EASYCAP_NEEDS_ALSA*/
+
+#endif /*EASYCAP_SOUND_H*/
diff --git a/drivers/staging/easycap/easycap_testcard.c b/drivers/staging/easycap/easycap_testcard.c
index e27dfe9..1089603 100644
--- a/drivers/staging/easycap/easycap_testcard.c
+++ b/drivers/staging/easycap/easycap_testcard.c
@@ -26,7 +26,7 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
+#include "easycap_testcard.h"
 
 /*****************************************************************************/
 #define TESTCARD_BYTESPERLINE (2 * 720)
@@ -397,7 +397,7 @@ int tones[2048] = {
 };
 /*****************************************************************************/
 void
-easysnd_testtone(struct easycap *peasycap, int audio_fill)
+easyoss_testtone(struct easycap *peasycap, int audio_fill)
 {
 int i1;
 unsigned char *p2;
diff --git a/drivers/staging/easycap/easycap_debug.h b/drivers/staging/easycap/easycap_testcard.h
similarity index 85%
rename from drivers/staging/easycap/easycap_debug.h
rename to drivers/staging/easycap/easycap_testcard.h
index b6b5718..5159127 100644
--- a/drivers/staging/easycap/easycap_debug.h
+++ b/drivers/staging/easycap/easycap_testcard.h
@@ -1,6 +1,6 @@
 /*****************************************************************************
 *                                                                            *
-*  easycap_debug.h                                                           *
+*  easycap_testcard.h                                                        *
 *                                                                            *
 *****************************************************************************/
 /*
@@ -24,6 +24,11 @@
  *
 */
 /*****************************************************************************/
+#if !defined(EASYCAP_TESTCARD_H)
+#define EASYCAP_TESTCARD_H
+
 extern int easycap_debug;
 extern int easycap_gain;
-extern struct easycap_dongle easycap_dongle[];
+extern struct easycap_dongle easycapdc60_dongle[];
+
+#endif /*EASYCAP_TESTCARD_H*/
-- 
1.7.4.1

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux