Commit a9855917 authored by Mike Thomas's avatar Mike Thomas Committed by Greg Kroah-Hartman

staging: easycap: add ALSA support

This is necessary because some distributions are disabling OSS entirely.
Signed-off-by: default avatarMike Thomas <rmthomas@sciolus.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b54a28a4
config EASYCAP config EASYCAP
tristate "EasyCAP USB ID 05e1:0408 support" tristate "EasyCAP USB ID 05e1:0408 support"
depends on USB && VIDEO_DEV depends on USB && VIDEO_DEV && SND
---help--- ---help---
This is an integrated audio/video driver for EasyCAP cards with This is an integrated audio/video driver for EasyCAP cards with
......
easycap-objs := easycap_main.o easycap_low.o easycap_sound.o \
easycap_ioctl.o easycap_settings.o easycap_testcard.o
obj-$(CONFIG_EASYCAP) += easycap.o obj-$(CONFIG_EASYCAP) += easycap.o
easycap-y := easycap_main.o easycap_low.o easycap_sound.o
easycap-y += easycap_ioctl.o easycap_settings.o
easycap-y += easycap_testcard.o
ccflags-y := -Wall ccflags-y := -Wall
# Impose all or none of the following:
ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT
ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H
ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS
ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL
ccflags-y += -DEASYCAP_NEEDS_ALSA
ccflags-y += -DEASYCAP_NEEDS_CARD_CREATE
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
* EASYCAP_NEEDS_V4L2_DEVICE_H * EASYCAP_NEEDS_V4L2_DEVICE_H
* EASYCAP_NEEDS_V4L2_FOPS * EASYCAP_NEEDS_V4L2_FOPS
* EASYCAP_NEEDS_UNLOCKED_IOCTL * EASYCAP_NEEDS_UNLOCKED_IOCTL
* EASYCAP_NEEDS_ALSA
* EASYCAP_SILENT
* *
* IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
* OPTIONS. * OPTIONS.
...@@ -57,9 +59,9 @@ ...@@ -57,9 +59,9 @@
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#undef EASYCAP_TESTCARD #undef EASYCAP_TESTCARD
#if (!defined(EASYCAP_NEEDS_ALSA))
#undef EASYCAP_TESTTONE #undef EASYCAP_TESTTONE
#undef NOREADBACK #endif /*EASYCAP_NEEDS_ALSA*/
#undef AUDIOTIME
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -79,6 +81,16 @@ ...@@ -79,6 +81,16 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/types.h> #include <linux/types.h>
#if defined(EASYCAP_NEEDS_ALSA)
#include <linux/vmalloc.h>
#include <linux/sound.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/info.h>
#include <sound/initval.h>
#include <sound/control.h>
#endif /*EASYCAP_NEEDS_ALSA*/
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
...@@ -112,7 +124,7 @@ ...@@ -112,7 +124,7 @@
#define USB_EASYCAP_VENDOR_ID 0x05e1 #define USB_EASYCAP_VENDOR_ID 0x05e1
#define USB_EASYCAP_PRODUCT_ID 0x0408 #define USB_EASYCAP_PRODUCT_ID 0x0408
#define EASYCAP_DRIVER_VERSION "0.8.41" #define EASYCAP_DRIVER_VERSION "0.9.01"
#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60" #define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
#define USB_SKEL_MINOR_BASE 192 #define USB_SKEL_MINOR_BASE 192
...@@ -158,7 +170,8 @@ ...@@ -158,7 +170,8 @@
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define AUDIO_ISOC_BUFFER_MANY 16 #define AUDIO_ISOC_BUFFER_MANY 16
#define AUDIO_ISOC_ORDER 3 #define AUDIO_ISOC_ORDER 1
#define AUDIO_ISOC_FRAMESPERDESC 32
#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER) #define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -166,6 +179,7 @@ ...@@ -166,6 +179,7 @@
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define AUDIO_FRAGMENT_MANY 32 #define AUDIO_FRAGMENT_MANY 32
#define PAGES_PER_AUDIO_FRAGMENT 4
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND, * IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
...@@ -296,6 +310,7 @@ struct easycap { ...@@ -296,6 +310,7 @@ struct easycap {
#define TELLTALE "expectedstring" #define TELLTALE "expectedstring"
char telltale[16]; char telltale[16];
int isdongle; int isdongle;
int minor;
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
...@@ -328,6 +343,7 @@ int done[FRAME_BUFFER_MANY]; ...@@ -328,6 +343,7 @@ int done[FRAME_BUFFER_MANY];
wait_queue_head_t wq_video; wait_queue_head_t wq_video;
wait_queue_head_t wq_audio; wait_queue_head_t wq_audio;
wait_queue_head_t wq_trigger;
int input; int input;
int polled; int polled;
...@@ -428,6 +444,20 @@ int allocation_video_page; ...@@ -428,6 +444,20 @@ int allocation_video_page;
int allocation_video_struct; int allocation_video_struct;
int registered_video; int registered_video;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*
* ALSA
*/
/*---------------------------------------------------------------------------*/
#if defined(EASYCAP_NEEDS_ALSA)
struct snd_pcm_hardware alsa_hardware;
struct snd_card *psnd_card;
struct snd_pcm *psnd_pcm;
struct snd_pcm_substream *psubstream;
int dma_fill;
int dma_next;
int dma_read;
#endif /*EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
/* /*
* SOUND PROPERTIES * SOUND PROPERTIES
*/ */
...@@ -455,10 +485,10 @@ struct list_head *purb_audio_head; ...@@ -455,10 +485,10 @@ struct list_head *purb_audio_head;
* BUFFER INDICATORS * BUFFER INDICATORS
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int audio_fill; /* Audio buffer being filled by easysnd_complete(). */ int audio_fill; /* Audio buffer being filled by easycap_complete(). */
/* Bumped only by easysnd_complete(). */ /* Bumped only by easycap_complete(). */
int audio_read; /* Audio buffer page being read by easysnd_read(). */ int audio_read; /* Audio buffer page being read by easycap_read(). */
/* Set by easysnd_read() to trail audio_fill by */ /* Set by easycap_read() to trail audio_fill by */
/* one fragment. */ /* one fragment. */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -532,19 +562,39 @@ int adjust_volume(struct easycap *, int); ...@@ -532,19 +562,39 @@ int adjust_volume(struct easycap *, int);
* AUDIO FUNCTION PROTOTYPES * AUDIO FUNCTION PROTOTYPES
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void easysnd_complete(struct urb *); #if defined(EASYCAP_NEEDS_ALSA)
ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *); int easycap_alsa_probe(struct easycap *);
int easysnd_open(struct inode *, struct file *);
int easysnd_release(struct inode *, struct file *); void easycap_alsa_complete(struct urb *);
long easysnd_ioctl_noinode(struct file *, unsigned int, \ int easycap_alsa_open(struct snd_pcm_substream *);
int easycap_alsa_close(struct snd_pcm_substream *);
int easycap_alsa_hw_params(struct snd_pcm_substream *, \
struct snd_pcm_hw_params *);
int easycap_alsa_vmalloc(struct snd_pcm_substream *, size_t);
int easycap_alsa_hw_free(struct snd_pcm_substream *);
int easycap_alsa_prepare(struct snd_pcm_substream *);
int easycap_alsa_ack(struct snd_pcm_substream *);
int easycap_alsa_trigger(struct snd_pcm_substream *, int);
snd_pcm_uframes_t \
easycap_alsa_pointer(struct snd_pcm_substream *);
struct page *easycap_alsa_page(struct snd_pcm_substream *, unsigned long);
#else
void easyoss_complete(struct urb *);
ssize_t easyoss_read(struct file *, char __user *, size_t, loff_t *);
int easyoss_open(struct inode *, struct file *);
int easyoss_release(struct inode *, struct file *);
long easyoss_ioctl_noinode(struct file *, unsigned int, \
unsigned long); unsigned long);
int easysnd_ioctl(struct inode *, struct file *, unsigned int, \ int easyoss_ioctl(struct inode *, struct file *, unsigned int, \
unsigned long); unsigned long);
unsigned int easysnd_poll(struct file *, poll_table *); unsigned int easyoss_poll(struct file *, poll_table *);
void easysnd_delete(struct kref *); void easyoss_delete(struct kref *);
#endif /*EASYCAP_NEEDS_ALSA*/
int easycap_sound_setup(struct easycap *);
int submit_audio_urbs(struct easycap *); int submit_audio_urbs(struct easycap *);
int kill_audio_urbs(struct easycap *); int kill_audio_urbs(struct easycap *);
void easysnd_testtone(struct easycap *, int); void easyoss_testtone(struct easycap *, int);
int audio_setup(struct easycap *); int audio_setup(struct easycap *);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
......
...@@ -27,8 +27,6 @@ ...@@ -27,8 +27,6 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include "easycap.h" #include "easycap.h"
#include "easycap_debug.h"
#include "easycap_standard.h"
#include "easycap_ioctl.h" #include "easycap_ioctl.h"
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
...@@ -910,7 +908,7 @@ return -ENOENT; ...@@ -910,7 +908,7 @@ return -ENOENT;
* peasycap->audio_interface, \ * peasycap->audio_interface, \
* peasycap->audio_altsetting_off); * peasycap->audio_altsetting_off);
* HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
* -ESHUTDOWN. THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
* THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE. * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -991,11 +989,12 @@ if (NULL == p) { ...@@ -991,11 +989,12 @@ if (NULL == p) {
} }
kd = isdongle(peasycap); kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd); SAY("ERROR: cannot lock " \
"easycapdc60_dongle[%i].mutex_video\n", kd);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
...@@ -1007,24 +1006,24 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -1007,24 +1006,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
return -ERESTARTSYS; return -ERESTARTSYS;
if (NULL == file) { if (NULL == file) {
SAY("ERROR: file is NULL\n"); SAY("ERROR: file is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
peasycap = file->private_data; peasycap = file->private_data;
if (NULL == peasycap) { if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n"); SAY("ERROR: peasycap is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n"); SAY("ERROR: bad peasycap\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
p = peasycap->pusb_device; p = peasycap->pusb_device;
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
} else { } else {
...@@ -1048,7 +1047,7 @@ case VIDIOC_QUERYCAP: { ...@@ -1048,7 +1047,7 @@ case VIDIOC_QUERYCAP: {
if (16 <= strlen(EASYCAP_DRIVER_VERSION)) { if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
SAM("ERROR: bad driver version string\n"); SAM("ERROR: bad driver version string\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
strcpy(&version[0], EASYCAP_DRIVER_VERSION); strcpy(&version[0], EASYCAP_DRIVER_VERSION);
...@@ -1066,7 +1065,8 @@ case VIDIOC_QUERYCAP: { ...@@ -1066,7 +1065,8 @@ case VIDIOC_QUERYCAP: {
if (0 != rc) { if (0 != rc) {
SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \ SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
rc, p1); rc, p1);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].\
mutex_video);
return -EINVAL; return -EINVAL;
} }
k[i] = (int)lng; k[i] = (int)lng;
...@@ -1097,7 +1097,7 @@ case VIDIOC_QUERYCAP: { ...@@ -1097,7 +1097,7 @@ case VIDIOC_QUERYCAP: {
} }
if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \ if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
sizeof(struct v4l2_capability))) { sizeof(struct v4l2_capability))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1111,7 +1111,7 @@ case VIDIOC_ENUMINPUT: { ...@@ -1111,7 +1111,7 @@ case VIDIOC_ENUMINPUT: {
if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
sizeof(struct v4l2_input))) { sizeof(struct v4l2_input))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1193,14 +1193,14 @@ case VIDIOC_ENUMINPUT: { ...@@ -1193,14 +1193,14 @@ case VIDIOC_ENUMINPUT: {
} }
default: { default: {
JOM(8, "%i=index: exhausts inputs\n", index); JOM(8, "%i=index: exhausts inputs\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
if (0 != copy_to_user((void __user *)arg, &v4l2_input, \ if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
sizeof(struct v4l2_input))) { sizeof(struct v4l2_input))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1213,7 +1213,7 @@ case VIDIOC_G_INPUT: { ...@@ -1213,7 +1213,7 @@ case VIDIOC_G_INPUT: {
index = (__u32)peasycap->input; index = (__u32)peasycap->input;
JOM(8, "user is told: %i\n", index); JOM(8, "user is told: %i\n", index);
if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) { if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1227,7 +1227,7 @@ case VIDIOC_S_INPUT: ...@@ -1227,7 +1227,7 @@ case VIDIOC_S_INPUT:
JOM(8, "VIDIOC_S_INPUT\n"); JOM(8, "VIDIOC_S_INPUT\n");
if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) { if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1240,7 +1240,7 @@ case VIDIOC_S_INPUT: ...@@ -1240,7 +1240,7 @@ case VIDIOC_S_INPUT:
if ((0 > index) || (INPUT_MANY <= index)) { if ((0 > index) || (INPUT_MANY <= index)) {
JOM(8, "ERROR: bad requested input: %i\n", index); JOM(8, "ERROR: bad requested input: %i\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
...@@ -1249,7 +1249,7 @@ case VIDIOC_S_INPUT: ...@@ -1249,7 +1249,7 @@ case VIDIOC_S_INPUT:
JOM(8, "newinput(.,%i) OK\n", (int)index); JOM(8, "newinput(.,%i) OK\n", (int)index);
} else { } else {
SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc); SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1257,7 +1257,7 @@ case VIDIOC_S_INPUT: ...@@ -1257,7 +1257,7 @@ case VIDIOC_S_INPUT:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUMAUDIO: { case VIDIOC_ENUMAUDIO: {
JOM(8, "VIDIOC_ENUMAUDIO\n"); JOM(8, "VIDIOC_ENUMAUDIO\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
...@@ -1268,12 +1268,12 @@ case VIDIOC_ENUMAUDOUT: { ...@@ -1268,12 +1268,12 @@ case VIDIOC_ENUMAUDOUT: {
if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
sizeof(struct v4l2_audioout))) { sizeof(struct v4l2_audioout))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (0 != v4l2_audioout.index) { if (0 != v4l2_audioout.index) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout)); memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
...@@ -1282,7 +1282,7 @@ case VIDIOC_ENUMAUDOUT: { ...@@ -1282,7 +1282,7 @@ case VIDIOC_ENUMAUDOUT: {
if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \ if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
sizeof(struct v4l2_audioout))) { sizeof(struct v4l2_audioout))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1296,7 +1296,7 @@ case VIDIOC_QUERYCTRL: { ...@@ -1296,7 +1296,7 @@ case VIDIOC_QUERYCTRL: {
if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
sizeof(struct v4l2_queryctrl))) { sizeof(struct v4l2_queryctrl))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1313,12 +1313,12 @@ case VIDIOC_QUERYCTRL: { ...@@ -1313,12 +1313,12 @@ case VIDIOC_QUERYCTRL: {
} }
if (0xFFFFFFFF == easycap_control[i1].id) { if (0xFFFFFFFF == easycap_control[i1].id) {
JOM(8, "%i=index: exhausts controls\n", i1); JOM(8, "%i=index: exhausts controls\n", i1);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \ if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
sizeof(struct v4l2_queryctrl))) { sizeof(struct v4l2_queryctrl))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1326,7 +1326,7 @@ case VIDIOC_QUERYCTRL: { ...@@ -1326,7 +1326,7 @@ case VIDIOC_QUERYCTRL: {
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYMENU: { case VIDIOC_QUERYMENU: {
JOM(8, "VIDIOC_QUERYMENU unsupported\n"); JOM(8, "VIDIOC_QUERYMENU unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
...@@ -1337,13 +1337,13 @@ case VIDIOC_G_CTRL: { ...@@ -1337,13 +1337,13 @@ case VIDIOC_G_CTRL: {
pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL); pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
if (!pv4l2_control) { if (!pv4l2_control) {
SAM("ERROR: out of memory\n"); SAM("ERROR: out of memory\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM; return -ENOMEM;
} }
if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \ if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
sizeof(struct v4l2_control))) { sizeof(struct v4l2_control))) {
kfree(pv4l2_control); kfree(pv4l2_control);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1385,14 +1385,14 @@ case VIDIOC_G_CTRL: { ...@@ -1385,14 +1385,14 @@ case VIDIOC_G_CTRL: {
SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \ SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
pv4l2_control->id); pv4l2_control->id);
kfree(pv4l2_control); kfree(pv4l2_control);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
if (0 != copy_to_user((void __user *)arg, pv4l2_control, \ if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
sizeof(struct v4l2_control))) { sizeof(struct v4l2_control))) {
kfree(pv4l2_control); kfree(pv4l2_control);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
kfree(pv4l2_control); kfree(pv4l2_control);
...@@ -1412,7 +1412,7 @@ case VIDIOC_S_CTRL: ...@@ -1412,7 +1412,7 @@ case VIDIOC_S_CTRL:
if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
sizeof(struct v4l2_control))) { sizeof(struct v4l2_control))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1463,7 +1463,7 @@ case VIDIOC_S_CTRL: ...@@ -1463,7 +1463,7 @@ case VIDIOC_S_CTRL:
default: { default: {
SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \ SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
v4l2_control.id); v4l2_control.id);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
...@@ -1472,7 +1472,7 @@ case VIDIOC_S_CTRL: ...@@ -1472,7 +1472,7 @@ case VIDIOC_S_CTRL:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_EXT_CTRLS: { case VIDIOC_S_EXT_CTRLS: {
JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n"); JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
...@@ -1484,7 +1484,7 @@ case VIDIOC_ENUM_FMT: { ...@@ -1484,7 +1484,7 @@ case VIDIOC_ENUM_FMT: {
if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
sizeof(struct v4l2_fmtdesc))) { sizeof(struct v4l2_fmtdesc))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1539,13 +1539,13 @@ case VIDIOC_ENUM_FMT: { ...@@ -1539,13 +1539,13 @@ case VIDIOC_ENUM_FMT: {
} }
default: { default: {
JOM(8, "%i=index: exhausts formats\n", index); JOM(8, "%i=index: exhausts formats\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \ if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
sizeof(struct v4l2_fmtdesc))) { sizeof(struct v4l2_fmtdesc))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1564,7 +1564,7 @@ case VIDIOC_ENUM_FRAMESIZES: { ...@@ -1564,7 +1564,7 @@ case VIDIOC_ENUM_FRAMESIZES: {
if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
sizeof(struct v4l2_frmsizeenum))) { sizeof(struct v4l2_frmsizeenum))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1616,7 +1616,7 @@ case VIDIOC_ENUM_FRAMESIZES: { ...@@ -1616,7 +1616,7 @@ case VIDIOC_ENUM_FRAMESIZES: {
} }
default: { default: {
JOM(8, "%i=index: exhausts framesizes\n", index); JOM(8, "%i=index: exhausts framesizes\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
...@@ -1674,14 +1674,14 @@ case VIDIOC_ENUM_FRAMESIZES: { ...@@ -1674,14 +1674,14 @@ case VIDIOC_ENUM_FRAMESIZES: {
} }
default: { default: {
JOM(8, "%i=index: exhausts framesizes\n", index); JOM(8, "%i=index: exhausts framesizes\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
} }
if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \ if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
sizeof(struct v4l2_frmsizeenum))) { sizeof(struct v4l2_frmsizeenum))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1710,7 +1710,7 @@ case VIDIOC_ENUM_FRAMEINTERVALS: { ...@@ -1710,7 +1710,7 @@ case VIDIOC_ENUM_FRAMEINTERVALS: {
if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
sizeof(struct v4l2_frmivalenum))) { sizeof(struct v4l2_frmivalenum))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1737,13 +1737,13 @@ case VIDIOC_ENUM_FRAMEINTERVALS: { ...@@ -1737,13 +1737,13 @@ case VIDIOC_ENUM_FRAMEINTERVALS: {
} }
default: { default: {
JOM(8, "%i=index: exhausts frameintervals\n", index); JOM(8, "%i=index: exhausts frameintervals\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
} }
if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \ if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
sizeof(struct v4l2_frmivalenum))) { sizeof(struct v4l2_frmivalenum))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1757,28 +1757,28 @@ case VIDIOC_G_FMT: { ...@@ -1757,28 +1757,28 @@ case VIDIOC_G_FMT: {
pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL); pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
if (!pv4l2_format) { if (!pv4l2_format) {
SAM("ERROR: out of memory\n"); SAM("ERROR: out of memory\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM; return -ENOMEM;
} }
pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL); pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
if (!pv4l2_pix_format) { if (!pv4l2_pix_format) {
SAM("ERROR: out of memory\n"); SAM("ERROR: out of memory\n");
kfree(pv4l2_format); kfree(pv4l2_format);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM; return -ENOMEM;
} }
if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \ if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
sizeof(struct v4l2_format))) { sizeof(struct v4l2_format))) {
kfree(pv4l2_format); kfree(pv4l2_format);
kfree(pv4l2_pix_format); kfree(pv4l2_pix_format);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
kfree(pv4l2_format); kfree(pv4l2_format);
kfree(pv4l2_pix_format); kfree(pv4l2_pix_format);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
...@@ -1794,7 +1794,7 @@ case VIDIOC_G_FMT: { ...@@ -1794,7 +1794,7 @@ case VIDIOC_G_FMT: {
sizeof(struct v4l2_format))) { sizeof(struct v4l2_format))) {
kfree(pv4l2_format); kfree(pv4l2_format);
kfree(pv4l2_pix_format); kfree(pv4l2_pix_format);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
kfree(pv4l2_format); kfree(pv4l2_format);
...@@ -1819,7 +1819,7 @@ case VIDIOC_S_FMT: { ...@@ -1819,7 +1819,7 @@ case VIDIOC_S_FMT: {
if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
sizeof(struct v4l2_format))) { sizeof(struct v4l2_format))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1831,11 +1831,11 @@ case VIDIOC_S_FMT: { ...@@ -1831,11 +1831,11 @@ case VIDIOC_S_FMT: {
try); try);
if (0 > best_format) { if (0 > best_format) {
if (-EBUSY == best_format) { if (-EBUSY == best_format) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EBUSY; return -EBUSY;
} }
JOM(8, "WARNING: adjust_format() returned %i\n", best_format); JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOENT; return -ENOENT;
} }
/*...........................................................................*/ /*...........................................................................*/
...@@ -1848,7 +1848,7 @@ case VIDIOC_S_FMT: { ...@@ -1848,7 +1848,7 @@ case VIDIOC_S_FMT: {
if (0 != copy_to_user((void __user *)arg, &v4l2_format, \ if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
sizeof(struct v4l2_format))) { sizeof(struct v4l2_format))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1861,7 +1861,7 @@ case VIDIOC_CROPCAP: { ...@@ -1861,7 +1861,7 @@ case VIDIOC_CROPCAP: {
if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
sizeof(struct v4l2_cropcap))) { sizeof(struct v4l2_cropcap))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1885,7 +1885,7 @@ case VIDIOC_CROPCAP: { ...@@ -1885,7 +1885,7 @@ case VIDIOC_CROPCAP: {
if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \ if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
sizeof(struct v4l2_cropcap))) { sizeof(struct v4l2_cropcap))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1894,14 +1894,14 @@ case VIDIOC_CROPCAP: { ...@@ -1894,14 +1894,14 @@ case VIDIOC_CROPCAP: {
case VIDIOC_G_CROP: case VIDIOC_G_CROP:
case VIDIOC_S_CROP: { case VIDIOC_S_CROP: {
JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n"); JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYSTD: { case VIDIOC_QUERYSTD: {
JOM(8, "VIDIOC_QUERYSTD: " \ JOM(8, "VIDIOC_QUERYSTD: " \
"EasyCAP is incapable of detecting standard\n"); "EasyCAP is incapable of detecting standard\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
break; break;
} }
...@@ -1923,7 +1923,7 @@ case VIDIOC_ENUMSTD: { ...@@ -1923,7 +1923,7 @@ case VIDIOC_ENUMSTD: {
if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
sizeof(struct v4l2_standard))) { sizeof(struct v4l2_standard))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
index = v4l2_standard.index; index = v4l2_standard.index;
...@@ -1945,7 +1945,7 @@ case VIDIOC_ENUMSTD: { ...@@ -1945,7 +1945,7 @@ case VIDIOC_ENUMSTD: {
} }
if (0xFFFF == peasycap_standard->mask) { if (0xFFFF == peasycap_standard->mask) {
JOM(8, "%i=index: exhausts standards\n", index); JOM(8, "%i=index: exhausts standards\n", index);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
JOM(8, "%i=index: %s\n", index, \ JOM(8, "%i=index: %s\n", index, \
...@@ -1957,7 +1957,7 @@ case VIDIOC_ENUMSTD: { ...@@ -1957,7 +1957,7 @@ case VIDIOC_ENUMSTD: {
if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \ if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
sizeof(struct v4l2_standard))) { sizeof(struct v4l2_standard))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -1972,13 +1972,13 @@ case VIDIOC_G_STD: { ...@@ -1972,13 +1972,13 @@ case VIDIOC_G_STD: {
if (0 > peasycap->standard_offset) { if (0 > peasycap->standard_offset) {
JOM(8, "%i=peasycap->standard_offset\n", \ JOM(8, "%i=peasycap->standard_offset\n", \
peasycap->standard_offset); peasycap->standard_offset);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EBUSY; return -EBUSY;
} }
if (0 != copy_from_user(&std_id, (void __user *)arg, \ if (0 != copy_from_user(&std_id, (void __user *)arg, \
sizeof(v4l2_std_id))) { sizeof(v4l2_std_id))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -1990,7 +1990,7 @@ case VIDIOC_G_STD: { ...@@ -1990,7 +1990,7 @@ case VIDIOC_G_STD: {
if (0 != copy_to_user((void __user *)arg, &std_id, \ if (0 != copy_to_user((void __user *)arg, &std_id, \
sizeof(v4l2_std_id))) { sizeof(v4l2_std_id))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2004,7 +2004,7 @@ case VIDIOC_S_STD: { ...@@ -2004,7 +2004,7 @@ case VIDIOC_S_STD: {
if (0 != copy_from_user(&std_id, (void __user *)arg, \ if (0 != copy_from_user(&std_id, (void __user *)arg, \
sizeof(v4l2_std_id))) { sizeof(v4l2_std_id))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -2015,7 +2015,7 @@ case VIDIOC_S_STD: { ...@@ -2015,7 +2015,7 @@ case VIDIOC_S_STD: {
rc = adjust_standard(peasycap, std_id); rc = adjust_standard(peasycap, std_id);
if (0 > rc) { if (0 > rc) {
JOM(8, "WARNING: adjust_standard() returned %i\n", rc); JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOENT; return -ENOENT;
} }
break; break;
...@@ -2029,16 +2029,16 @@ case VIDIOC_REQBUFS: { ...@@ -2029,16 +2029,16 @@ case VIDIOC_REQBUFS: {
if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
sizeof(struct v4l2_requestbuffers))) { sizeof(struct v4l2_requestbuffers))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) { if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
nbuffers = v4l2_requestbuffers.count; nbuffers = v4l2_requestbuffers.count;
...@@ -2059,7 +2059,7 @@ case VIDIOC_REQBUFS: { ...@@ -2059,7 +2059,7 @@ case VIDIOC_REQBUFS: {
if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \ if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
sizeof(struct v4l2_requestbuffers))) { sizeof(struct v4l2_requestbuffers))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2074,18 +2074,18 @@ case VIDIOC_QUERYBUF: { ...@@ -2074,18 +2074,18 @@ case VIDIOC_QUERYBUF: {
if (peasycap->video_eof) { if (peasycap->video_eof) {
JOM(8, "returning -EIO because %i=video_eof\n", \ JOM(8, "returning -EIO because %i=video_eof\n", \
peasycap->video_eof); peasycap->video_eof);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO; return -EIO;
} }
if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
sizeof(struct v4l2_buffer))) { sizeof(struct v4l2_buffer))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
index = v4l2_buffer.index; index = v4l2_buffer.index;
...@@ -2117,7 +2117,7 @@ case VIDIOC_QUERYBUF: { ...@@ -2117,7 +2117,7 @@ case VIDIOC_QUERYBUF: {
if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
sizeof(struct v4l2_buffer))) { sizeof(struct v4l2_buffer))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2130,21 +2130,21 @@ case VIDIOC_QBUF: { ...@@ -2130,21 +2130,21 @@ case VIDIOC_QBUF: {
if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
sizeof(struct v4l2_buffer))) { sizeof(struct v4l2_buffer))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) { if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
if (v4l2_buffer.index < 0 || \ if (v4l2_buffer.index < 0 || \
(v4l2_buffer.index >= peasycap->frame_buffer_many)) { (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED; v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
...@@ -2154,7 +2154,7 @@ case VIDIOC_QBUF: { ...@@ -2154,7 +2154,7 @@ case VIDIOC_QBUF: {
if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
sizeof(struct v4l2_buffer))) { sizeof(struct v4l2_buffer))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -2187,18 +2187,18 @@ case VIDIOC_DQBUF: ...@@ -2187,18 +2187,18 @@ case VIDIOC_DQBUF:
JOM(8, "returning -EIO because " \ JOM(8, "returning -EIO because " \
"%i=video_idle %i=video_eof\n", \ "%i=video_idle %i=video_eof\n", \
peasycap->video_idle, peasycap->video_eof); peasycap->video_idle, peasycap->video_eof);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO; return -EIO;
} }
if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
sizeof(struct v4l2_buffer))) { sizeof(struct v4l2_buffer))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
...@@ -2222,7 +2222,7 @@ case VIDIOC_DQBUF: ...@@ -2222,7 +2222,7 @@ case VIDIOC_DQBUF:
if (!peasycap->video_isoc_streaming) { if (!peasycap->video_isoc_streaming) {
JOM(16, "returning -EIO because video urbs not streaming\n"); JOM(16, "returning -EIO because video urbs not streaming\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO; return -EIO;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -2239,18 +2239,19 @@ case VIDIOC_DQBUF: ...@@ -2239,18 +2239,19 @@ case VIDIOC_DQBUF:
if (-EIO == rcdq) { if (-EIO == rcdq) {
JOM(8, "returning -EIO because " \ JOM(8, "returning -EIO because " \
"dqbuf() returned -EIO\n"); "dqbuf() returned -EIO\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].\
mutex_video);
return -EIO; return -EIO;
} }
} while (0 != rcdq); } while (0 != rcdq);
} else { } else {
if (peasycap->video_eof) { if (peasycap->video_eof) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO; return -EIO;
} }
} }
if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) { if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \ JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n", \
peasycap->done[peasycap->frame_read]); peasycap->done[peasycap->frame_read]);
} }
peasycap->polled = 0; peasycap->polled = 0;
...@@ -2337,7 +2338,7 @@ case VIDIOC_DQBUF: ...@@ -2337,7 +2338,7 @@ case VIDIOC_DQBUF:
if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
sizeof(struct v4l2_buffer))) { sizeof(struct v4l2_buffer))) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -2370,7 +2371,7 @@ case VIDIOC_STREAMON: { ...@@ -2370,7 +2371,7 @@ case VIDIOC_STREAMON: {
peasycap->merit[i] = 0; peasycap->merit[i] = 0;
if ((struct usb_device *)NULL == peasycap->pusb_device) { if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
submit_video_urbs(peasycap); submit_video_urbs(peasycap);
...@@ -2386,7 +2387,7 @@ case VIDIOC_STREAMOFF: { ...@@ -2386,7 +2387,7 @@ case VIDIOC_STREAMOFF: {
if ((struct usb_device *)NULL == peasycap->pusb_device) { if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
...@@ -2400,7 +2401,12 @@ case VIDIOC_STREAMOFF: { ...@@ -2400,7 +2401,12 @@ case VIDIOC_STREAMOFF: {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
JOM(8, "calling wake_up on wq_video and wq_audio\n"); JOM(8, "calling wake_up on wq_video and wq_audio\n");
wake_up_interruptible(&(peasycap->wq_video)); wake_up_interruptible(&(peasycap->wq_video));
#if defined(EASYCAP_NEEDS_ALSA)
if (NULL != peasycap->psubstream)
snd_pcm_period_elapsed(peasycap->psubstream);
#else
wake_up_interruptible(&(peasycap->wq_audio)); wake_up_interruptible(&(peasycap->wq_audio));
#endif /*EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
break; break;
} }
...@@ -2412,19 +2418,19 @@ case VIDIOC_G_PARM: { ...@@ -2412,19 +2418,19 @@ case VIDIOC_G_PARM: {
pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL); pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
if (!pv4l2_streamparm) { if (!pv4l2_streamparm) {
SAM("ERROR: out of memory\n"); SAM("ERROR: out of memory\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM; return -ENOMEM;
} }
if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \ if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
sizeof(struct v4l2_streamparm))) { sizeof(struct v4l2_streamparm))) {
kfree(pv4l2_streamparm); kfree(pv4l2_streamparm);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
kfree(pv4l2_streamparm); kfree(pv4l2_streamparm);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
pv4l2_streamparm->parm.capture.capability = 0; pv4l2_streamparm->parm.capture.capability = 0;
...@@ -2450,7 +2456,7 @@ case VIDIOC_G_PARM: { ...@@ -2450,7 +2456,7 @@ case VIDIOC_G_PARM: {
if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \ if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
sizeof(struct v4l2_streamparm))) { sizeof(struct v4l2_streamparm))) {
kfree(pv4l2_streamparm); kfree(pv4l2_streamparm);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT; return -EFAULT;
} }
kfree(pv4l2_streamparm); kfree(pv4l2_streamparm);
...@@ -2459,25 +2465,25 @@ case VIDIOC_G_PARM: { ...@@ -2459,25 +2465,25 @@ case VIDIOC_G_PARM: {
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_PARM: { case VIDIOC_S_PARM: {
JOM(8, "VIDIOC_S_PARM unsupported\n"); JOM(8, "VIDIOC_S_PARM unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_AUDIO: { case VIDIOC_G_AUDIO: {
JOM(8, "VIDIOC_G_AUDIO unsupported\n"); JOM(8, "VIDIOC_G_AUDIO unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_AUDIO: { case VIDIOC_S_AUDIO: {
JOM(8, "VIDIOC_S_AUDIO unsupported\n"); JOM(8, "VIDIOC_S_AUDIO unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_TUNER: { case VIDIOC_S_TUNER: {
JOM(8, "VIDIOC_S_TUNER unsupported\n"); JOM(8, "VIDIOC_S_TUNER unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
...@@ -2485,45 +2491,46 @@ case VIDIOC_G_FBUF: ...@@ -2485,45 +2491,46 @@ case VIDIOC_G_FBUF:
case VIDIOC_S_FBUF: case VIDIOC_S_FBUF:
case VIDIOC_OVERLAY: { case VIDIOC_OVERLAY: {
JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n"); JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_TUNER: { case VIDIOC_G_TUNER: {
JOM(8, "VIDIOC_G_TUNER unsupported\n"); JOM(8, "VIDIOC_G_TUNER unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
case VIDIOC_G_FREQUENCY: case VIDIOC_G_FREQUENCY:
case VIDIOC_S_FREQUENCY: { case VIDIOC_S_FREQUENCY: {
JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n"); JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL; return -EINVAL;
} }
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
default: { default: {
JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd); JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
} }
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
#if !defined(EASYCAP_NEEDS_ALSA)
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \ #if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
(defined(EASYCAP_NEEDS_UNLOCKED_IOCTL))) (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
long long
easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) { easyoss_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg); return (long)easyoss_ioctl((struct inode *)NULL, file, cmd, arg);
} }
#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
easysnd_ioctl(struct inode *inode, struct file *file, easyoss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct easycap *peasycap; struct easycap *peasycap;
...@@ -2550,11 +2557,12 @@ if (NULL == p) { ...@@ -2550,11 +2557,12 @@ if (NULL == p) {
} }
kd = isdongle(peasycap); kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd); SAY("ERROR: cannot lock "
"easycapdc60_dongle[%i].mutex_audio\n", kd);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
...@@ -2566,24 +2574,24 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -2566,24 +2574,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
return -ERESTARTSYS; return -ERESTARTSYS;
if (NULL == file) { if (NULL == file) {
SAY("ERROR: file is NULL\n"); SAY("ERROR: file is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
peasycap = file->private_data; peasycap = file->private_data;
if (NULL == peasycap) { if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n"); SAY("ERROR: peasycap is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n"); SAY("ERROR: bad peasycap\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
p = peasycap->pusb_device; p = peasycap->pusb_device;
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
} else { } else {
...@@ -2614,7 +2622,7 @@ case SNDCTL_DSP_GETCAPS: { ...@@ -2614,7 +2622,7 @@ case SNDCTL_DSP_GETCAPS: {
#endif /*UPSAMPLE*/ #endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) { if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2636,7 +2644,7 @@ case SNDCTL_DSP_GETFMTS: { ...@@ -2636,7 +2644,7 @@ case SNDCTL_DSP_GETFMTS: {
#endif /*UPSAMPLE*/ #endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2645,7 +2653,7 @@ case SNDCTL_DSP_SETFMT: { ...@@ -2645,7 +2653,7 @@ case SNDCTL_DSP_SETFMT: {
int incoming, outgoing; int incoming, outgoing;
JOM(8, "SNDCTL_DSP_SETFMT\n"); JOM(8, "SNDCTL_DSP_SETFMT\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(8, "........... %i=incoming\n", incoming); JOM(8, "........... %i=incoming\n", incoming);
...@@ -2668,10 +2676,10 @@ case SNDCTL_DSP_SETFMT: { ...@@ -2668,10 +2676,10 @@ case SNDCTL_DSP_SETFMT: {
JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8); JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8);
if (0 != copy_to_user((void __user *)arg, &outgoing, \ if (0 != copy_to_user((void __user *)arg, &outgoing, \
sizeof(int))) { sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EINVAL ; return -EINVAL ;
} }
break; break;
...@@ -2680,7 +2688,7 @@ case SNDCTL_DSP_STEREO: { ...@@ -2680,7 +2688,7 @@ case SNDCTL_DSP_STEREO: {
int incoming; int incoming;
JOM(8, "SNDCTL_DSP_STEREO\n"); JOM(8, "SNDCTL_DSP_STEREO\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(8, "........... %i=incoming\n", incoming); JOM(8, "........... %i=incoming\n", incoming);
...@@ -2698,7 +2706,7 @@ case SNDCTL_DSP_STEREO: { ...@@ -2698,7 +2706,7 @@ case SNDCTL_DSP_STEREO: {
#endif /*UPSAMPLE*/ #endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2707,7 +2715,7 @@ case SNDCTL_DSP_SPEED: { ...@@ -2707,7 +2715,7 @@ case SNDCTL_DSP_SPEED: {
int incoming; int incoming;
JOM(8, "SNDCTL_DSP_SPEED\n"); JOM(8, "SNDCTL_DSP_SPEED\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(8, "........... %i=incoming\n", incoming); JOM(8, "........... %i=incoming\n", incoming);
...@@ -2725,7 +2733,7 @@ case SNDCTL_DSP_SPEED: { ...@@ -2725,7 +2733,7 @@ case SNDCTL_DSP_SPEED: {
#endif /*UPSAMPLE*/ #endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2734,14 +2742,14 @@ case SNDCTL_DSP_GETTRIGGER: { ...@@ -2734,14 +2742,14 @@ case SNDCTL_DSP_GETTRIGGER: {
int incoming; int incoming;
JOM(8, "SNDCTL_DSP_GETTRIGGER\n"); JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(8, "........... %i=incoming\n", incoming); JOM(8, "........... %i=incoming\n", incoming);
incoming = PCM_ENABLE_INPUT; incoming = PCM_ENABLE_INPUT;
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2750,7 +2758,7 @@ case SNDCTL_DSP_SETTRIGGER: { ...@@ -2750,7 +2758,7 @@ case SNDCTL_DSP_SETTRIGGER: {
int incoming; int incoming;
JOM(8, "SNDCTL_DSP_SETTRIGGER\n"); JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(8, "........... %i=incoming\n", incoming); JOM(8, "........... %i=incoming\n", incoming);
...@@ -2767,13 +2775,13 @@ case SNDCTL_DSP_GETBLKSIZE: { ...@@ -2767,13 +2775,13 @@ case SNDCTL_DSP_GETBLKSIZE: {
int incoming; int incoming;
JOM(8, "SNDCTL_DSP_GETBLKSIZE\n"); JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) { if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(8, "........... %i=incoming\n", incoming); JOM(8, "........... %i=incoming\n", incoming);
incoming = peasycap->audio_bytes_per_fragment; incoming = peasycap->audio_bytes_per_fragment;
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) { if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2790,7 +2798,7 @@ case SNDCTL_DSP_GETISPACE: { ...@@ -2790,7 +2798,7 @@ case SNDCTL_DSP_GETISPACE: {
if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \ if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
sizeof(int))) { sizeof(int))) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
break; break;
...@@ -2802,18 +2810,18 @@ case 0x00005404: ...@@ -2802,18 +2810,18 @@ case 0x00005404:
case 0x00005405: case 0x00005405:
case 0x00005406: { case 0x00005406: {
JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd); JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
default: { default: {
JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd); JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
} }
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0; return 0;
} }
#endif /*EASYCAP_NEEDS_ALSA*/
/*****************************************************************************/ /*****************************************************************************/
...@@ -24,5 +24,14 @@ ...@@ -24,5 +24,14 @@
* *
*/ */
/*****************************************************************************/ /*****************************************************************************/
#if !defined(EASYCAP_IOCTL_H)
#define EASYCAP_IOCTL_H
extern int easycap_debug;
extern int easycap_gain;
extern struct easycap_dongle easycapdc60_dongle[];
extern struct easycap_standard easycap_standard[];
extern struct easycap_format easycap_format[]; extern struct easycap_format easycap_format[];
extern struct v4l2_queryctrl easycap_control[]; extern struct v4l2_queryctrl easycap_control[];
#endif /*EASYCAP_IOCTL_H*/
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
/****************************************************************************/ /****************************************************************************/
#include "easycap.h" #include "easycap.h"
#include "easycap_debug.h" #include "easycap_low.h"
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
const struct stk1160config { int reg; int set; } stk1160configPAL[256] = { const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
...@@ -1052,9 +1052,18 @@ rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ ...@@ -1052,9 +1052,18 @@ rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \
(int)50000); (int)50000);
JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0])); JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0]));
if (rc != (int)length) if (rc != (int)length) {
switch (rc) {
case -EPIPE: {
SAY("usb_control_msg returned -EPIPE\n");
break;
}
default: {
SAY("ERROR: usb_control_msg returned %i\n", rc); SAY("ERROR: usb_control_msg returned %i\n", rc);
break;
}
}
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* /*
* REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ??? * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
......
/***************************************************************************** /*****************************************************************************
* * * *
* easycap_debug.h * * easycap_low.h *
* * * *
*****************************************************************************/ *****************************************************************************/
/* /*
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
* *
*/ */
/*****************************************************************************/ /*****************************************************************************/
#if !defined(EASYCAP_LOW_H)
#define EASYCAP_LOW_H
extern int easycap_debug; extern int easycap_debug;
extern int easycap_gain; extern int easycap_gain;
extern struct easycap_dongle easycap_dongle[]; extern struct easycap_dongle easycapdc60_dongle[];
#endif /*EASYCAP_LOW_H*/
...@@ -29,30 +29,17 @@ ...@@ -29,30 +29,17 @@
/*****************************************************************************/ /*****************************************************************************/
#include "easycap.h" #include "easycap.h"
#include "easycap_standard.h" #include "easycap_main.h"
#include "easycap_ioctl.h"
int easycap_debug; int easycap_debug;
static int easycap_bars; static int easycap_bars = 1;
int easycap_gain = 16; int easycap_gain = 16;
module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR); module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR); module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR); module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
/*---------------------------------------------------------------------------*/ struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
/* static struct mutex mutex_dongle;
* dongle_this IS INDISPENSIBLY static BECAUSE FUNCTION easycap_usb_probe()
* IS CALLED SUCCESSIVELY FOR INTERFACES 0, 1, 2 AND THE POINTER peasycap
* ALLOCATED DURING THE PROBING OF INTERFACE 0 MUST BE REMEMBERED WHEN
* PROBING INTERFACES 1 AND 2.
*
* IOCTL LOCKING IS DONE AT MODULE LEVEL, NOT DEVICE LEVEL.
*/
/*---------------------------------------------------------------------------*/
struct easycap_dongle easycap_dongle[DONGLE_MANY];
static int dongle_this;
static int dongle_done;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -120,28 +107,6 @@ const struct v4l2_file_operations v4l2_fops = { ...@@ -120,28 +107,6 @@ const struct v4l2_file_operations v4l2_fops = {
#endif /*EASYCAP_NEEDS_V4L2_FOPS*/ #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/*--------------------------------------------------------------------------*/
/*
* PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
*/
/*--------------------------------------------------------------------------*/
const struct file_operations easysnd_fops = {
.owner = THIS_MODULE,
.open = easysnd_open,
.release = easysnd_release,
#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
.unlocked_ioctl = easysnd_ioctl_noinode,
#else
.ioctl = easysnd_ioctl,
#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
.read = easysnd_read,
.llseek = no_llseek,
};
struct usb_class_driver easysnd_class = {
.name = "usb/easysnd%d",
.fops = &easysnd_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};
/****************************************************************************/ /****************************************************************************/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -155,7 +120,7 @@ int k; ...@@ -155,7 +120,7 @@ int k;
if (NULL == peasycap) if (NULL == peasycap)
return -2; return -2;
for (k = 0; k < DONGLE_MANY; k++) { for (k = 0; k < DONGLE_MANY; k++) {
if (easycap_dongle[k].peasycap == peasycap) { if (easycapdc60_dongle[k].peasycap == peasycap) {
peasycap->isdongle = k; peasycap->isdongle = k;
return k; return k;
} }
...@@ -1055,9 +1020,10 @@ for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { ...@@ -1055,9 +1020,10 @@ for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
m++; m++;
} }
} }
JOM(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \ JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n", \
m * (0x01 << AUDIO_ISOC_ORDER)); m * (0x01 << AUDIO_ISOC_ORDER));
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if !defined(EASYCAP_NEEDS_ALSA)
JOM(4, "freeing audio buffers.\n"); JOM(4, "freeing audio buffers.\n");
gone = 0; gone = 0;
for (k = 0; k < peasycap->audio_buffer_page_many; k++) { for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
...@@ -1068,7 +1034,8 @@ for (k = 0; k < peasycap->audio_buffer_page_many; k++) { ...@@ -1068,7 +1034,8 @@ for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
gone++; gone++;
} }
} }
JOM(4, "easysnd_delete(): audio buffers freed: %i pages\n", gone); JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
#endif /*!EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
JOM(4, "freeing easycap structure.\n"); JOM(4, "freeing easycap structure.\n");
allocation_video_urb = peasycap->allocation_video_urb; allocation_video_urb = peasycap->allocation_video_urb;
...@@ -1081,12 +1048,20 @@ allocation_audio_struct = peasycap->allocation_audio_struct; ...@@ -1081,12 +1048,20 @@ allocation_audio_struct = peasycap->allocation_audio_struct;
registered_audio = peasycap->registered_audio; registered_audio = peasycap->registered_audio;
kfree(peasycap); kfree(peasycap);
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
easycap_dongle[kd].peasycap = (struct easycap *)NULL; if (mutex_lock_interruptible(&mutex_dongle)) {
JOT(4, " null-->easycap_dongle[%i].peasycap\n", kd); SAY("ERROR: cannot down mutex_dongle\n");
} else {
JOM(4, "locked mutex_dongle\n");
easycapdc60_dongle[kd].peasycap = (struct easycap *)NULL;
mutex_unlock(&mutex_dongle);
JOM(4, "unlocked mutex_dongle\n");
JOT(4, " null-->easycapdc60_dongle[%i].peasycap\n", kd);
allocation_video_struct -= sizeof(struct easycap); allocation_video_struct -= sizeof(struct easycap);
}
} else { } else {
SAY("ERROR: cannot purge easycap_dongle[].peasycap"); SAY("ERROR: cannot purge easycapdc60_dongle[].peasycap");
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
SAY("%8i= video urbs after all deletions\n", allocation_video_urb); SAY("%8i= video urbs after all deletions\n", allocation_video_urb);
...@@ -1131,11 +1106,12 @@ if (NULL == peasycap->pusb_device) { ...@@ -1131,11 +1106,12 @@ if (NULL == peasycap->pusb_device) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
kd = isdongle(peasycap); kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd); SAY("ERROR: cannot down "
"easycapdc60_dongle[%i].mutex_video\n", kd);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/* /*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
...@@ -1147,24 +1123,24 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -1147,24 +1123,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
return -ERESTARTSYS; return -ERESTARTSYS;
if (NULL == file) { if (NULL == file) {
SAY("ERROR: file is NULL\n"); SAY("ERROR: file is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
peasycap = file->private_data; peasycap = file->private_data;
if (NULL == peasycap) { if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n"); SAY("ERROR: peasycap is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap: 0x%08lX\n", \ SAY("ERROR: bad peasycap: 0x%08lX\n", \
(unsigned long int) peasycap); (unsigned long int) peasycap);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
} else } else
...@@ -1179,7 +1155,7 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -1179,7 +1155,7 @@ if (0 <= kd && DONGLE_MANY > kd) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
rc = easycap_dqbuf(peasycap, 0); rc = easycap_dqbuf(peasycap, 0);
peasycap->polled = 1; peasycap->polled = 1;
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
if (0 == rc) if (0 == rc)
return POLLIN | POLLRDNORM; return POLLIN | POLLRDNORM;
else else
...@@ -3391,20 +3367,13 @@ return; ...@@ -3391,20 +3367,13 @@ return;
/*****************************************************************************/ /*****************************************************************************/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
* FIXME * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
*
*
* THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE EasyCAP
* IS PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST.
* IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops.
*
* THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
easycap_usb_probe(struct usb_interface *pusb_interface, \ easycap_usb_probe(struct usb_interface *pusb_interface, \
const struct usb_device_id *id) const struct usb_device_id *pusb_device_id)
{ {
struct usb_device *pusb_device, *pusb_device1; struct usb_device *pusb_device, *pusb_device1;
struct usb_host_interface *pusb_host_interface; struct usb_host_interface *pusb_host_interface;
...@@ -3413,6 +3382,7 @@ struct usb_interface_descriptor *pusb_interface_descriptor; ...@@ -3413,6 +3382,7 @@ struct usb_interface_descriptor *pusb_interface_descriptor;
struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor; struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
struct urb *purb; struct urb *purb;
struct easycap *peasycap; struct easycap *peasycap;
int ndong;
struct data_urb *pdata_urb; struct data_urb *pdata_urb;
size_t wMaxPacketSize; size_t wMaxPacketSize;
int ISOCwMaxPacketSize; int ISOCwMaxPacketSize;
...@@ -3434,24 +3404,19 @@ int maxpacketsize; ...@@ -3434,24 +3404,19 @@ int maxpacketsize;
__u16 mask; __u16 mask;
__s32 value; __s32 value;
struct easycap_format *peasycap_format; struct easycap_format *peasycap_format;
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
JOT(4, "\n"); #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
if (!dongle_done) { struct v4l2_device *pv4l2_device;
dongle_done = 1; #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
for (k = 0; k < DONGLE_MANY; k++) { #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
easycap_dongle[k].peasycap = (struct easycap *)NULL; /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
mutex_init(&easycap_dongle[k].mutex_video);
mutex_init(&easycap_dongle[k].mutex_audio);
}
}
peasycap = (struct easycap *)NULL;
if ((struct usb_interface *)NULL == pusb_interface) { if ((struct usb_interface *)NULL == pusb_interface) {
SAY("ERROR: pusb_interface is NULL\n"); SAY("ERROR: pusb_interface is NULL\n");
return -EFAULT; return -EFAULT;
} }
peasycap = (struct easycap *)NULL;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* GET POINTER TO STRUCTURE usb_device * GET POINTER TO STRUCTURE usb_device
...@@ -3472,9 +3437,7 @@ if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) { ...@@ -3472,9 +3437,7 @@ if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) {
JOT(4, "ERROR: pusb_device1 != pusb_device\n"); JOT(4, "ERROR: pusb_device1 != pusb_device\n");
return -EFAULT; return -EFAULT;
} }
JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations); JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
pusb_host_interface = pusb_interface->cur_altsetting; pusb_host_interface = pusb_interface->cur_altsetting;
if (NULL == pusb_host_interface) { if (NULL == pusb_host_interface) {
...@@ -3553,9 +3516,6 @@ JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \ ...@@ -3553,9 +3516,6 @@ JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \
* *
* THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
* INTERFACES 1 AND 2 ARE PROBED. * INTERFACES 1 AND 2 ARE PROBED.
*
* IF TWO EasyCAPs ARE PLUGGED IN NEARLY SIMULTANEOUSLY THERE WILL
* BE TROUBLE. BEWARE.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if (0 == bInterfaceNumber) { if (0 == bInterfaceNumber) {
...@@ -3580,6 +3540,7 @@ if (0 == bInterfaceNumber) { ...@@ -3580,6 +3540,7 @@ if (0 == bInterfaceNumber) {
* PERFORM URGENT INTIALIZATIONS ... * PERFORM URGENT INTIALIZATIONS ...
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
peasycap->minor = -1;
strcpy(&peasycap->telltale[0], TELLTALE); strcpy(&peasycap->telltale[0], TELLTALE);
kref_init(&peasycap->kref); kref_init(&peasycap->kref);
JOM(8, "intf[%i]: after kref_init(..._video) " \ JOM(8, "intf[%i]: after kref_init(..._video) " \
...@@ -3588,29 +3549,43 @@ if (0 == bInterfaceNumber) { ...@@ -3588,29 +3549,43 @@ if (0 == bInterfaceNumber) {
init_waitqueue_head(&peasycap->wq_video); init_waitqueue_head(&peasycap->wq_video);
init_waitqueue_head(&peasycap->wq_audio); init_waitqueue_head(&peasycap->wq_audio);
init_waitqueue_head(&peasycap->wq_trigger);
for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) { if (mutex_lock_interruptible(&mutex_dongle)) {
if (NULL == easycap_dongle[dongle_this].peasycap) { SAY("ERROR: cannot down mutex_dongle\n");
if (0 == mutex_is_locked(&easycap_dongle\ return -ERESTARTSYS;
[dongle_this].mutex_video)) { } else {
if (0 == mutex_is_locked(&easycap_dongle\ /*---------------------------------------------------------------------------*/
[dongle_this].mutex_audio)) { /*
easycap_dongle\ * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
[dongle_this].peasycap = \ * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
peasycap; *
* NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
* PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
* EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
*/
/*---------------------------------------------------------------------------*/
for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
if ((NULL == easycapdc60_dongle[ndong].peasycap) && \
(!mutex_is_locked(&easycapdc60_dongle\
[ndong].mutex_video)) && \
(!mutex_is_locked(&easycapdc60_dongle\
[ndong].mutex_audio))) {
easycapdc60_dongle[ndong].peasycap = peasycap;
peasycap->isdongle = ndong;
JOM(8, "intf[%i]: peasycap-->easycap" \ JOM(8, "intf[%i]: peasycap-->easycap" \
"_dongle[%i].peasycap\n", \ "_dongle[%i].peasycap\n", \
bInterfaceNumber, dongle_this); bInterfaceNumber, ndong);
break; break;
} }
} }
} if (DONGLE_MANY <= ndong) {
}
if (DONGLE_MANY <= dongle_this) {
SAM("ERROR: too many dongles\n"); SAM("ERROR: too many dongles\n");
mutex_unlock(&mutex_dongle);
return -ENOMEM; return -ENOMEM;
} }
mutex_unlock(&mutex_dongle);
}
peasycap->allocation_video_struct = sizeof(struct easycap); peasycap->allocation_video_struct = sizeof(struct easycap);
peasycap->allocation_video_page = 0; peasycap->allocation_video_page = 0;
peasycap->allocation_video_urb = 0; peasycap->allocation_video_urb = 0;
...@@ -3778,26 +3753,56 @@ if (0 == bInterfaceNumber) { ...@@ -3778,26 +3753,56 @@ if (0 == bInterfaceNumber) {
JOM(4, "finished initialization\n"); JOM(4, "finished initialization\n");
} else { } else {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* FOR INTERFACES 1 AND 2 THE POINTER peasycap IS OBTAINED BY ASSUMING * FIXME
* THAT dongle_this HAS NOT CHANGED SINCE INTERFACE 0 WAS PROBED. IF *
* THIS IS NOT THE CASE, FOR EXAMPLE WHEN TWO EASYCAPs ARE PLUGGED IN * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
* SIMULTANEOUSLY, THERE WILL BE SERIOUS TROUBLE. * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if ((0 > dongle_this) || (DONGLE_MANY <= dongle_this)) { for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
SAY("ERROR: bad dongle count\n"); if (pusb_device == easycapdc60_dongle[ndong].peasycap->\
return -EFAULT; pusb_device) {
peasycap = easycapdc60_dongle[ndong].peasycap;
JOT(8, "intf[%i]: easycapdc60_dongle[%i].peasycap-->" \
"peasycap\n", bInterfaceNumber, ndong);
break;
} }
peasycap = easycap_dongle[dongle_this].peasycap; }
JOT(8, "intf[%i]: easycap_dongle[%i].peasycap-->peasycap\n", \ if (DONGLE_MANY <= ndong) {
bInterfaceNumber, dongle_this); SAY("ERROR: peasycap is unknown when probing interface %i\n", \
bInterfaceNumber);
if ((struct easycap *)NULL == peasycap) { return -ENODEV;
}
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL when probing interface %i\n", \ SAY("ERROR: peasycap is NULL when probing interface %i\n", \
bInterfaceNumber); bInterfaceNumber);
return -EFAULT; return -ENODEV;
} }
#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
#
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#else
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
/*---------------------------------------------------------------------------*/
/*
* SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
* BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
* REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
* TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
*/
/*---------------------------------------------------------------------------*/
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
pv4l2_device = usb_get_intfdata(pusb_interface);
if ((struct v4l2_device *)NULL == pv4l2_device) {
SAY("ERROR: pv4l2_device is NULL\n");
return -ENODEV;
}
peasycap = (struct easycap *) \
container_of(pv4l2_device, struct easycap, v4l2_device);
}
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if ((USB_CLASS_VIDEO == bInterfaceClass) || \ if ((USB_CLASS_VIDEO == bInterfaceClass) || \
...@@ -4368,6 +4373,7 @@ case 0: { ...@@ -4368,6 +4373,7 @@ case 0: {
} else { } else {
(peasycap->registered_video)++; (peasycap->registered_video)++;
SAM("easycap attached to minor #%d\n", pusb_interface->minor); SAM("easycap attached to minor #%d\n", pusb_interface->minor);
peasycap->minor = pusb_interface->minor;
break; break;
} }
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
...@@ -4414,9 +4420,11 @@ case 0: { ...@@ -4414,9 +4420,11 @@ case 0: {
(peasycap->registered_video)++; (peasycap->registered_video)++;
SAM("registered with videodev: %i=minor\n", \ SAM("registered with videodev: %i=minor\n", \
peasycap->video_device.minor); peasycap->video_device.minor);
peasycap->minor = peasycap->video_device.minor;
} }
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
break; break;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
...@@ -4426,8 +4434,11 @@ case 0: { ...@@ -4426,8 +4434,11 @@ case 0: {
*/ */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
case 1: { case 1: {
#if defined(EASYCAP_SILENT)
return -ENOENT;
#endif /*EASYCAP_SILENT*/
if (!peasycap) { if (!peasycap) {
SAM("ERROR: peasycap is NULL\n"); SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT; return -EFAULT;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
...@@ -4442,6 +4453,9 @@ case 1: { ...@@ -4442,6 +4453,9 @@ case 1: {
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
case 2: { case 2: {
#if defined(EASYCAP_SILENT)
return -ENOENT;
#endif /*EASYCAP_SILENT*/
if (!peasycap) { if (!peasycap) {
SAM("MISTAKE: peasycap is NULL\n"); SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT; return -EFAULT;
...@@ -4467,14 +4481,14 @@ case 2: { ...@@ -4467,14 +4481,14 @@ case 2: {
} }
if (9 == peasycap->audio_isoc_maxframesize) { if (9 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk |= 0x02; peasycap->ilk |= 0x02;
SAM("hardware is FOUR-CVBS\n"); SAM("audio hardware is microphone\n");
peasycap->microphone = true; peasycap->microphone = true;
peasycap->audio_pages_per_fragment = 4; peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
} else if (256 == peasycap->audio_isoc_maxframesize) { } else if (256 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk &= ~0x02; peasycap->ilk &= ~0x02;
SAM("hardware is CVBS+S-VIDEO\n"); SAM("audio hardware is AC'97\n");
peasycap->microphone = false; peasycap->microphone = false;
peasycap->audio_pages_per_fragment = 4; peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
} else { } else {
SAM("hardware is unidentified:\n"); SAM("hardware is unidentified:\n");
SAM("%i=audio_isoc_maxframesize\n", \ SAM("%i=audio_isoc_maxframesize\n", \
...@@ -4496,7 +4510,7 @@ case 2: { ...@@ -4496,7 +4510,7 @@ case 2: {
JOM(4, "%6i=audio_buffer_page_many\n", \ JOM(4, "%6i=audio_buffer_page_many\n", \
peasycap->audio_buffer_page_many); peasycap->audio_buffer_page_many);
peasycap->audio_isoc_framesperdesc = 128; peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
JOM(4, "%i=audio_isoc_framesperdesc\n", \ JOM(4, "%i=audio_isoc_framesperdesc\n", \
peasycap->audio_isoc_framesperdesc); peasycap->audio_isoc_framesperdesc);
...@@ -4548,6 +4562,7 @@ case 2: { ...@@ -4548,6 +4562,7 @@ case 2: {
INIT_LIST_HEAD(&(peasycap->urb_audio_head)); INIT_LIST_HEAD(&(peasycap->urb_audio_head));
peasycap->purb_audio_head = &(peasycap->urb_audio_head); peasycap->purb_audio_head = &(peasycap->urb_audio_head);
#if !defined(EASYCAP_NEEDS_ALSA)
JOM(4, "allocating an audio buffer\n"); JOM(4, "allocating an audio buffer\n");
JOM(4, ".... scattered over %i pages\n", \ JOM(4, ".... scattered over %i pages\n", \
peasycap->audio_buffer_page_many); peasycap->audio_buffer_page_many);
...@@ -4572,6 +4587,7 @@ case 2: { ...@@ -4572,6 +4587,7 @@ case 2: {
peasycap->audio_fill = 0; peasycap->audio_fill = 0;
peasycap->audio_read = 0; peasycap->audio_read = 0;
JOM(4, "allocation of audio buffer done: %i pages\n", k); JOM(4, "allocation of audio buffer done: %i pages\n", k);
#endif /*!EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
JOM(4, "allocating %i isoc audio buffers of size %i\n", \ JOM(4, "allocating %i isoc audio buffers of size %i\n", \
AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size); AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
...@@ -4646,7 +4662,11 @@ case 2: { ...@@ -4646,7 +4662,11 @@ case 2: {
"peasycap->audio_isoc_buffer[.].pgo;\n"); "peasycap->audio_isoc_buffer[.].pgo;\n");
JOM(4, " purb->transfer_buffer_length = %i;\n", \ JOM(4, " purb->transfer_buffer_length = %i;\n", \
peasycap->audio_isoc_buffer_size); peasycap->audio_isoc_buffer_size);
JOM(4, " purb->complete = easysnd_complete;\n"); #if defined(EASYCAP_NEEDS_ALSA)
JOM(4, " purb->complete = easycap_alsa_complete;\n");
#else
JOM(4, " purb->complete = easyoss_complete;\n");
#endif /*EASYCAP_NEEDS_ALSA*/
JOM(4, " purb->context = peasycap;\n"); JOM(4, " purb->context = peasycap;\n");
JOM(4, " purb->start_frame = 0;\n"); JOM(4, " purb->start_frame = 0;\n");
JOM(4, " purb->number_of_packets = %i;\n", \ JOM(4, " purb->number_of_packets = %i;\n", \
...@@ -4669,7 +4689,11 @@ case 2: { ...@@ -4669,7 +4689,11 @@ case 2: {
purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo; purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
purb->transfer_buffer_length = \ purb->transfer_buffer_length = \
peasycap->audio_isoc_buffer_size; peasycap->audio_isoc_buffer_size;
purb->complete = easysnd_complete; #if defined(EASYCAP_NEEDS_ALSA)
purb->complete = easycap_alsa_complete;
#else
purb->complete = easyoss_complete;
#endif /*EASYCAP_NEEDS_ALSA*/
purb->context = peasycap; purb->context = peasycap;
purb->start_frame = 0; purb->start_frame = 0;
purb->number_of_packets = peasycap->audio_isoc_framesperdesc; purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
...@@ -4692,9 +4716,24 @@ case 2: { ...@@ -4692,9 +4716,24 @@ case 2: {
* THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
rc = usb_register_dev(pusb_interface, &easysnd_class); #if defined(EASYCAP_NEEDS_ALSA)
JOM(4, "initializing ALSA card\n");
rc = easycap_alsa_probe(peasycap);
if (0 != rc) {
err("easycap_alsa_probe() returned %i\n", rc);
return -ENODEV;
} else {
JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",\
(int)peasycap->kref.refcount.counter);
kref_get(&peasycap->kref);
(peasycap->registered_audio)++;
}
#else /*EASYCAP_NEEDS_ALSA*/
rc = usb_register_dev(pusb_interface, &easyoss_class);
if (0 != rc) { if (0 != rc) {
err("Not able to get a minor for this device."); SAY("ERROR: usb_register_dev() failed\n");
usb_set_intfdata(pusb_interface, NULL); usb_set_intfdata(pusb_interface, NULL);
return -ENODEV; return -ENODEV;
} else { } else {
...@@ -4708,7 +4747,9 @@ case 2: { ...@@ -4708,7 +4747,9 @@ case 2: {
* LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO. * LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
SAM("easysnd attached to minor #%d\n", pusb_interface->minor); SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
#endif /*EASYCAP_NEEDS_ALSA*/
break; break;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -4721,7 +4762,7 @@ default: { ...@@ -4721,7 +4762,7 @@ default: {
return -EINVAL; return -EINVAL;
} }
} }
JOM(4, "ends successfully for interface %i\n", \ SAM("ends successfully for interface %i\n", \
pusb_interface_descriptor->bInterfaceNumber); pusb_interface_descriptor->bInterfaceNumber);
return 0; return 0;
} }
...@@ -4730,6 +4771,8 @@ return 0; ...@@ -4730,6 +4771,8 @@ return 0;
/* /*
* WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
* UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID. * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
*
* THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
...@@ -4881,14 +4924,15 @@ switch (bInterfaceNumber) { ...@@ -4881,14 +4924,15 @@ switch (bInterfaceNumber) {
case 0: { case 0: {
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
wake_up_interruptible(&peasycap->wq_video); wake_up_interruptible(&peasycap->wq_video);
JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd); JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", \
if (mutex_lock_interruptible(&easycap_dongle[kd].\ kd);
if (mutex_lock_interruptible(&easycapdc60_dongle[kd].\
mutex_video)) { mutex_video)) {
SAY("ERROR: cannot lock easycap_dongle[%i]." \ SAY("ERROR: cannot lock easycapdc60_dongle[%i]." \
"mutex_video\n", kd); "mutex_video\n", kd);
return; return;
} }
JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
} else } else
SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd); SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
...@@ -4907,7 +4951,7 @@ case 0: { ...@@ -4907,7 +4951,7 @@ case 0: {
if (!peasycap->v4l2_device.name[0]) { if (!peasycap->v4l2_device.name[0]) {
SAM("ERROR: peasycap->v4l2_device.name is empty\n"); SAM("ERROR: peasycap->v4l2_device.name is empty\n");
if (0 <= kd && DONGLE_MANY > kd) if (0 <= kd && DONGLE_MANY > kd)
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return; return;
} }
v4l2_device_disconnect(&peasycap->v4l2_device); v4l2_device_disconnect(&peasycap->v4l2_device);
...@@ -4924,34 +4968,47 @@ case 0: { ...@@ -4924,34 +4968,47 @@ case 0: {
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
} }
break; break;
} }
case 2: { case 2: {
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
wake_up_interruptible(&peasycap->wq_audio); wake_up_interruptible(&peasycap->wq_audio);
JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", \
if (mutex_lock_interruptible(&easycap_dongle[kd].\ kd);
if (mutex_lock_interruptible(&easycapdc60_dongle[kd].\
mutex_audio)) { mutex_audio)) {
SAY("ERROR: cannot lock easycap_dongle[%i]." \ SAY("ERROR: cannot lock easycapdc60_dongle[%i]." \
"mutex_audio\n", kd); "mutex_audio\n", kd);
return; return;
} }
JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
} else } else
SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd); SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
#if defined(EASYCAP_NEEDS_ALSA)
usb_deregister_dev(pusb_interface, &easysnd_class);
if (0 != snd_card_free(peasycap->psnd_card)) {
SAY("ERROR: snd_card_free() failed\n");
} else {
peasycap->psnd_card = (struct snd_card *)NULL;
(peasycap->registered_audio)--; (peasycap->registered_audio)--;
}
#else /*EASYCAP_NEEDS_ALSA*/
usb_deregister_dev(pusb_interface, &easyoss_class);
(peasycap->registered_audio)--;
JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
SAM("easysnd detached from minor #%d\n", minor); SAM("easyoss detached from minor #%d\n", minor);
#endif /*EASYCAP_NEEDS_ALSA*/
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
JOM(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
} }
break; break;
} }
...@@ -4961,6 +5018,7 @@ case 2: { ...@@ -4961,6 +5018,7 @@ case 2: {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
* (ALSO WHEN ALSA HAS BEEN IN USE)
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
if (!peasycap->kref.refcount.counter) { if (!peasycap->kref.refcount.counter) {
...@@ -4970,32 +5028,34 @@ if (!peasycap->kref.refcount.counter) { ...@@ -4970,32 +5028,34 @@ if (!peasycap->kref.refcount.counter) {
return; return;
} }
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd); JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", kd);
if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd); SAY("ERROR: cannot down "
"easycapdc60_dongle[%i].mutex_video\n", kd);
SAM("ending unsuccessfully: may cause memory leak\n"); SAM("ending unsuccessfully: may cause memory leak\n");
return; return;
} }
JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", kd);
if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) { if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
SAY("ERROR: cannot down easycap_dongle[%i].mutex_audio\n", kd); SAY("ERROR: cannot down "
mutex_unlock(&(easycap_dongle[kd].mutex_video)); "easycapdc60_dongle[%i].mutex_audio\n", kd);
JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
SAM("ending unsuccessfully: may cause memory leak\n"); SAM("ending unsuccessfully: may cause memory leak\n");
return; return;
} }
JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
} }
JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", \ JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", \
bInterfaceNumber, (int)peasycap->kref.refcount.counter); bInterfaceNumber, (int)peasycap->kref.refcount.counter);
kref_put(&peasycap->kref, easycap_delete); kref_put(&peasycap->kref, easycap_delete);
JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber); JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
mutex_unlock(&(easycap_dongle[kd].mutex_audio)); mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
JOT(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd); JOT(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
mutex_unlock(&easycap_dongle[kd].mutex_video); mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
JOT(4, "unlocked easycap_dongle[%i].mutex_video\n", kd); JOT(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
JOM(4, "ends\n"); JOM(4, "ends\n");
...@@ -5005,25 +5065,31 @@ return; ...@@ -5005,25 +5065,31 @@ return;
int __init int __init
easycap_module_init(void) easycap_module_init(void)
{ {
int result; int k, rc;
SAY("========easycap=======\n"); SAY("========easycap=======\n");
JOT(4, "begins. %i=debug %i=bars %i=gain\n", easycap_debug, easycap_bars, \ JOT(4, "begins. %i=debug %i=bars %i=gain\n", easycap_debug, easycap_bars, \
easycap_gain); easycap_gain);
SAY("version: " EASYCAP_DRIVER_VERSION "\n"); SAY("version: " EASYCAP_DRIVER_VERSION "\n");
mutex_init(&mutex_dongle);
for (k = 0; k < DONGLE_MANY; k++) {
easycapdc60_dongle[k].peasycap = (struct easycap *)NULL;
mutex_init(&easycapdc60_dongle[k].mutex_video);
mutex_init(&easycapdc60_dongle[k].mutex_audio);
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* REGISTER THIS DRIVER WITH THE USB SUBSYTEM. * REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
JOT(4, "registering driver easycap\n"); JOT(4, "registering driver easycap\n");
rc = usb_register(&easycap_usb_driver);
result = usb_register(&easycap_usb_driver); if (0 != rc)
if (0 != result) SAY("ERROR: usb_register returned %i\n", rc);
SAY("ERROR: usb_register returned %i\n", result);
JOT(4, "ends\n"); JOT(4, "ends\n");
return result; return rc;
} }
/*****************************************************************************/ /*****************************************************************************/
void __exit void __exit
......
/*****************************************************************************
* *
* easycap_main.h *
* *
*****************************************************************************/
/*
*
* 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
*
*/
/*****************************************************************************/
#if !defined(EASYCAP_MAIN_H)
#define EASYCAP_MAIN_H
extern struct easycap_standard easycap_standard[];
extern struct easycap_format easycap_format[];
extern struct v4l2_queryctrl easycap_control[];
extern struct usb_driver easycap_usb_driver;
#if defined(EASYCAP_NEEDS_ALSA)
extern struct snd_pcm_ops easycap_alsa_ops;
extern struct snd_pcm_hardware easycap_pcm_hardware;
extern struct snd_card *psnd_card;
#else
extern struct usb_class_driver easyoss_class;
extern const struct file_operations easyoss_fops;
#endif /*EASYCAP_NEEDS_ALSA*/
#endif /*EASYCAP_MAIN_H*/
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/*****************************************************************************/ /*****************************************************************************/
#include "easycap.h" #include "easycap.h"
#include "easycap_debug.h" #include "easycap_settings.h"
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
......
/***************************************************************************** /*****************************************************************************
* * * *
* easycap_standard.h * * easycap_settings.h *
* * * *
*****************************************************************************/ *****************************************************************************/
/* /*
...@@ -24,4 +24,11 @@ ...@@ -24,4 +24,11 @@
* *
*/ */
/*****************************************************************************/ /*****************************************************************************/
extern struct easycap_standard easycap_standard[]; #if !defined(EASYCAP_SETTINGS_H)
#define EASYCAP_SETTINGS_H
extern int easycap_debug;
extern int easycap_gain;
extern struct easycap_dongle easycapdc60_dongle[];
#endif /*EASYCAP_SETTINGS_H*/
...@@ -29,9 +29,890 @@ ...@@ -29,9 +29,890 @@
/*****************************************************************************/ /*****************************************************************************/
#include "easycap.h" #include "easycap.h"
#include "easycap_debug.h"
#include "easycap_sound.h" #include "easycap_sound.h"
#if defined(EASYCAP_NEEDS_ALSA)
/*--------------------------------------------------------------------------*/
/*
* PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
*/
/*--------------------------------------------------------------------------*/
static const struct snd_pcm_hardware alsa_hardware = {
.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
.rate_min = 32000,
.rate_max = 48000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * \
AUDIO_FRAGMENT_MANY,
.period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
.period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
.periods_min = AUDIO_FRAGMENT_MANY,
.periods_max = AUDIO_FRAGMENT_MANY * 2,
};
static struct snd_pcm_ops easycap_alsa_pcm_ops = {
.open = easycap_alsa_open,
.close = easycap_alsa_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = easycap_alsa_hw_params,
.hw_free = easycap_alsa_hw_free,
.prepare = easycap_alsa_prepare,
.ack = easycap_alsa_ack,
.trigger = easycap_alsa_trigger,
.pointer = easycap_alsa_pointer,
.page = easycap_alsa_page,
};
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS
* MEANS MODULE easycap. BEWARE.
*/
/*---------------------------------------------------------------------------*/
int
easycap_alsa_probe(struct easycap *peasycap)
{
int rc;
struct snd_card *psnd_card;
struct snd_pcm *psnd_pcm;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return -ENODEV;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
if (0 > peasycap->minor) {
SAY("ERROR: no minor\n");
return -ENODEV;
}
peasycap->alsa_hardware = alsa_hardware;
if (true == peasycap->microphone) {
peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
peasycap->alsa_hardware.rate_min = 32000;
peasycap->alsa_hardware.rate_max = 32000;
} else {
peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
peasycap->alsa_hardware.rate_min = 48000;
peasycap->alsa_hardware.rate_max = 48000;
}
#if defined(EASYCAP_NEEDS_CARD_CREATE)
if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa", \
THIS_MODULE, 0, \
&psnd_card)) {
SAY("ERROR: Cannot do ALSA snd_card_create()\n");
return -EFAULT;
}
#else
psnd_card = snd_card_new(SNDRV_DEFAULT_IDX1, "easycap_alsa", \
THIS_MODULE, 0);
if (NULL == psnd_card) {
SAY("ERROR: Cannot do ALSA snd_card_new()\n");
return -EFAULT;
}
#endif /*EASYCAP_NEEDS_CARD_CREATE*/
sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
strcpy(&psnd_card->shortname[0], "easycap_alsa");
sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
psnd_card->dev = &peasycap->pusb_device->dev;
psnd_card->private_data = peasycap;
peasycap->psnd_card = psnd_card;
rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
if (0 != rc) {
SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
snd_card_free(psnd_card);
return -EFAULT;
}
snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE, \
&easycap_alsa_pcm_ops);
psnd_pcm->info_flags = 0;
strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
psnd_pcm->private_data = peasycap;
peasycap->psnd_pcm = psnd_pcm;
peasycap->psubstream = (struct snd_pcm_substream *)NULL;
rc = snd_card_register(psnd_card);
if (0 != rc) {
SAM("ERROR: Cannot do ALSA snd_card_register()\n");
snd_card_free(psnd_card);
return -EFAULT;
} else {
;
SAM("registered %s\n", &psnd_card->id[0]);
}
return 0;
}
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
* PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
* IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
*/
/*---------------------------------------------------------------------------*/
void
easycap_alsa_complete(struct urb *purb)
{
struct easycap *peasycap;
struct snd_pcm_substream *pss;
struct snd_pcm_runtime *prt;
int dma_bytes, fragment_bytes;
int isfragment;
__u8 *p1, *p2;
__s16 s16;
int i, j, more, much, rc;
#if defined(UPSAMPLE)
int k;
__s16 oldaudio, newaudio, delta;
#endif /*UPSAMPLE*/
JOT(16, "\n");
if (NULL == purb) {
SAY("ERROR: purb is NULL\n");
return;
}
peasycap = purb->context;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return;
}
much = 0;
if (peasycap->audio_idle) {
JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n", \
peasycap->audio_idle, peasycap->audio_isoc_streaming);
if (peasycap->audio_isoc_streaming)
goto resubmit;
}
/*---------------------------------------------------------------------------*/
pss = peasycap->psubstream;
if (NULL == pss)
goto resubmit;
prt = pss->runtime;
if (NULL == prt)
goto resubmit;
dma_bytes = (int)prt->dma_bytes;
if (0 == dma_bytes)
goto resubmit;
fragment_bytes = 4 * ((int)prt->period_size);
if (0 == fragment_bytes)
goto resubmit;
/* -------------------------------------------------------------------------*/
if (purb->status) {
if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
return;
}
SAM("ERROR: non-zero urb status:\n");
switch (purb->status) {
case -EINPROGRESS: {
SAM("-EINPROGRESS\n");
break;
}
case -ENOSR: {
SAM("-ENOSR\n");
break;
}
case -EPIPE: {
SAM("-EPIPE\n");
break;
}
case -EOVERFLOW: {
SAM("-EOVERFLOW\n");
break;
}
case -EPROTO: {
SAM("-EPROTO\n");
break;
}
case -EILSEQ: {
SAM("-EILSEQ\n");
break;
}
case -ETIMEDOUT: {
SAM("-ETIMEDOUT\n");
break;
}
case -EMSGSIZE: {
SAM("-EMSGSIZE\n");
break;
}
case -EOPNOTSUPP: {
SAM("-EOPNOTSUPP\n");
break;
}
case -EPFNOSUPPORT: {
SAM("-EPFNOSUPPORT\n");
break;
}
case -EAFNOSUPPORT: {
SAM("-EAFNOSUPPORT\n");
break;
}
case -EADDRINUSE: {
SAM("-EADDRINUSE\n");
break;
}
case -EADDRNOTAVAIL: {
SAM("-EADDRNOTAVAIL\n");
break;
}
case -ENOBUFS: {
SAM("-ENOBUFS\n");
break;
}
case -EISCONN: {
SAM("-EISCONN\n");
break;
}
case -ENOTCONN: {
SAM("-ENOTCONN\n");
break;
}
case -ESHUTDOWN: {
SAM("-ESHUTDOWN\n");
break;
}
case -ENOENT: {
SAM("-ENOENT\n");
break;
}
case -ECONNRESET: {
SAM("-ECONNRESET\n");
break;
}
case -ENOSPC: {
SAM("ENOSPC\n");
break;
}
default: {
SAM("unknown error: %i\n", purb->status);
break;
}
}
goto resubmit;
}
/*---------------------------------------------------------------------------*/
/*
* PROCEED HERE WHEN NO ERROR
*/
/*---------------------------------------------------------------------------*/
#if defined(UPSAMPLE)
oldaudio = peasycap->oldaudio;
#endif /*UPSAMPLE*/
for (i = 0; i < purb->number_of_packets; i++) {
switch (purb->iso_frame_desc[i].status) {
case 0: {
break;
}
case -ENOENT: {
SAM("-ENOENT\n");
break;
}
case -EINPROGRESS: {
SAM("-EINPROGRESS\n");
break;
}
case -EPROTO: {
SAM("-EPROTO\n");
break;
}
case -EILSEQ: {
SAM("-EILSEQ\n");
break;
}
case -ETIME: {
SAM("-ETIME\n");
break;
}
case -ETIMEDOUT: {
SAM("-ETIMEDOUT\n");
break;
}
case -EPIPE: {
SAM("-EPIPE\n");
break;
}
case -ECOMM: {
SAM("-ECOMM\n");
break;
}
case -ENOSR: {
SAM("-ENOSR\n");
break;
}
case -EOVERFLOW: {
SAM("-EOVERFLOW\n");
break;
}
case -EREMOTEIO: {
SAM("-EREMOTEIO\n");
break;
}
case -ENODEV: {
SAM("-ENODEV\n");
break;
}
case -EXDEV: {
SAM("-EXDEV\n");
break;
}
case -EINVAL: {
SAM("-EINVAL\n");
break;
}
case -ECONNRESET: {
SAM("-ECONNRESET\n");
break;
}
case -ENOSPC: {
SAM("-ENOSPC\n");
break;
}
case -ESHUTDOWN: {
SAM("-ESHUTDOWN\n");
break;
}
case -EPERM: {
SAM("-EPERM\n");
break;
}
default: {
SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
break;
}
}
if (!purb->iso_frame_desc[i].status) {
more = purb->iso_frame_desc[i].actual_length;
if (!more)
peasycap->audio_mt++;
else {
if (peasycap->audio_mt) {
JOM(12, "%4i empty audio urb frames\n", \
peasycap->audio_mt);
peasycap->audio_mt = 0;
}
p1 = (__u8 *)(purb->transfer_buffer + \
purb->iso_frame_desc[i].offset);
/*---------------------------------------------------------------------------*/
/*
* COPY more BYTES FROM ISOC BUFFER TO THE DMA BUFFER,
* CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
*/
/*---------------------------------------------------------------------------*/
while (more) {
if (0 > more) {
SAM("MISTAKE: more is negative\n");
return;
}
much = dma_bytes - peasycap->dma_fill;
if (0 > much) {
SAM("MISTAKE: much is negative\n");
return;
}
if (0 == much) {
peasycap->dma_fill = 0;
peasycap->dma_next = fragment_bytes;
JOM(8, "wrapped dma buffer\n");
}
if (false == peasycap->microphone) {
if (much > more)
much = more;
memcpy(prt->dma_area + \
peasycap->dma_fill, \
p1, much);
p1 += much;
more -= much;
} else {
#if defined(UPSAMPLE)
if (much % 16)
JOM(8, "MISTAKE? much" \
" is not divisible by 16\n");
if (much > (16 * \
more))
much = 16 * \
more;
p2 = (__u8 *)(prt->dma_area + \
peasycap->dma_fill);
for (j = 0; j < (much/16); j++) {
newaudio = ((int) *p1) - 128;
newaudio = 128 * \
newaudio;
delta = (newaudio - oldaudio) \
/ 4;
s16 = oldaudio + delta;
for (k = 0; k < 4; k++) {
*p2 = (0x00FF & s16);
*(p2 + 1) = (0xFF00 & \
s16) >> 8;
p2 += 2;
*p2 = (0x00FF & s16);
*(p2 + 1) = (0xFF00 & \
s16) >> 8;
p2 += 2;
s16 += delta;
}
p1++;
more--;
oldaudio = s16;
}
#else /*!UPSAMPLE*/
if (much > (2 * more))
much = 2 * more;
p2 = (__u8 *)(prt->dma_area + \
peasycap->dma_fill);
for (j = 0; j < (much / 2); j++) {
s16 = ((int) *p1) - 128;
s16 = 128 * \
s16;
*p2 = (0x00FF & s16);
*(p2 + 1) = (0xFF00 & s16) >> \
8;
p1++; p2 += 2;
more--;
}
#endif /*UPSAMPLE*/
}
peasycap->dma_fill += much;
if (peasycap->dma_fill >= peasycap->dma_next) {
isfragment = peasycap->dma_fill / \
fragment_bytes;
if (0 > isfragment) {
SAM("MISTAKE: isfragment is " \
"negative\n");
return;
}
peasycap->dma_read = (isfragment \
- 1) * fragment_bytes;
peasycap->dma_next = (isfragment \
+ 1) * fragment_bytes;
if (dma_bytes < peasycap->dma_next) {
peasycap->dma_next = \
fragment_bytes;
}
if (0 <= peasycap->dma_read) {
JOM(8, "snd_pcm_period_elap" \
"sed(), %i=" \
"isfragment\n", \
isfragment);
snd_pcm_period_elapsed(pss);
}
}
}
}
} else {
JOM(12, "discarding audio samples because " \
"%i=purb->iso_frame_desc[i].status\n", \
purb->iso_frame_desc[i].status);
}
#if defined(UPSAMPLE)
peasycap->oldaudio = oldaudio;
#endif /*UPSAMPLE*/
}
/*---------------------------------------------------------------------------*/
/*
* RESUBMIT THIS URB
*/
/*---------------------------------------------------------------------------*/
resubmit:
if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) {
if ((-ENODEV != rc) && (-ENOENT != rc)) {
SAM("ERROR: while %i=audio_idle, " \
"usb_submit_urb() failed " \
"with rc:\n", peasycap->audio_idle);
}
switch (rc) {
case -ENODEV:
case -ENOENT:
break;
case -ENOMEM: {
SAM("-ENOMEM\n");
break;
}
case -ENXIO: {
SAM("-ENXIO\n");
break;
}
case -EINVAL: {
SAM("-EINVAL\n");
break;
}
case -EAGAIN: {
SAM("-EAGAIN\n");
break;
}
case -EFBIG: {
SAM("-EFBIG\n");
break;
}
case -EPIPE: {
SAM("-EPIPE\n");
break;
}
case -EMSGSIZE: {
SAM("-EMSGSIZE\n");
break;
}
case -ENOSPC: {
SAM("-ENOSPC\n");
break;
}
case -EPERM: {
SAM("-EPERM\n");
break;
}
default: {
SAM("unknown error: %i\n", rc);
break;
}
}
if (0 < peasycap->audio_isoc_streaming)
(peasycap->audio_isoc_streaming)--;
}
}
return;
}
/*****************************************************************************/
int
easycap_alsa_open(struct snd_pcm_substream *pss)
{
struct snd_pcm *psnd_pcm;
struct snd_card *psnd_card;
struct easycap *peasycap;
JOT(4, "\n");
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
psnd_pcm = pss->pcm;
if (NULL == psnd_pcm) {
SAY("ERROR: psnd_pcm is NULL\n");
return -EFAULT;
}
psnd_card = psnd_pcm->card;
if (NULL == psnd_card) {
SAY("ERROR: psnd_card is NULL\n");
return -EFAULT;
}
peasycap = psnd_card->private_data;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return -EFAULT;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
if (peasycap->psnd_card != psnd_card) {
SAM("ERROR: bad peasycap->psnd_card\n");
return -EFAULT;
}
if (NULL != peasycap->psubstream) {
SAM("ERROR: bad peasycap->psubstream\n");
return -EFAULT;
}
pss->private_data = peasycap;
peasycap->psubstream = pss;
pss->runtime->hw = peasycap->alsa_hardware;
pss->runtime->private_data = peasycap;
pss->private_data = peasycap;
if (0 != easycap_sound_setup(peasycap)) {
JOM(4, "ending unsuccessfully\n");
return -EFAULT;
}
JOM(4, "ending successfully\n");
return 0;
}
/*****************************************************************************/
int
easycap_alsa_close(struct snd_pcm_substream *pss)
{
struct easycap *peasycap;
JOT(4, "\n");
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
peasycap = snd_pcm_substream_chip(pss);
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return -EFAULT;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
pss->private_data = NULL;
peasycap->psubstream = (struct snd_pcm_substream *)NULL;
JOT(4, "ending successfully\n");
return 0;
}
/*****************************************************************************/
int
easycap_alsa_hw_params(struct snd_pcm_substream *pss, \
struct snd_pcm_hw_params *phw)
{
int rc;
JOT(4, "%i\n", (params_buffer_bytes(phw)));
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
if (0 != rc)
return rc;
return 0;
}
/*****************************************************************************/
int
easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
{
struct snd_pcm_runtime *prt;
JOT(4, "\n");
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
prt = pss->runtime;
if (NULL == prt) {
SAY("ERROR: substream.runtime is NULL\n");
return -EFAULT;
}
if (prt->dma_area) {
if (prt->dma_bytes > sz)
return 0;
vfree(prt->dma_area);
}
prt->dma_area = vmalloc(sz);
if (NULL == prt->dma_area)
return -ENOMEM;
prt->dma_bytes = sz;
return 0;
}
/*****************************************************************************/
int
easycap_alsa_hw_free(struct snd_pcm_substream *pss)
{
struct snd_pcm_runtime *prt;
JOT(4, "\n");
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
prt = pss->runtime;
if (NULL == prt) {
SAY("ERROR: substream.runtime is NULL\n");
return -EFAULT;
}
if (NULL != prt->dma_area) {
JOT(8, "0x%08lX=prt->dma_area\n", (unsigned long int)prt->dma_area);
vfree(prt->dma_area);
prt->dma_area = NULL;
} else
JOT(8, "dma_area already freed\n");
return 0;
}
/*****************************************************************************/
int
easycap_alsa_prepare(struct snd_pcm_substream *pss)
{
struct easycap *peasycap;
struct snd_pcm_runtime *prt;
JOT(4, "\n");
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
prt = pss->runtime;
peasycap = snd_pcm_substream_chip(pss);
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return -EFAULT;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
JOM(16, "ALSA decides %8i Hz=rate\n", (int)pss->runtime->rate);
JOM(16, "ALSA decides %8i =period_size\n", (int)pss->runtime->period_size);
JOM(16, "ALSA decides %8i =periods\n", (int)pss->runtime->periods);
JOM(16, "ALSA decides %8i =buffer_size\n", (int)pss->runtime->buffer_size);
JOM(16, "ALSA decides %8i =dma_bytes\n", (int)pss->runtime->dma_bytes);
JOM(16, "ALSA decides %8i =boundary\n", (int)pss->runtime->boundary);
JOM(16, "ALSA decides %8i =period_step\n", (int)pss->runtime->period_step);
JOM(16, "ALSA decides %8i =sample_bits\n", (int)pss->runtime->sample_bits);
JOM(16, "ALSA decides %8i =frame_bits\n", (int)pss->runtime->frame_bits);
JOM(16, "ALSA decides %8i =min_align\n", (int)pss->runtime->min_align);
JOM(12, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
JOM(12, "ALSA decides %8i =hw_ptr_interrupt\n", \
(int)pss->runtime->hw_ptr_interrupt);
if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
SAY("MISTAKE: unexpected ALSA parameters\n");
return -ENOENT;
}
return 0;
}
/*****************************************************************************/
int
easycap_alsa_ack(struct snd_pcm_substream *pss)
{
return 0;
}
/*****************************************************************************/
int
easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
{
struct easycap *peasycap;
int retval;
JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START, \
SNDRV_PCM_TRIGGER_STOP);
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
peasycap = snd_pcm_substream_chip(pss);
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return -EFAULT;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
switch (cmd) {
case SNDRV_PCM_TRIGGER_START: {
peasycap->audio_idle = 0;
break;
}
case SNDRV_PCM_TRIGGER_STOP: {
peasycap->audio_idle = 1;
break;
}
default:
retval = -EINVAL;
}
return 0;
}
/*****************************************************************************/
snd_pcm_uframes_t
easycap_alsa_pointer(struct snd_pcm_substream *pss)
{
struct easycap *peasycap;
snd_pcm_uframes_t offset;
JOT(16, "\n");
if (NULL == pss) {
SAY("ERROR: pss is NULL\n");
return -EFAULT;
}
peasycap = snd_pcm_substream_chip(pss);
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return -EFAULT;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return -EFAULT;
}
if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
JOM(8, "returning -EIO because " \
"%i=audio_idle %i=audio_eof\n", \
peasycap->audio_idle, peasycap->audio_eof);
return -EIO;
}
/*---------------------------------------------------------------------------*/
if (0 > peasycap->dma_read) {
JOM(8, "returning -EBUSY\n");
return -EBUSY;
}
offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
JOM(8, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
JOM(8, "ALSA decides %8i =hw_ptr_interrupt\n", \
(int)pss->runtime->hw_ptr_interrupt);
JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n", \
(int)offset, peasycap->dma_read, peasycap->dma_next);
return offset;
}
/*****************************************************************************/
struct page *
easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
{
return vmalloc_to_page(pss->runtime->dma_area + offset);
}
/*****************************************************************************/
#else /*!EASYCAP_NEEDS_ALSA*/
/*****************************************************************************/
/**************************** **************************/
/**************************** Open Sound System **************************/
/**************************** **************************/
/*****************************************************************************/
/*--------------------------------------------------------------------------*/
/*
* PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
*/
/*--------------------------------------------------------------------------*/
const struct file_operations easyoss_fops = {
.owner = THIS_MODULE,
.open = easyoss_open,
.release = easyoss_release,
#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
.unlocked_ioctl = easyoss_ioctl_noinode,
#else
.ioctl = easyoss_ioctl,
#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
.read = easyoss_read,
.llseek = no_llseek,
};
struct usb_class_driver easyoss_class = {
.name = "usb/easyoss%d",
.fops = &easyoss_fops,
.minor_base = USB_SKEL_MINOR_BASE,
};
/*****************************************************************************/ /*****************************************************************************/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -41,7 +922,7 @@ ...@@ -41,7 +922,7 @@
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
easysnd_complete(struct urb *purb) easyoss_complete(struct urb *purb)
{ {
struct easycap *peasycap; struct easycap *peasycap;
struct data_buffer *paudio_buffer; struct data_buffer *paudio_buffer;
...@@ -68,27 +949,26 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { ...@@ -68,27 +949,26 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n"); SAY("ERROR: bad peasycap\n");
return; return;
} }
much = 0; much = 0;
if (peasycap->audio_idle) { if (peasycap->audio_idle) {
JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n", \ JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n", \
peasycap->audio_idle, peasycap->audio_isoc_streaming); peasycap->audio_idle, peasycap->audio_isoc_streaming);
if (peasycap->audio_isoc_streaming) { if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC); rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) { if (0 != rc) {
if (-ENODEV != rc) if (-ENODEV != rc && -ENOENT != rc) {
SAM("ERROR: while %i=audio_idle, " \ SAM("ERROR: while %i=audio_idle, " \
"usb_submit_urb() failed with rc:\n", \ "usb_submit_urb() failed with rc:\n", \
peasycap->audio_idle); peasycap->audio_idle);
}
switch (rc) { switch (rc) {
case -ENODEV:
case -ENOENT:
break;
case -ENOMEM: { case -ENOMEM: {
SAM("-ENOMEM\n"); SAM("-ENOMEM\n");
break; break;
} }
case -ENODEV: {
break;
}
case -ENXIO: { case -ENXIO: {
SAM("-ENXIO\n"); SAM("-ENXIO\n");
break; break;
...@@ -117,8 +997,12 @@ if (peasycap->audio_idle) { ...@@ -117,8 +997,12 @@ if (peasycap->audio_idle) {
SAM("-ENOSPC\n"); SAM("-ENOSPC\n");
break; break;
} }
case -EPERM: {
SAM("-EPERM\n");
break;
}
default: { default: {
SAM("unknown error: 0x%08X\n", rc); SAM("unknown error: %i\n", rc);
break; break;
} }
} }
...@@ -214,63 +1098,16 @@ if (purb->status) { ...@@ -214,63 +1098,16 @@ if (purb->status) {
SAM("ENOSPC\n"); SAM("ENOSPC\n");
break; break;
} }
default: { case -EPERM: {
SAM("unknown error code 0x%08X\n", purb->status); SAM("-EPERM\n");
break;
}
}
/*---------------------------------------------------------------------------*/
/*
* RESUBMIT THIS URB AFTER AN ERROR
*
* (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH)
*/
/*---------------------------------------------------------------------------*/
if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) {
SAM("ERROR: while %i=audio_idle, usb_submit_urb() "
"failed with rc:\n", peasycap->audio_idle);
switch (rc) {
case -ENOMEM: {
SAM("-ENOMEM\n");
break;
}
case -ENODEV: {
SAM("-ENODEV\n");
break;
}
case -ENXIO: {
SAM("-ENXIO\n");
break;
}
case -EINVAL: {
SAM("-EINVAL\n");
break;
}
case -EAGAIN: {
SAM("-EAGAIN\n");
break;
}
case -EFBIG: {
SAM("-EFBIG\n");
break;
}
case -EPIPE: {
SAM("-EPIPE\n");
break;
}
case -EMSGSIZE: {
SAM("-EMSGSIZE\n");
break; break;
} }
default: { default: {
SAM("0x%08X\n", rc); break; SAM("unknown error: %i\n", purb->status);
} break;
}
} }
} }
return; goto resubmit;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
...@@ -286,6 +1123,10 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -286,6 +1123,10 @@ for (i = 0; i < purb->number_of_packets; i++) {
case 0: { case 0: {
break; break;
} }
case -ENODEV: {
SAM("-ENODEV\n");
break;
}
case -ENOENT: { case -ENOENT: {
SAM("-ENOENT\n"); SAM("-ENOENT\n");
break; break;
...@@ -330,10 +1171,6 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -330,10 +1171,6 @@ for (i = 0; i < purb->number_of_packets; i++) {
SAM("-EREMOTEIO\n"); SAM("-EREMOTEIO\n");
break; break;
} }
case -ENODEV: {
SAM("-ENODEV\n");
break;
}
case -EXDEV: { case -EXDEV: {
SAM("-EXDEV\n"); SAM("-EXDEV\n");
break; break;
...@@ -354,8 +1191,12 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -354,8 +1191,12 @@ for (i = 0; i < purb->number_of_packets; i++) {
SAM("-ESHUTDOWN\n"); SAM("-ESHUTDOWN\n");
break; break;
} }
case -EPERM: {
SAM("-EPERM\n");
break;
}
default: { default: {
SAM("unknown error:0x%08X\n", purb->iso_frame_desc[i].status); SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
break; break;
} }
} }
...@@ -371,7 +1212,7 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -371,7 +1212,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
peasycap->audio_mt++; peasycap->audio_mt++;
else { else {
if (peasycap->audio_mt) { if (peasycap->audio_mt) {
JOM(16, "%4i empty audio urb frames\n", \ JOM(12, "%4i empty audio urb frames\n", \
peasycap->audio_mt); peasycap->audio_mt);
peasycap->audio_mt = 0; peasycap->audio_mt = 0;
} }
...@@ -390,8 +1231,7 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -390,8 +1231,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
while (more) { while (more) {
if (0 > more) { if (0 > more) {
SAM("easysnd_complete: MISTAKE: " \ SAM("MISTAKE: more is negative\n");
"more is negative\n");
return; return;
} }
if (peasycap->audio_buffer_page_many <= \ if (peasycap->audio_buffer_page_many <= \
...@@ -412,7 +1252,7 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -412,7 +1252,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
paudio_buffer->pgo)) { paudio_buffer->pgo)) {
#if defined(TESTTONE) #if defined(TESTTONE)
easysnd_testtone(peasycap, \ easyoss_testtone(peasycap, \
peasycap->audio_fill); peasycap->audio_fill);
#endif /*TESTTONE*/ #endif /*TESTTONE*/
...@@ -424,7 +1264,7 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -424,7 +1264,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
peasycap->audio_fill) peasycap->audio_fill)
peasycap->audio_fill = 0; peasycap->audio_fill = 0;
JOM(12, "bumped peasycap->" \ JOM(8, "bumped peasycap->" \
"audio_fill to %i\n", \ "audio_fill to %i\n", \
peasycap->audio_fill); peasycap->audio_fill);
...@@ -497,7 +1337,7 @@ for (i = 0; i < purb->number_of_packets; i++) { ...@@ -497,7 +1337,7 @@ for (i = 0; i < purb->number_of_packets; i++) {
more--; more--;
oldaudio = s16; oldaudio = s16;
} }
#else #else /*!UPSAMPLE*/
if (much > (2 * more)) if (much > (2 * more))
much = 2 * more; much = 2 * more;
p2 = (__u8 *)paudio_buffer->pto; p2 = (__u8 *)paudio_buffer->pto;
...@@ -530,25 +1370,26 @@ peasycap->oldaudio = oldaudio; ...@@ -530,25 +1370,26 @@ peasycap->oldaudio = oldaudio;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* RESUBMIT THIS URB AFTER NO ERROR * RESUBMIT THIS URB
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
resubmit:
if (peasycap->audio_isoc_streaming) { if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC); rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) { if (0 != rc) {
if (-ENODEV != rc) { if (-ENODEV != rc && -ENOENT != rc) {
SAM("ERROR: while %i=audio_idle, " \ SAM("ERROR: while %i=audio_idle, " \
"usb_submit_urb() failed " \ "usb_submit_urb() failed " \
"with rc:\n", peasycap->audio_idle); "with rc:\n", peasycap->audio_idle);
} }
switch (rc) { switch (rc) {
case -ENODEV:
case -ENOENT:
break;
case -ENOMEM: { case -ENOMEM: {
SAM("-ENOMEM\n"); SAM("-ENOMEM\n");
break; break;
} }
case -ENODEV: {
break;
}
case -ENXIO: { case -ENXIO: {
SAM("-ENXIO\n"); SAM("-ENXIO\n");
break; break;
...@@ -577,8 +1418,12 @@ if (peasycap->audio_isoc_streaming) { ...@@ -577,8 +1418,12 @@ if (peasycap->audio_isoc_streaming) {
SAM("-ENOSPC\n"); SAM("-ENOSPC\n");
break; break;
} }
case -EPERM: {
SAM("-EPERM\n");
break;
}
default: { default: {
SAM("unknown error: 0x%08X\n", rc); SAM("unknown error: %i\n", rc);
break; break;
} }
} }
...@@ -590,16 +1435,16 @@ return; ...@@ -590,16 +1435,16 @@ return;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO * THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
* STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT * STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
* HAVE AN IOCTL INTERFACE. * HAVE AN IOCTL INTERFACE.
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
easysnd_open(struct inode *inode, struct file *file) easyoss_open(struct inode *inode, struct file *file)
{ {
struct usb_interface *pusb_interface; struct usb_interface *pusb_interface;
struct easycap *peasycap; struct easycap *peasycap;
int subminor, rc; int subminor;
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
...@@ -660,59 +1505,15 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { ...@@ -660,59 +1505,15 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
file->private_data = peasycap; file->private_data = peasycap;
/*---------------------------------------------------------------------------*/ if (0 != easycap_sound_setup(peasycap)) {
/* ;
* INITIALIZATION ;
*/
/*---------------------------------------------------------------------------*/
JOM(4, "starting initialization\n");
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
return -ENODEV;
}
JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
rc = audio_setup(peasycap);
if (0 <= rc)
JOM(8, "audio_setup() returned %i\n", rc);
else
JOM(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc);
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device has become NULL\n");
return -ENODEV;
}
/*---------------------------------------------------------------------------*/
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device has become NULL\n");
return -ENODEV;
} }
rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
peasycap->audio_altsetting_on);
JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
peasycap->audio_altsetting_on, rc);
rc = wakeup_device(peasycap->pusb_device);
if (0 == rc)
JOM(8, "wakeup_device() returned %i\n", rc);
else
JOM(8, "ERROR: wakeup_device() returned %i\n", rc);
peasycap->audio_eof = 0;
peasycap->audio_idle = 0;
peasycap->timeval1.tv_sec = 0;
peasycap->timeval1.tv_usec = 0;
submit_audio_urbs(peasycap);
JOM(4, "finished initialization\n");
return 0; return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
int int
easysnd_release(struct inode *inode, struct file *file) easyoss_release(struct inode *inode, struct file *file)
{ {
struct easycap *peasycap; struct easycap *peasycap;
...@@ -736,7 +1537,7 @@ return 0; ...@@ -736,7 +1537,7 @@ return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
ssize_t ssize_t
easysnd_read(struct file *file, char __user *puserspacebuffer, \ easyoss_read(struct file *file, char __user *puserspacebuffer, \
size_t kount, loff_t *poff) size_t kount, loff_t *poff)
{ {
struct timeval timeval; struct timeval timeval;
...@@ -760,7 +1561,7 @@ size_t szret; ...@@ -760,7 +1561,7 @@ size_t szret;
*/ */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); JOT(8, "%5i=kount %5i=*poff\n", (int)kount, (int)(*poff));
if (NULL == file) { if (NULL == file) {
SAY("ERROR: file is NULL\n"); SAY("ERROR: file is NULL\n");
...@@ -768,7 +1569,7 @@ if (NULL == file) { ...@@ -768,7 +1569,7 @@ if (NULL == file) {
} }
peasycap = file->private_data; peasycap = file->private_data;
if (NULL == peasycap) { if (NULL == peasycap) {
SAY("ERROR in easysnd_read(): peasycap is NULL\n"); SAY("ERROR in easyoss_read(): peasycap is NULL\n");
return -EFAULT; return -EFAULT;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
...@@ -776,16 +1577,17 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { ...@@ -776,16 +1577,17 @@ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
return -EFAULT; return -EFAULT;
} }
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n"); SAY("ERROR: peasycap->pusb_device is NULL\n");
return -EFAULT; return -EFAULT;
} }
kd = isdongle(peasycap); kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) { if (0 <= kd && DONGLE_MANY > kd) {
if (mutex_lock_interruptible(&(easycap_dongle[kd].mutex_audio))) { if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd); SAY("ERROR: "
"cannot lock easycapdc60_dongle[%i].mutex_audio\n", kd);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
...@@ -797,24 +1599,24 @@ if (0 <= kd && DONGLE_MANY > kd) { ...@@ -797,24 +1599,24 @@ if (0 <= kd && DONGLE_MANY > kd) {
return -ERESTARTSYS; return -ERESTARTSYS;
if (NULL == file) { if (NULL == file) {
SAY("ERROR: file is NULL\n"); SAY("ERROR: file is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
peasycap = file->private_data; peasycap = file->private_data;
if (NULL == peasycap) { if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n"); SAY("ERROR: peasycap is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap: 0x%08lX\n", \ SAY("ERROR: bad peasycap: 0x%08lX\n", \
(unsigned long int) peasycap); (unsigned long int) peasycap);
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (NULL == peasycap->pusb_device) { if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n"); SAM("ERROR: peasycap->pusb_device is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
} else { } else {
...@@ -835,13 +1637,13 @@ else ...@@ -835,13 +1637,13 @@ else
if ((0 > peasycap->audio_read) || \ if ((0 > peasycap->audio_read) || \
(peasycap->audio_buffer_page_many <= peasycap->audio_read)) { (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
SAM("ERROR: peasycap->audio_read out of range\n"); SAM("ERROR: peasycap->audio_read out of range\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
if ((struct data_buffer *)NULL == pdata_buffer) { if ((struct data_buffer *)NULL == pdata_buffer) {
SAM("ERROR: pdata_buffer is NULL\n"); SAM("ERROR: pdata_buffer is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
JOM(12, "before wait, %i=frag read %i=frag fill\n", \ JOM(12, "before wait, %i=frag read %i=frag fill\n", \
...@@ -853,7 +1655,7 @@ while ((fragment == (peasycap->audio_fill / \ ...@@ -853,7 +1655,7 @@ while ((fragment == (peasycap->audio_fill / \
(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) { (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
if (file->f_flags & O_NONBLOCK) { if (file->f_flags & O_NONBLOCK) {
JOM(16, "returning -EAGAIN as instructed\n"); JOM(16, "returning -EAGAIN as instructed\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EAGAIN; return -EAGAIN;
} }
rc = wait_event_interruptible(peasycap->wq_audio, \ rc = wait_event_interruptible(peasycap->wq_audio, \
...@@ -863,25 +1665,25 @@ while ((fragment == (peasycap->audio_fill / \ ...@@ -863,25 +1665,25 @@ while ((fragment == (peasycap->audio_fill / \
(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))))); (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
if (0 != rc) { if (0 != rc) {
SAM("aborted by signal\n"); SAM("aborted by signal\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (peasycap->audio_eof) { if (peasycap->audio_eof) {
JOM(8, "returning 0 because %i=audio_eof\n", \ JOM(8, "returning 0 because %i=audio_eof\n", \
peasycap->audio_eof); peasycap->audio_eof);
kill_audio_urbs(peasycap); kill_audio_urbs(peasycap);
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0; return 0;
} }
if (peasycap->audio_idle) { if (peasycap->audio_idle) {
JOM(16, "returning 0 because %i=audio_idle\n", \ JOM(16, "returning 0 because %i=audio_idle\n", \
peasycap->audio_idle); peasycap->audio_idle);
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0; return 0;
} }
if (!peasycap->audio_isoc_streaming) { if (!peasycap->audio_isoc_streaming) {
JOM(16, "returning 0 because audio urbs not streaming\n"); JOM(16, "returning 0 because audio urbs not streaming\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0; return 0;
} }
} }
...@@ -889,22 +1691,23 @@ JOM(12, "after wait, %i=frag read %i=frag fill\n", \ ...@@ -889,22 +1691,23 @@ JOM(12, "after wait, %i=frag read %i=frag fill\n", \
(peasycap->audio_read / peasycap->audio_pages_per_fragment), \ (peasycap->audio_read / peasycap->audio_pages_per_fragment), \
(peasycap->audio_fill / peasycap->audio_pages_per_fragment)); (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
szret = (size_t)0; szret = (size_t)0;
fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
while (fragment == (peasycap->audio_read / \ while (fragment == (peasycap->audio_read / \
peasycap->audio_pages_per_fragment)) { peasycap->audio_pages_per_fragment)) {
if (NULL == pdata_buffer->pgo) { if (NULL == pdata_buffer->pgo) {
SAM("ERROR: pdata_buffer->pgo is NULL\n"); SAM("ERROR: pdata_buffer->pgo is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
if (NULL == pdata_buffer->pto) { if (NULL == pdata_buffer->pto) {
SAM("ERROR: pdata_buffer->pto is NULL\n"); SAM("ERROR: pdata_buffer->pto is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
if (0 > kount1) { if (0 > kount1) {
SAM("easysnd_read: MISTAKE: kount1 is negative\n"); SAM("MISTAKE: kount1 is negative\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS; return -ERESTARTSYS;
} }
if (!kount1) { if (!kount1) {
...@@ -922,23 +1725,23 @@ while (fragment == (peasycap->audio_read / \ ...@@ -922,23 +1725,23 @@ while (fragment == (peasycap->audio_read / \
(peasycap->audio_buffer_page_many <= \ (peasycap->audio_buffer_page_many <= \
peasycap->audio_read)) { peasycap->audio_read)) {
SAM("ERROR: peasycap->audio_read out of range\n"); SAM("ERROR: peasycap->audio_read out of range\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
if ((struct data_buffer *)NULL == pdata_buffer) { if ((struct data_buffer *)NULL == pdata_buffer) {
SAM("ERROR: pdata_buffer is NULL\n"); SAM("ERROR: pdata_buffer is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
if (NULL == pdata_buffer->pgo) { if (NULL == pdata_buffer->pgo) {
SAM("ERROR: pdata_buffer->pgo is NULL\n"); SAM("ERROR: pdata_buffer->pgo is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
if (NULL == pdata_buffer->pto) { if (NULL == pdata_buffer->pto) {
SAM("ERROR: pdata_buffer->pto is NULL\n"); SAM("ERROR: pdata_buffer->pto is NULL\n");
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
...@@ -967,7 +1770,7 @@ while (fragment == (peasycap->audio_read / \ ...@@ -967,7 +1770,7 @@ while (fragment == (peasycap->audio_read / \
rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more); rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
if (0 != rc) { if (0 != rc) {
SAM("ERROR: copy_to_user() returned %li\n", rc); SAM("ERROR: copy_to_user() returned %li\n", rc);
mutex_unlock(&easycap_dongle[kd].mutex_audio); mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT; return -EFAULT;
} }
*poff += (loff_t)more; *poff += (loff_t)more;
...@@ -1029,11 +1832,75 @@ if (!peasycap->timeval1.tv_sec) { ...@@ -1029,11 +1832,75 @@ if (!peasycap->timeval1.tv_sec) {
JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient); JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
peasycap->dnbydt = 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); JOM(8, "returning %li\n", (long int)szret);
mutex_unlock(&easycap_dongle[kd].mutex_audio);
return szret; return szret;
} }
/*****************************************************************************/ /*****************************************************************************/
#endif /*!EASYCAP_NEEDS_ALSA*/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* COMMON AUDIO INITIALIZATION
*/
/*---------------------------------------------------------------------------*/
int
easycap_sound_setup(struct easycap *peasycap)
{
int rc;
JOM(4, "starting initialization\n");
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL.\n");
return -EFAULT;
}
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
return -ENODEV;
}
JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
rc = audio_setup(peasycap);
JOM(8, "audio_setup() returned %i\n", rc);
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device has become NULL\n");
return -ENODEV;
}
/*---------------------------------------------------------------------------*/
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device has become NULL\n");
return -ENODEV;
}
rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
peasycap->audio_altsetting_on);
JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
peasycap->audio_altsetting_on, rc);
rc = wakeup_device(peasycap->pusb_device);
JOM(8, "wakeup_device() returned %i\n", rc);
peasycap->audio_eof = 0;
peasycap->audio_idle = 0;
peasycap->timeval1.tv_sec = 0;
peasycap->timeval1.tv_usec = 0;
submit_audio_urbs(peasycap);
JOM(4, "finished initialization\n");
return 0;
}
/*****************************************************************************/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* SUBMIT ALL AUDIO URBS. * SUBMIT ALL AUDIO URBS.
...@@ -1087,7 +1954,11 @@ if (!peasycap->audio_isoc_streaming) { ...@@ -1087,7 +1954,11 @@ if (!peasycap->audio_isoc_streaming) {
peasycap->audio_isoc_buffer[isbuf].pgo; peasycap->audio_isoc_buffer[isbuf].pgo;
purb->transfer_buffer_length = \ purb->transfer_buffer_length = \
peasycap->audio_isoc_buffer_size; peasycap->audio_isoc_buffer_size;
purb->complete = easysnd_complete; #if defined(EASYCAP_NEEDS_ALSA)
purb->complete = easycap_alsa_complete;
#else
purb->complete = easyoss_complete;
#endif /*EASYCAP_NEEDS_ALSA*/
purb->context = peasycap; purb->context = peasycap;
purb->start_frame = 0; purb->start_frame = 0;
purb->number_of_packets = \ purb->number_of_packets = \
...@@ -1109,14 +1980,18 @@ if (!peasycap->audio_isoc_streaming) { ...@@ -1109,14 +1980,18 @@ if (!peasycap->audio_isoc_streaming) {
SAM("ERROR: usb_submit_urb() failed" \ SAM("ERROR: usb_submit_urb() failed" \
" for urb with rc:\n"); " for urb with rc:\n");
switch (rc) { switch (rc) {
case -ENOMEM: {
SAM("-ENOMEM\n");
break;
}
case -ENODEV: { case -ENODEV: {
SAM("-ENODEV\n"); SAM("-ENODEV\n");
break; break;
} }
case -ENOENT: {
SAM("-ENOENT\n");
break;
}
case -ENOMEM: {
SAM("-ENOMEM\n");
break;
}
case -ENXIO: { case -ENXIO: {
SAM("-ENXIO\n"); SAM("-ENXIO\n");
break; break;
...@@ -1145,9 +2020,12 @@ if (!peasycap->audio_isoc_streaming) { ...@@ -1145,9 +2020,12 @@ if (!peasycap->audio_isoc_streaming) {
nospc++; nospc++;
break; break;
} }
case -EPERM: {
SAM("-EPERM\n");
break;
}
default: { default: {
SAM("unknown error code %i\n",\ SAM("unknown error: %i\n", rc);
rc);
break; break;
} }
} }
...@@ -1179,7 +2057,7 @@ if (!peasycap->audio_isoc_streaming) { ...@@ -1179,7 +2057,7 @@ if (!peasycap->audio_isoc_streaming) {
} }
peasycap->audio_isoc_streaming = 0; peasycap->audio_isoc_streaming = 0;
} else { } else {
peasycap->audio_isoc_streaming = 1; peasycap->audio_isoc_streaming = m;
JOM(4, "submitted %i audio urbs\n", m); JOM(4, "submitted %i audio urbs\n", m);
} }
} else } else
......
...@@ -24,5 +24,19 @@ ...@@ -24,5 +24,19 @@
* *
*/ */
/*****************************************************************************/ /*****************************************************************************/
#if !defined(EASYCAP_SOUND_H)
#define EASYCAP_SOUND_H
extern int easycap_debug;
extern int easycap_gain;
extern struct easycap_dongle easycapdc60_dongle[];
extern struct easycap *peasycap; extern struct easycap *peasycap;
extern struct usb_driver easycap_usb_driver; extern struct usb_driver easycap_usb_driver;
#if defined(EASYCAP_NEEDS_ALSA)
extern struct snd_pcm_hardware easycap_pcm_hardware;
#else
extern struct usb_class_driver easyoss_class;
extern const struct file_operations easyoss_fops;
#endif /*EASYCAP_NEEDS_ALSA*/
#endif /*EASYCAP_SOUND_H*/
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/*****************************************************************************/ /*****************************************************************************/
#include "easycap.h" #include "easycap.h"
#include "easycap_debug.h" #include "easycap_testcard.h"
/*****************************************************************************/ /*****************************************************************************/
#define TESTCARD_BYTESPERLINE (2 * 720) #define TESTCARD_BYTESPERLINE (2 * 720)
...@@ -397,7 +397,7 @@ int tones[2048] = { ...@@ -397,7 +397,7 @@ int tones[2048] = {
}; };
/*****************************************************************************/ /*****************************************************************************/
void void
easysnd_testtone(struct easycap *peasycap, int audio_fill) easyoss_testtone(struct easycap *peasycap, int audio_fill)
{ {
int i1; int i1;
unsigned char *p2; unsigned char *p2;
......
/*****************************************************************************
* *
* easycap_testcard.h *
* *
*****************************************************************************/
/*
*
* 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
*
*/
/*****************************************************************************/
#if !defined(EASYCAP_TESTCARD_H)
#define EASYCAP_TESTCARD_H
extern int easycap_debug;
extern int easycap_gain;
extern struct easycap_dongle easycapdc60_dongle[];
#endif /*EASYCAP_TESTCARD_H*/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment