]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
staging/easycap: make OSS compilation optional instead of ALSA
authorTomas Winkler <tomas.winkler@intel.com>
Mon, 24 Jan 2011 15:08:20 +0000 (17:08 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 24 Jan 2011 23:32:53 +0000 (07:32 +0800)
OSS is deprecated yet currently it is reported to be more stable
therefore we keep it but make it optional
Revert the conditional compilation:
add  CONFIG_EASYCAP_OSS and kill EASYCAP_NEEDS_ALSA
move oss-only code from easycap_sound.c to easycap_sound_oss.c

Cc: Mike Thomas <rmthomas@sciolus.org>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/easycap/Kconfig
drivers/staging/easycap/Makefile
drivers/staging/easycap/easycap.h
drivers/staging/easycap/easycap_ioctl.c
drivers/staging/easycap/easycap_main.c
drivers/staging/easycap/easycap_sound.c
drivers/staging/easycap/easycap_sound_oss.c [new file with mode: 0644]

index 4c1ad7e8b5aba9901b37769ced9a3c7c0f37316a..5072cf8a5da0fb373f20d64decaecafa05c14334 100644 (file)
@@ -1,6 +1,6 @@
 config EASYCAP
        tristate "EasyCAP USB ID 05e1:0408 support"
-       depends on USB && VIDEO_DEV && SND
+       depends on USB && VIDEO_DEV && SOUND
 
        ---help---
          This is an integrated audio/video driver for EasyCAP cards with
@@ -15,6 +15,18 @@ config EASYCAP
          To compile this driver as a module, choose M here: the
          module will be called easycap
 
+config EASYCAP_OSS
+       bool "OSS (DEPRECATED)"
+       depends on EASYCAP && SOUND_OSS_CORE
+
+       ---help---
+         Say 'Y' if you prefer Open Sound System (OSS) interface
+
+         This will disable Advanced Linux Sound Architecture (ALSA) binding.
+
+         Once binding to ALSA interface will be stable this option will be
+          removed.
+
 config EASYCAP_DEBUG
        bool "Enable EasyCAP driver debugging"
        depends on EASYCAP
index 226a7795a1db29af5d586f6d40a7d180791c68c8..a01ca11ec1e4049d0374b0ee05eda5e4b9e37a45 100644 (file)
@@ -1,5 +1,10 @@
-easycap-objs      := easycap_main.o easycap_low.o easycap_sound.o \
-                    easycap_ioctl.o easycap_settings.o easycap_testcard.o
+easycap-objs := easycap_main.o
+easycap-objs += easycap_low.o
+easycap-objs += easycap_ioctl.o
+easycap-objs += easycap_settings.o
+easycap-objs += easycap_testcard.o
+easycap-objs += easycap_sound.o
+easycap-$(CONFIG_EASYCAP_OSS) += easycap_sound_oss.o
 
 obj-$(CONFIG_EASYCAP)       += easycap.o
 
@@ -8,5 +13,4 @@ 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
 
index d751e752a57c313d2b8e177a7febbe2459803421..55ff0d571cfdc92933533b43fcbe7a0bac434746 100644 (file)
@@ -59,9 +59,9 @@
  */
 /*---------------------------------------------------------------------------*/
 #undef  EASYCAP_TESTCARD
-#if (!defined(EASYCAP_NEEDS_ALSA))
+#ifdef CONFIG_EASYCAP_OSS
 #undef  EASYCAP_TESTTONE
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -81,7 +81,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 
-#if defined(EASYCAP_NEEDS_ALSA)
+#ifndef CONFIG_EASYCAP_OSS
 #include <linux/vmalloc.h>
 #include <linux/sound.h>
 #include <sound/core.h>
@@ -90,7 +90,7 @@
 #include <sound/info.h>
 #include <sound/initval.h>
 #include <sound/control.h>
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* !CONFIG_EASYCAP_OSS */
 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
 #include <media/v4l2-dev.h>
@@ -445,7 +445,7 @@ __s16 oldaudio;
  *  ALSA
  */
 /*---------------------------------------------------------------------------*/
-#if defined(EASYCAP_NEEDS_ALSA)
+#ifndef CONFIG_EASYCAP_OSS
        struct snd_pcm_hardware alsa_hardware;
        struct snd_card *psnd_card;
        struct snd_pcm *psnd_pcm;
@@ -453,7 +453,7 @@ __s16 oldaudio;
        int dma_fill;
        int dma_next;
        int dma_read;
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* !CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
 /*
  *  SOUND PROPERTIES
@@ -537,7 +537,7 @@ int              adjust_volume(struct easycap *, int);
  *  AUDIO FUNCTION PROTOTYPES
  */
 /*---------------------------------------------------------------------------*/
-#if defined(EASYCAP_NEEDS_ALSA)
+#ifndef CONFIG_EASYCAP_OSS
 int            easycap_alsa_probe(struct easycap *);
 
 void            easycap_alsa_complete(struct urb *);
@@ -553,7 +553,7 @@ 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
+#else /* CONFIG_EASYCAP_OSS */
 void             easyoss_complete(struct urb *);
 ssize_t          easyoss_read(struct file *, char __user *, size_t, loff_t *);
 int              easyoss_open(struct inode *, struct file *);
@@ -564,7 +564,8 @@ int              easyoss_ioctl(struct inode *, struct file *, unsigned int,
                                                                unsigned long);
 unsigned int     easyoss_poll(struct file *, poll_table *);
 void             easyoss_delete(struct kref *);
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* !CONFIG_EASYCAP_OSS */
+
 int              easycap_sound_setup(struct easycap *);
 int              submit_audio_urbs(struct easycap *);
 int              kill_audio_urbs(struct easycap *);
@@ -715,13 +716,13 @@ extern struct easycap_format easycap_format[];
 extern struct v4l2_queryctrl easycap_control[];
 extern struct usb_driver easycap_usb_driver;
 extern struct easycap_dongle easycapdc60_dongle[];
-#if defined(EASYCAP_NEEDS_ALSA)
+#ifndef CONFIG_EASYCAP_OSS
 extern struct snd_pcm_ops easycap_alsa_ops;
 extern struct snd_pcm_hardware easycap_pcm_hardware;
 extern struct snd_card *psnd_card;
-#else
+#else /* CONFIG_EASYCAP_OSS */
 extern struct usb_class_driver easyoss_class;
 extern const struct file_operations easyoss_fops;
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* !CONFIG_EASYCAP_OSS */
 
 #endif /* !__EASYCAP_H__  */
index 43891039e7bfce1fad13d35abdc645a9ff675efd..6995163aba9e0e72515f0a759c830ba04ab8ccc7 100644 (file)
@@ -2517,7 +2517,7 @@ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
 return 0;
 }
 /*****************************************************************************/
-#if !defined(EASYCAP_NEEDS_ALSA)
+#ifdef CONFIG_EASYCAP_OSS
 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
        (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
@@ -2821,6 +2821,6 @@ default: {
 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
 return 0;
 }
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* CONFIG_EASYCAP_OSS */
 /*****************************************************************************/
 
index cc1460b64b1e8944b196dff6097be60d12f0e283..d1d7a483157152afd8ade003ba19a59f98ad0a38 100644 (file)
@@ -962,7 +962,7 @@ for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
                                        m * (0x01 << AUDIO_ISOC_ORDER));
 /*---------------------------------------------------------------------------*/
-#if !defined(EASYCAP_NEEDS_ALSA)
+#ifdef CONFIG_EASYCAP_OSS
 JOM(4, "freeing audio buffers.\n");
 gone = 0;
 for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
@@ -974,7 +974,7 @@ for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
        }
 }
 JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
-#endif /*!EASYCAP_NEEDS_ALSA*/
+#endif /* CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
 JOM(4, "freeing easycap structure.\n");
 allocation_video_urb    = peasycap->allocation_video_urb;
@@ -4350,7 +4350,7 @@ case 2: {
        INIT_LIST_HEAD(&(peasycap->urb_audio_head));
        peasycap->purb_audio_head = &(peasycap->urb_audio_head);
 
-#if !defined(EASYCAP_NEEDS_ALSA)
+#ifdef CONFIG_EASYCAP_OSS
        JOM(4, "allocating an audio buffer\n");
        JOM(4, ".... scattered over %i pages\n",
                                        peasycap->audio_buffer_page_many);
@@ -4375,7 +4375,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*/
+#endif /* CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
        JOM(4, "allocating %i isoc audio buffers of size %i\n",
                AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
@@ -4450,11 +4450,11 @@ case 2: {
                                "peasycap->audio_isoc_buffer[.].pgo;\n");
                        JOM(4, "  purb->transfer_buffer_length = %i;\n",
                                        peasycap->audio_isoc_buffer_size);
-#if defined(EASYCAP_NEEDS_ALSA)
-                       JOM(4, "  purb->complete = easycap_alsa_complete;\n");
-#else
+#ifdef CONFIG_EASYCAP_OSS
                        JOM(4, "  purb->complete = easyoss_complete;\n");
-#endif /*EASYCAP_NEEDS_ALSA*/
+#else /* CONFIG_EASYCAP_OSS */
+                       JOM(4, "  purb->complete = easycap_alsa_complete;\n");
+#endif /* CONFIG_EASYCAP_OSS */
                        JOM(4, "  purb->context = peasycap;\n");
                        JOM(4, "  purb->start_frame = 0;\n");
                        JOM(4, "  purb->number_of_packets = %i;\n",
@@ -4477,11 +4477,11 @@ case 2: {
                purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
                purb->transfer_buffer_length =
                                        peasycap->audio_isoc_buffer_size;
-#if defined(EASYCAP_NEEDS_ALSA)
-               purb->complete = easycap_alsa_complete;
-#else
+#ifdef CONFIG_EASYCAP_OSS
                purb->complete = easyoss_complete;
-#endif /*EASYCAP_NEEDS_ALSA*/
+#else /* CONFIG_EASYCAP_OSS */
+               purb->complete = easycap_alsa_complete;
+#endif /* CONFIG_EASYCAP_OSS */
                purb->context = peasycap;
                purb->start_frame = 0;
                purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
@@ -4504,7 +4504,7 @@ case 2: {
  *  THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
  */
 /*---------------------------------------------------------------------------*/
-#if defined(EASYCAP_NEEDS_ALSA)
+#ifndef CONFIG_EASYCAP_OSS
        JOM(4, "initializing ALSA card\n");
 
        rc = easycap_alsa_probe(peasycap);
@@ -4518,7 +4518,7 @@ case 2: {
                (peasycap->registered_audio)++;
        }
 
-#else /*EASYCAP_NEEDS_ALSA*/
+#else /* CONFIG_EASYCAP_OSS */
        rc = usb_register_dev(pusb_interface, &easyoss_class);
        if (0 != rc) {
                SAY("ERROR: usb_register_dev() failed\n");
@@ -4536,7 +4536,7 @@ case 2: {
  */
 /*---------------------------------------------------------------------------*/
        SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* CONFIG_EASYCAP_OSS */
 
        break;
 }
@@ -4774,7 +4774,7 @@ case 2: {
                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)
+#ifndef CONFIG_EASYCAP_OSS
 
 
 
@@ -4786,12 +4786,12 @@ case 2: {
        }
 
 
-#else /*EASYCAP_NEEDS_ALSA*/
+#else /* CONFIG_EASYCAP_OSS */
        usb_deregister_dev(pusb_interface, &easyoss_class);
        (peasycap->registered_audio)--;
        JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
        SAM("easyoss detached from minor #%d\n", minor);
-#endif /*EASYCAP_NEEDS_ALSA*/
+#endif /* CONFIG_EASYCAP_OSS */
 
        if (0 <= kd && DONGLE_MANY > kd) {
                mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
index 05d9eed6eb0437378a94aa8307904c0e846f221e..07dd7aa95ea5db8be0340d479ac39ba506088f9b 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "easycap.h"
 
-#if defined(EASYCAP_NEEDS_ALSA)
+#ifndef CONFIG_EASYCAP_OSS
 /*--------------------------------------------------------------------------*/
 /*
  *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
@@ -669,707 +669,7 @@ 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,
-};
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
- *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
- *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
- */
-/*---------------------------------------------------------------------------*/
-void
-easyoss_complete(struct urb *purb)
-{
-struct easycap *peasycap;
-struct data_buffer *paudio_buffer;
-__u8 *p1, *p2;
-__s16 s16;
-int i, j, more, much, leap, 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) {
-               rc = usb_submit_urb(purb, GFP_ATOMIC);
-               if (rc) {
-                       if (-ENODEV != rc && -ENOENT != rc) {
-                               SAM("ERROR: while %i=audio_idle, "
-                                   "usb_submit_urb() failed with rc: -%s: %d\n",
-                                       peasycap->audio_idle,
-                                       strerror(rc), rc);
-                       }
-               }
-       }
-return;
-}
-/*---------------------------------------------------------------------------*/
-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: -%s: %d\n",
-               strerror(purb->status), purb->status);
-       goto resubmit;
-}
-/*---------------------------------------------------------------------------*/
-/*
- *  PROCEED HERE WHEN NO ERROR
- */
-/*---------------------------------------------------------------------------*/
-#if defined(UPSAMPLE)
-oldaudio = peasycap->oldaudio;
-#endif /*UPSAMPLE*/
-
-for (i = 0;  i < purb->number_of_packets; i++) {
-       if (!purb->iso_frame_desc[i].status) {
-
-               SAM("-%s\n", strerror(purb->iso_frame_desc[i].status));
-
-               more = purb->iso_frame_desc[i].actual_length;
-
-#if defined(TESTTONE)
-               if (!more)
-                       more = purb->iso_frame_desc[i].length;
-#endif
-
-               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);
-
-                       leap = 0;
-                       p1 += leap;
-                       more -= leap;
-/*---------------------------------------------------------------------------*/
-/*
- *  COPY more BYTES FROM ISOC BUFFER TO AUDIO 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;
-                               }
-                               if (peasycap->audio_buffer_page_many <=
-                                                       peasycap->audio_fill) {
-                                       SAM("ERROR: bad "
-                                               "peasycap->audio_fill\n");
-                                       return;
-                               }
-
-                               paudio_buffer = &peasycap->audio_buffer
-                                                       [peasycap->audio_fill];
-                               if (PAGE_SIZE < (paudio_buffer->pto -
-                                               paudio_buffer->pgo)) {
-                                       SAM("ERROR: bad paudio_buffer->pto\n");
-                                       return;
-                               }
-                               if (PAGE_SIZE == (paudio_buffer->pto -
-                                                       paudio_buffer->pgo)) {
-
-#if defined(TESTTONE)
-                                       easyoss_testtone(peasycap,
-                                                       peasycap->audio_fill);
-#endif /*TESTTONE*/
-
-                                       paudio_buffer->pto =
-                                                       paudio_buffer->pgo;
-                                       (peasycap->audio_fill)++;
-                                       if (peasycap->
-                                               audio_buffer_page_many <=
-                                                       peasycap->audio_fill)
-                                               peasycap->audio_fill = 0;
-
-                                       JOM(8, "bumped peasycap->"
-                                                       "audio_fill to %i\n",
-                                                       peasycap->audio_fill);
-
-                                       paudio_buffer = &peasycap->
-                                                       audio_buffer
-                                                       [peasycap->audio_fill];
-                                       paudio_buffer->pto =
-                                                       paudio_buffer->pgo;
-
-                                       if (!(peasycap->audio_fill %
-                                               peasycap->
-                                               audio_pages_per_fragment)) {
-                                               JOM(12, "wakeup call on wq_"
-                                               "audio, %i=frag reading  %i"
-                                               "=fragment fill\n",
-                                               (peasycap->audio_read /
-                                               peasycap->
-                                               audio_pages_per_fragment),
-                                               (peasycap->audio_fill /
-                                               peasycap->
-                                               audio_pages_per_fragment));
-                                               wake_up_interruptible
-                                               (&(peasycap->wq_audio));
-                                       }
-                               }
-
-                               much = PAGE_SIZE - (int)(paudio_buffer->pto -
-                                                        paudio_buffer->pgo);
-
-                               if (false == peasycap->microphone) {
-                                       if (much > more)
-                                               much = more;
-
-                                       memcpy(paudio_buffer->pto, 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 *)paudio_buffer->pto;
-
-                                       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 *)paudio_buffer->pto;
-
-                                       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*/
-                               }
-                               (paudio_buffer->pto) += much;
-                       }
-               }
-       } 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: -%s: %d\n", peasycap->audio_idle,
-                               strerror(rc), rc);
-               }
-       }
-}
-return;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
- *  STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
- *  HAVE AN IOCTL INTERFACE.
- */
-/*---------------------------------------------------------------------------*/
-int
-easyoss_open(struct inode *inode, struct file *file)
-{
-struct usb_interface *pusb_interface;
-struct easycap *peasycap;
-int subminor;
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-struct v4l2_device *pv4l2_device;
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-
-JOT(4, "begins\n");
-
-subminor = iminor(inode);
-
-pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
-if (NULL == pusb_interface) {
-       SAY("ERROR: pusb_interface is NULL\n");
-       SAY("ending unsuccessfully\n");
-       return -1;
-}
-peasycap = usb_get_intfdata(pusb_interface);
-if (NULL == peasycap) {
-       SAY("ERROR: peasycap is NULL\n");
-       SAY("ending unsuccessfully\n");
-       return -1;
-}
-/*---------------------------------------------------------------------------*/
-#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 -EFAULT;
-       }
-       peasycap = (struct easycap *)
-               container_of(pv4l2_device, struct easycap, v4l2_device);
-}
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*---------------------------------------------------------------------------*/
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-       SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-       return -EFAULT;
-}
-/*---------------------------------------------------------------------------*/
-
-file->private_data = peasycap;
-
-if (0 != easycap_sound_setup(peasycap)) {
-       ;
-       ;
-}
-return 0;
-}
-/*****************************************************************************/
-int
-easyoss_release(struct inode *inode, struct file *file)
-{
-struct easycap *peasycap;
-
-JOT(4, "begins\n");
-
-peasycap = file->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: 0x%08lX\n", (unsigned long int) peasycap);
-       return -EFAULT;
-}
-if (0 != kill_audio_urbs(peasycap)) {
-       SAM("ERROR: kill_audio_urbs() failed\n");
-       return -EFAULT;
-}
-JOM(4, "ending successfully\n");
-return 0;
-}
-/*****************************************************************************/
-ssize_t
-easyoss_read(struct file *file, char __user *puserspacebuffer,
-                                               size_t kount, loff_t *poff)
-{
-struct timeval timeval;
-long long int above, below, mean;
-struct signed_div_result sdr;
-unsigned char *p0;
-long int kount1, more, rc, l0, lm;
-int fragment, kd;
-struct easycap *peasycap;
-struct data_buffer *pdata_buffer;
-size_t szret;
-
-/*---------------------------------------------------------------------------*/
-/*
- *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
- *
- ******************************************************************************
- *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
- *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
- ******************************************************************************
- */
-/*---------------------------------------------------------------------------*/
-
-JOT(8, "%5i=kount  %5i=*poff\n", (int)kount, (int)(*poff));
-
-if (NULL == file) {
-       SAY("ERROR:  file is NULL\n");
-       return -ERESTARTSYS;
-}
-peasycap = file->private_data;
-if (NULL == peasycap) {
-       SAY("ERROR in easyoss_read(): peasycap is NULL\n");
-       return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-       SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-       return -EFAULT;
-}
-if (NULL == peasycap->pusb_device) {
-       SAY("ERROR: peasycap->pusb_device is NULL\n");
-       return -EFAULT;
-}
-kd = isdongle(peasycap);
-if (0 <= kd && DONGLE_MANY > 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 easycapdc60_dongle[%i].mutex_audio\n", kd);
-/*---------------------------------------------------------------------------*/
-/*
- *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
- *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
- *  IF NECESSARY, BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-       if (kd != isdongle(peasycap))
-               return -ERESTARTSYS;
-       if (NULL == file) {
-               SAY("ERROR:  file is NULL\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return -ERESTARTSYS;
-       }
-       peasycap = file->private_data;
-       if (NULL == peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               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(&easycapdc60_dongle[kd].mutex_audio);
-               return -ERESTARTSYS;
-       }
-       if (NULL == peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return -ERESTARTSYS;
-       }
-} else {
-/*---------------------------------------------------------------------------*/
-/*
- *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
- *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-       return -ERESTARTSYS;
-}
-/*---------------------------------------------------------------------------*/
-if (file->f_flags & O_NONBLOCK)
-       JOT(16, "NONBLOCK  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
-else
-       JOT(8, "BLOCKING  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
-
-if ((0 > peasycap->audio_read) ||
-               (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
-       SAM("ERROR: peasycap->audio_read out of range\n");
-       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(&easycapdc60_dongle[kd].mutex_audio);
-       return -EFAULT;
-}
-JOM(12, "before wait, %i=frag read  %i=frag fill\n",
-               (peasycap->audio_read / peasycap->audio_pages_per_fragment),
-               (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
-while ((fragment == (peasycap->audio_fill /
-                               peasycap->audio_pages_per_fragment)) ||
-               (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
-       if (file->f_flags & O_NONBLOCK) {
-               JOM(16, "returning -EAGAIN as instructed\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return -EAGAIN;
-       }
-       rc = wait_event_interruptible(peasycap->wq_audio,
-               (peasycap->audio_idle  || peasycap->audio_eof   ||
-               ((fragment != (peasycap->audio_fill /
-                               peasycap->audio_pages_per_fragment)) &&
-               (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
-       if (0 != rc) {
-               SAM("aborted by signal\n");
-               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(&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(&easycapdc60_dongle[kd].mutex_audio);
-               return 0;
-       }
-       if (!peasycap->audio_isoc_streaming) {
-               JOM(16, "returning 0 because audio urbs not streaming\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return 0;
-       }
-}
-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(&easycapdc60_dongle[kd].mutex_audio);
-               return -EFAULT;
-       }
-       if (NULL == pdata_buffer->pto) {
-               SAM("ERROR: pdata_buffer->pto is NULL\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return -EFAULT;
-       }
-       kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
-       if (0 > kount1) {
-               SAM("MISTAKE: kount1 is negative\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return -ERESTARTSYS;
-       }
-       if (!kount1) {
-               (peasycap->audio_read)++;
-               if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
-                       peasycap->audio_read = 0;
-               JOM(12, "bumped peasycap->audio_read to %i\n",
-                                               peasycap->audio_read);
-
-               if (fragment != (peasycap->audio_read /
-                                       peasycap->audio_pages_per_fragment))
-                       break;
-
-               if ((0 > peasycap->audio_read) ||
-                       (peasycap->audio_buffer_page_many <=
-                                       peasycap->audio_read)) {
-                       SAM("ERROR: peasycap->audio_read out of range\n");
-                       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(&easycapdc60_dongle[kd].mutex_audio);
-                       return -EFAULT;
-               }
-               if (NULL == pdata_buffer->pgo) {
-                       SAM("ERROR: pdata_buffer->pgo is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-                       return -EFAULT;
-               }
-               if (NULL == pdata_buffer->pto) {
-                       SAM("ERROR: pdata_buffer->pto is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-                       return -EFAULT;
-               }
-               kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
-       }
-       JOM(12, "ready  to send %li bytes\n", (long int) kount1);
-       JOM(12, "still  to send %li bytes\n", (long int) kount);
-       more = kount1;
-       if (more > kount)
-               more = kount;
-       JOM(12, "agreed to send %li bytes from page %i\n",
-                                               more, peasycap->audio_read);
-       if (!more)
-               break;
-
-/*---------------------------------------------------------------------------*/
-/*
- *  ACCUMULATE DYNAMIC-RANGE INFORMATION
- */
-/*---------------------------------------------------------------------------*/
-       p0 = (unsigned char *)pdata_buffer->pgo;  l0 = 0;  lm = more/2;
-       while (l0 < lm) {
-               SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau,
-                               &peasycap->audio_square);  l0++;  p0 += 2;
-       }
-/*---------------------------------------------------------------------------*/
-       rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
-       if (0 != rc) {
-               SAM("ERROR: copy_to_user() returned %li\n", rc);
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-               return -EFAULT;
-       }
-       *poff += (loff_t)more;
-       szret += (size_t)more;
-       pdata_buffer->pto += more;
-       puserspacebuffer += more;
-       kount -= (size_t)more;
-}
-JOM(12, "after  read, %i=frag read  %i=frag fill\n",
-               (peasycap->audio_read / peasycap->audio_pages_per_fragment),
-               (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-if (kount < 0) {
-       SAM("MISTAKE:  %li=kount  %li=szret\n",
-                                       (long int)kount, (long int)szret);
-}
-/*---------------------------------------------------------------------------*/
-/*
- *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
- */
-/*---------------------------------------------------------------------------*/
-if (peasycap->audio_sample) {
-       below = peasycap->audio_sample;
-       above = peasycap->audio_square;
-       sdr = signed_div(above, below);
-       above = sdr.quotient;
-       mean = peasycap->audio_niveau;
-       sdr = signed_div(mean, peasycap->audio_sample);
-
-       JOM(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n",
-                               sdr.quotient, above, peasycap->audio_sample);
-
-       sdr = signed_div(above, 32768);
-       JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
-}
-/*---------------------------------------------------------------------------*/
-/*
- *  UPDATE THE AUDIO CLOCK
- */
-/*---------------------------------------------------------------------------*/
-do_gettimeofday(&timeval);
-if (!peasycap->timeval1.tv_sec) {
-       peasycap->audio_bytes = 0;
-       peasycap->timeval3 = timeval;
-       peasycap->timeval1 = peasycap->timeval3;
-       sdr.quotient = 192000;
-} else {
-       peasycap->audio_bytes += (long long int) szret;
-       below = ((long long int)(1000000)) *
-               ((long long int)(timeval.tv_sec  -
-                                               peasycap->timeval3.tv_sec)) +
-               (long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
-       above = 1000000 * ((long long int) peasycap->audio_bytes);
-
-       if (below)
-               sdr = signed_div(above, below);
-       else
-               sdr.quotient = 192000;
-}
-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);
-return szret;
-}
-/*****************************************************************************/
-
-#endif /*!EASYCAP_NEEDS_ALSA*/
+#endif /*! CONFIG_EASYCAP_OSS */
 
 /*****************************************************************************/
 /*****************************************************************************/
@@ -1484,11 +784,11 @@ if (!peasycap->audio_isoc_streaming) {
                                        peasycap->audio_isoc_buffer[isbuf].pgo;
                                purb->transfer_buffer_length =
                                        peasycap->audio_isoc_buffer_size;
-#if defined(EASYCAP_NEEDS_ALSA)
-                               purb->complete = easycap_alsa_complete;
-#else
+#ifdef CONFIG_EASYCAP_OSS
                                purb->complete = easyoss_complete;
-#endif /*EASYCAP_NEEDS_ALSA*/
+#else /* CONFIG_EASYCAP_OSS */
+                               purb->complete = easycap_alsa_complete;
+#endif /* CONFIG_EASYCAP_OSS */
                                purb->context = peasycap;
                                purb->start_frame = 0;
                                purb->number_of_packets =
diff --git a/drivers/staging/easycap/easycap_sound_oss.c b/drivers/staging/easycap/easycap_sound_oss.c
new file mode 100644 (file)
index 0000000..3f85cc3
--- /dev/null
@@ -0,0 +1,730 @@
+/******************************************************************************
+*                                                                             *
+*  easycap_sound.c                                                            *
+*                                                                             *
+*  Audio driver for EasyCAP USB2.0 Video Capture Device DC60                  *
+*                                                                             *
+*                                                                             *
+******************************************************************************/
+/*
+ *
+ *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
+ *
+ *
+ *  This is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The software is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+*/
+/*****************************************************************************/
+
+#include "easycap.h"
+
+/*****************************************************************************/
+/****************************                       **************************/
+/****************************   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,
+};
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
+ *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
+ *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
+ */
+/*---------------------------------------------------------------------------*/
+void
+easyoss_complete(struct urb *purb)
+{
+struct easycap *peasycap;
+struct data_buffer *paudio_buffer;
+__u8 *p1, *p2;
+__s16 s16;
+int i, j, more, much, leap, 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) {
+               rc = usb_submit_urb(purb, GFP_ATOMIC);
+               if (rc) {
+                       if (-ENODEV != rc && -ENOENT != rc) {
+                               SAM("ERROR: while %i=audio_idle, "
+                                   "usb_submit_urb() failed with rc: -%s: %d\n",
+                                       peasycap->audio_idle,
+                                       strerror(rc), rc);
+                       }
+               }
+       }
+return;
+}
+/*---------------------------------------------------------------------------*/
+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: -%s: %d\n",
+               strerror(purb->status), purb->status);
+       goto resubmit;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ *  PROCEED HERE WHEN NO ERROR
+ */
+/*---------------------------------------------------------------------------*/
+#if defined(UPSAMPLE)
+oldaudio = peasycap->oldaudio;
+#endif /*UPSAMPLE*/
+
+for (i = 0;  i < purb->number_of_packets; i++) {
+       if (!purb->iso_frame_desc[i].status) {
+
+               SAM("-%s\n", strerror(purb->iso_frame_desc[i].status));
+
+               more = purb->iso_frame_desc[i].actual_length;
+
+#if defined(TESTTONE)
+               if (!more)
+                       more = purb->iso_frame_desc[i].length;
+#endif
+
+               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);
+
+                       leap = 0;
+                       p1 += leap;
+                       more -= leap;
+/*---------------------------------------------------------------------------*/
+/*
+ *  COPY more BYTES FROM ISOC BUFFER TO AUDIO 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;
+                               }
+                               if (peasycap->audio_buffer_page_many <=
+                                                       peasycap->audio_fill) {
+                                       SAM("ERROR: bad "
+                                               "peasycap->audio_fill\n");
+                                       return;
+                               }
+
+                               paudio_buffer = &peasycap->audio_buffer
+                                                       [peasycap->audio_fill];
+                               if (PAGE_SIZE < (paudio_buffer->pto -
+                                               paudio_buffer->pgo)) {
+                                       SAM("ERROR: bad paudio_buffer->pto\n");
+                                       return;
+                               }
+                               if (PAGE_SIZE == (paudio_buffer->pto -
+                                                       paudio_buffer->pgo)) {
+
+#if defined(TESTTONE)
+                                       easyoss_testtone(peasycap,
+                                                       peasycap->audio_fill);
+#endif /*TESTTONE*/
+
+                                       paudio_buffer->pto =
+                                                       paudio_buffer->pgo;
+                                       (peasycap->audio_fill)++;
+                                       if (peasycap->
+                                               audio_buffer_page_many <=
+                                                       peasycap->audio_fill)
+                                               peasycap->audio_fill = 0;
+
+                                       JOM(8, "bumped peasycap->"
+                                                       "audio_fill to %i\n",
+                                                       peasycap->audio_fill);
+
+                                       paudio_buffer = &peasycap->
+                                                       audio_buffer
+                                                       [peasycap->audio_fill];
+                                       paudio_buffer->pto =
+                                                       paudio_buffer->pgo;
+
+                                       if (!(peasycap->audio_fill %
+                                               peasycap->
+                                               audio_pages_per_fragment)) {
+                                               JOM(12, "wakeup call on wq_"
+                                               "audio, %i=frag reading  %i"
+                                               "=fragment fill\n",
+                                               (peasycap->audio_read /
+                                               peasycap->
+                                               audio_pages_per_fragment),
+                                               (peasycap->audio_fill /
+                                               peasycap->
+                                               audio_pages_per_fragment));
+                                               wake_up_interruptible
+                                               (&(peasycap->wq_audio));
+                                       }
+                               }
+
+                               much = PAGE_SIZE - (int)(paudio_buffer->pto -
+                                                        paudio_buffer->pgo);
+
+                               if (false == peasycap->microphone) {
+                                       if (much > more)
+                                               much = more;
+
+                                       memcpy(paudio_buffer->pto, 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 *)paudio_buffer->pto;
+
+                                       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 *)paudio_buffer->pto;
+
+                                       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*/
+                               }
+                               (paudio_buffer->pto) += much;
+                       }
+               }
+       } 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: -%s: %d\n", peasycap->audio_idle,
+                               strerror(rc), rc);
+               }
+       }
+}
+return;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
+ *  STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
+ *  HAVE AN IOCTL INTERFACE.
+ */
+/*---------------------------------------------------------------------------*/
+int
+easyoss_open(struct inode *inode, struct file *file)
+{
+struct usb_interface *pusb_interface;
+struct easycap *peasycap;
+int subminor;
+/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
+#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
+struct v4l2_device *pv4l2_device;
+#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
+#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
+/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
+JOT(4, "begins\n");
+
+subminor = iminor(inode);
+
+pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
+if (NULL == pusb_interface) {
+       SAY("ERROR: pusb_interface is NULL\n");
+       SAY("ending unsuccessfully\n");
+       return -1;
+}
+peasycap = usb_get_intfdata(pusb_interface);
+if (NULL == peasycap) {
+       SAY("ERROR: peasycap is NULL\n");
+       SAY("ending unsuccessfully\n");
+       return -1;
+}
+/*---------------------------------------------------------------------------*/
+#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 -EFAULT;
+       }
+       peasycap = (struct easycap *)
+               container_of(pv4l2_device, struct easycap, v4l2_device);
+}
+#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
+#
+#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
+/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+/*---------------------------------------------------------------------------*/
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+       SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
+       return -EFAULT;
+}
+/*---------------------------------------------------------------------------*/
+
+file->private_data = peasycap;
+
+if (0 != easycap_sound_setup(peasycap)) {
+       ;
+       ;
+}
+return 0;
+}
+/*****************************************************************************/
+int
+easyoss_release(struct inode *inode, struct file *file)
+{
+struct easycap *peasycap;
+
+JOT(4, "begins\n");
+
+peasycap = file->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: 0x%08lX\n", (unsigned long int) peasycap);
+       return -EFAULT;
+}
+if (0 != kill_audio_urbs(peasycap)) {
+       SAM("ERROR: kill_audio_urbs() failed\n");
+       return -EFAULT;
+}
+JOM(4, "ending successfully\n");
+return 0;
+}
+/*****************************************************************************/
+ssize_t
+easyoss_read(struct file *file, char __user *puserspacebuffer,
+                                               size_t kount, loff_t *poff)
+{
+struct timeval timeval;
+long long int above, below, mean;
+struct signed_div_result sdr;
+unsigned char *p0;
+long int kount1, more, rc, l0, lm;
+int fragment, kd;
+struct easycap *peasycap;
+struct data_buffer *pdata_buffer;
+size_t szret;
+
+/*---------------------------------------------------------------------------*/
+/*
+ *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
+ *
+ ******************************************************************************
+ *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
+ *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
+ ******************************************************************************
+ */
+/*---------------------------------------------------------------------------*/
+
+JOT(8, "%5i=kount  %5i=*poff\n", (int)kount, (int)(*poff));
+
+if (NULL == file) {
+       SAY("ERROR:  file is NULL\n");
+       return -ERESTARTSYS;
+}
+peasycap = file->private_data;
+if (NULL == peasycap) {
+       SAY("ERROR in easyoss_read(): peasycap is NULL\n");
+       return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+       SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
+       return -EFAULT;
+}
+if (NULL == peasycap->pusb_device) {
+       SAY("ERROR: peasycap->pusb_device is NULL\n");
+       return -EFAULT;
+}
+kd = isdongle(peasycap);
+if (0 <= kd && DONGLE_MANY > 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 easycapdc60_dongle[%i].mutex_audio\n", kd);
+/*---------------------------------------------------------------------------*/
+/*
+ *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
+ *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
+ *  IF NECESSARY, BAIL OUT.
+*/
+/*---------------------------------------------------------------------------*/
+       if (kd != isdongle(peasycap))
+               return -ERESTARTSYS;
+       if (NULL == file) {
+               SAY("ERROR:  file is NULL\n");
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return -ERESTARTSYS;
+       }
+       peasycap = file->private_data;
+       if (NULL == peasycap) {
+               SAY("ERROR:  peasycap is NULL\n");
+               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(&easycapdc60_dongle[kd].mutex_audio);
+               return -ERESTARTSYS;
+       }
+       if (NULL == peasycap->pusb_device) {
+               SAM("ERROR: peasycap->pusb_device is NULL\n");
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return -ERESTARTSYS;
+       }
+} else {
+/*---------------------------------------------------------------------------*/
+/*
+ *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
+ *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
+*/
+/*---------------------------------------------------------------------------*/
+       return -ERESTARTSYS;
+}
+/*---------------------------------------------------------------------------*/
+if (file->f_flags & O_NONBLOCK)
+       JOT(16, "NONBLOCK  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
+else
+       JOT(8, "BLOCKING  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
+
+if ((0 > peasycap->audio_read) ||
+               (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
+       SAM("ERROR: peasycap->audio_read out of range\n");
+       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(&easycapdc60_dongle[kd].mutex_audio);
+       return -EFAULT;
+}
+JOM(12, "before wait, %i=frag read  %i=frag fill\n",
+               (peasycap->audio_read / peasycap->audio_pages_per_fragment),
+               (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
+fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
+while ((fragment == (peasycap->audio_fill /
+                               peasycap->audio_pages_per_fragment)) ||
+               (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
+       if (file->f_flags & O_NONBLOCK) {
+               JOM(16, "returning -EAGAIN as instructed\n");
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return -EAGAIN;
+       }
+       rc = wait_event_interruptible(peasycap->wq_audio,
+               (peasycap->audio_idle  || peasycap->audio_eof   ||
+               ((fragment != (peasycap->audio_fill /
+                               peasycap->audio_pages_per_fragment)) &&
+               (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
+       if (0 != rc) {
+               SAM("aborted by signal\n");
+               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(&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(&easycapdc60_dongle[kd].mutex_audio);
+               return 0;
+       }
+       if (!peasycap->audio_isoc_streaming) {
+               JOM(16, "returning 0 because audio urbs not streaming\n");
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return 0;
+       }
+}
+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(&easycapdc60_dongle[kd].mutex_audio);
+               return -EFAULT;
+       }
+       if (NULL == pdata_buffer->pto) {
+               SAM("ERROR: pdata_buffer->pto is NULL\n");
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return -EFAULT;
+       }
+       kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
+       if (0 > kount1) {
+               SAM("MISTAKE: kount1 is negative\n");
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return -ERESTARTSYS;
+       }
+       if (!kount1) {
+               (peasycap->audio_read)++;
+               if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
+                       peasycap->audio_read = 0;
+               JOM(12, "bumped peasycap->audio_read to %i\n",
+                                               peasycap->audio_read);
+
+               if (fragment != (peasycap->audio_read /
+                                       peasycap->audio_pages_per_fragment))
+                       break;
+
+               if ((0 > peasycap->audio_read) ||
+                       (peasycap->audio_buffer_page_many <=
+                                       peasycap->audio_read)) {
+                       SAM("ERROR: peasycap->audio_read out of range\n");
+                       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(&easycapdc60_dongle[kd].mutex_audio);
+                       return -EFAULT;
+               }
+               if (NULL == pdata_buffer->pgo) {
+                       SAM("ERROR: pdata_buffer->pgo is NULL\n");
+                       mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+                       return -EFAULT;
+               }
+               if (NULL == pdata_buffer->pto) {
+                       SAM("ERROR: pdata_buffer->pto is NULL\n");
+                       mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+                       return -EFAULT;
+               }
+               kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
+       }
+       JOM(12, "ready  to send %li bytes\n", (long int) kount1);
+       JOM(12, "still  to send %li bytes\n", (long int) kount);
+       more = kount1;
+       if (more > kount)
+               more = kount;
+       JOM(12, "agreed to send %li bytes from page %i\n",
+                                               more, peasycap->audio_read);
+       if (!more)
+               break;
+
+/*---------------------------------------------------------------------------*/
+/*
+ *  ACCUMULATE DYNAMIC-RANGE INFORMATION
+ */
+/*---------------------------------------------------------------------------*/
+       p0 = (unsigned char *)pdata_buffer->pgo;  l0 = 0;  lm = more/2;
+       while (l0 < lm) {
+               SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau,
+                               &peasycap->audio_square);  l0++;  p0 += 2;
+       }
+/*---------------------------------------------------------------------------*/
+       rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
+       if (0 != rc) {
+               SAM("ERROR: copy_to_user() returned %li\n", rc);
+               mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+               return -EFAULT;
+       }
+       *poff += (loff_t)more;
+       szret += (size_t)more;
+       pdata_buffer->pto += more;
+       puserspacebuffer += more;
+       kount -= (size_t)more;
+}
+JOM(12, "after  read, %i=frag read  %i=frag fill\n",
+               (peasycap->audio_read / peasycap->audio_pages_per_fragment),
+               (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
+if (kount < 0) {
+       SAM("MISTAKE:  %li=kount  %li=szret\n",
+                                       (long int)kount, (long int)szret);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
+ */
+/*---------------------------------------------------------------------------*/
+if (peasycap->audio_sample) {
+       below = peasycap->audio_sample;
+       above = peasycap->audio_square;
+       sdr = signed_div(above, below);
+       above = sdr.quotient;
+       mean = peasycap->audio_niveau;
+       sdr = signed_div(mean, peasycap->audio_sample);
+
+       JOM(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n",
+                               sdr.quotient, above, peasycap->audio_sample);
+
+       sdr = signed_div(above, 32768);
+       JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ *  UPDATE THE AUDIO CLOCK
+ */
+/*---------------------------------------------------------------------------*/
+do_gettimeofday(&timeval);
+if (!peasycap->timeval1.tv_sec) {
+       peasycap->audio_bytes = 0;
+       peasycap->timeval3 = timeval;
+       peasycap->timeval1 = peasycap->timeval3;
+       sdr.quotient = 192000;
+} else {
+       peasycap->audio_bytes += (long long int) szret;
+       below = ((long long int)(1000000)) *
+               ((long long int)(timeval.tv_sec  -
+                                               peasycap->timeval3.tv_sec)) +
+               (long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
+       above = 1000000 * ((long long int) peasycap->audio_bytes);
+
+       if (below)
+               sdr = signed_div(above, below);
+       else
+               sdr.quotient = 192000;
+}
+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);
+return szret;
+}
+/*****************************************************************************/
+