summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2011-01-24 17:08:20 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2011-01-25 07:32:53 +0800
commit0edbc24c5dc7fba0dce193f7d4b7faf2ad211ba4 (patch)
treee26f8b9805ceb997cd09306134efcc070a6bf61f
parent5c0c6c395ea8ad2f831c0717f67f957ba84550ad (diff)
downloadop-kernel-dev-0edbc24c5dc7fba0dce193f7d4b7faf2ad211ba4.zip
op-kernel-dev-0edbc24c5dc7fba0dce193f7d4b7faf2ad211ba4.tar.gz
staging/easycap: make OSS compilation optional instead of ALSA
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>
-rw-r--r--drivers/staging/easycap/Kconfig14
-rw-r--r--drivers/staging/easycap/Makefile10
-rw-r--r--drivers/staging/easycap/easycap.h25
-rw-r--r--drivers/staging/easycap/easycap_ioctl.c4
-rw-r--r--drivers/staging/easycap/easycap_main.c36
-rw-r--r--drivers/staging/easycap/easycap_sound.c712
-rw-r--r--drivers/staging/easycap/easycap_sound_oss.c730
7 files changed, 789 insertions, 742 deletions
diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
index 4c1ad7e..5072cf8 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 && 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
diff --git a/drivers/staging/easycap/Makefile b/drivers/staging/easycap/Makefile
index 226a779..a01ca11 100644
--- a/drivers/staging/easycap/Makefile
+++ b/drivers/staging/easycap/Makefile
@@ -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
diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h
index d751e75..55ff0d5 100644
--- a/drivers/staging/easycap/easycap.h
+++ b/drivers/staging/easycap/easycap.h
@@ -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__ */
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
index 4389103..6995163 100644
--- a/drivers/staging/easycap/easycap_ioctl.c
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -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 */
/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
index cc1460b..d1d7a48 100644
--- a/drivers/staging/easycap/easycap_main.c
+++ b/drivers/staging/easycap/easycap_main.c
@@ -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);
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c
index 05d9eed..07dd7aa 100644
--- a/drivers/staging/easycap/easycap_sound.c
+++ b/drivers/staging/easycap/easycap_sound.c
@@ -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
index 0000000..3f85cc3
--- /dev/null
+++ b/drivers/staging/easycap/easycap_sound_oss.c
@@ -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;
+}
+/*****************************************************************************/
+
OpenPOWER on IntegriCloud