This is necessary because some distributions are disabling OSS entirely.
Signed-off-by: Mike Thomas <rmthomas@sciolus.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
config EASYCAP
tristate "EasyCAP USB ID 05e1:0408 support"
- depends on USB && VIDEO_DEV
+ depends on USB && VIDEO_DEV && SND
---help---
This is an integrated audio/video driver for EasyCAP cards with
+easycap-objs := easycap_main.o easycap_low.o easycap_sound.o \
+ easycap_ioctl.o easycap_settings.o easycap_testcard.o
-obj-$(CONFIG_EASYCAP) += easycap.o
-
-easycap-y := easycap_main.o easycap_low.o easycap_sound.o
-easycap-y += easycap_ioctl.o easycap_settings.o
-easycap-y += easycap_testcard.o
+obj-$(CONFIG_EASYCAP) += easycap.o
ccflags-y := -Wall
-# Impose all or none of the following:
ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT
ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H
ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS
ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL
+ccflags-y += -DEASYCAP_NEEDS_ALSA
+ccflags-y += -DEASYCAP_NEEDS_CARD_CREATE
* EASYCAP_NEEDS_V4L2_DEVICE_H
* EASYCAP_NEEDS_V4L2_FOPS
* EASYCAP_NEEDS_UNLOCKED_IOCTL
+ * EASYCAP_NEEDS_ALSA
+ * EASYCAP_SILENT
*
* IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
* OPTIONS.
*/
/*---------------------------------------------------------------------------*/
#undef EASYCAP_TESTCARD
+#if (!defined(EASYCAP_NEEDS_ALSA))
#undef EASYCAP_TESTTONE
-#undef NOREADBACK
-#undef AUDIOTIME
+#endif /*EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/types.h>
+#if defined(EASYCAP_NEEDS_ALSA)
+#include <linux/vmalloc.h>
+#include <linux/sound.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#endif /*EASYCAP_NEEDS_ALSA*/
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
#include <media/v4l2-dev.h>
#define USB_EASYCAP_VENDOR_ID 0x05e1
#define USB_EASYCAP_PRODUCT_ID 0x0408
-#define EASYCAP_DRIVER_VERSION "0.8.41"
+#define EASYCAP_DRIVER_VERSION "0.9.01"
#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
#define USB_SKEL_MINOR_BASE 192
*/
/*---------------------------------------------------------------------------*/
#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_FRAGMENT_MANY 32
+#define PAGES_PER_AUDIO_FRAGMENT 4
/*---------------------------------------------------------------------------*/
/*
* IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
#define TELLTALE "expectedstring"
char telltale[16];
int isdongle;
+int minor;
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
wait_queue_head_t wq_video;
wait_queue_head_t wq_audio;
+wait_queue_head_t wq_trigger;
int input;
int polled;
int allocation_video_struct;
int registered_video;
/*---------------------------------------------------------------------------*/
+/*
+ * ALSA
+ */
+/*---------------------------------------------------------------------------*/
+#if defined(EASYCAP_NEEDS_ALSA)
+struct snd_pcm_hardware alsa_hardware;
+struct snd_card *psnd_card;
+struct snd_pcm *psnd_pcm;
+struct snd_pcm_substream *psubstream;
+int dma_fill;
+int dma_next;
+int dma_read;
+#endif /*EASYCAP_NEEDS_ALSA*/
+/*---------------------------------------------------------------------------*/
/*
* SOUND PROPERTIES
*/
* BUFFER INDICATORS
*/
/*---------------------------------------------------------------------------*/
-int audio_fill; /* Audio buffer being filled by easysnd_complete(). */
- /* Bumped only by easysnd_complete(). */
-int audio_read; /* Audio buffer page being read by easysnd_read(). */
- /* Set by easysnd_read() to trail audio_fill by */
+int audio_fill; /* Audio buffer being filled by easycap_complete(). */
+ /* Bumped only by easycap_complete(). */
+int audio_read; /* Audio buffer page being read by easycap_read(). */
+ /* Set by easycap_read() to trail audio_fill by */
/* one fragment. */
/*---------------------------------------------------------------------------*/
/*
* AUDIO FUNCTION PROTOTYPES
*/
/*---------------------------------------------------------------------------*/
-void easysnd_complete(struct urb *);
-ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *);
-int easysnd_open(struct inode *, struct file *);
-int easysnd_release(struct inode *, struct file *);
-long easysnd_ioctl_noinode(struct file *, unsigned int, \
+#if defined(EASYCAP_NEEDS_ALSA)
+int easycap_alsa_probe(struct easycap *);
+
+void easycap_alsa_complete(struct urb *);
+int easycap_alsa_open(struct snd_pcm_substream *);
+int easycap_alsa_close(struct snd_pcm_substream *);
+int easycap_alsa_hw_params(struct snd_pcm_substream *, \
+ struct snd_pcm_hw_params *);
+int easycap_alsa_vmalloc(struct snd_pcm_substream *, size_t);
+int easycap_alsa_hw_free(struct snd_pcm_substream *);
+int easycap_alsa_prepare(struct snd_pcm_substream *);
+int easycap_alsa_ack(struct snd_pcm_substream *);
+int easycap_alsa_trigger(struct snd_pcm_substream *, int);
+snd_pcm_uframes_t \
+ easycap_alsa_pointer(struct snd_pcm_substream *);
+struct page *easycap_alsa_page(struct snd_pcm_substream *, unsigned long);
+
+#else
+void easyoss_complete(struct urb *);
+ssize_t easyoss_read(struct file *, char __user *, size_t, loff_t *);
+int easyoss_open(struct inode *, struct file *);
+int easyoss_release(struct inode *, struct file *);
+long easyoss_ioctl_noinode(struct file *, unsigned int, \
unsigned long);
-int easysnd_ioctl(struct inode *, struct file *, unsigned int, \
+int easyoss_ioctl(struct inode *, struct file *, unsigned int, \
unsigned long);
-unsigned int easysnd_poll(struct file *, poll_table *);
-void easysnd_delete(struct kref *);
+unsigned int easyoss_poll(struct file *, poll_table *);
+void easyoss_delete(struct kref *);
+#endif /*EASYCAP_NEEDS_ALSA*/
+int easycap_sound_setup(struct easycap *);
int submit_audio_urbs(struct easycap *);
int kill_audio_urbs(struct easycap *);
-void easysnd_testtone(struct easycap *, int);
+void easyoss_testtone(struct easycap *, int);
int audio_setup(struct easycap *);
/*---------------------------------------------------------------------------*/
/*
+++ /dev/null
-/*****************************************************************************
-* *
-* easycap_debug.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
- *
-*/
-/*****************************************************************************/
-extern int easycap_debug;
-extern int easycap_gain;
-extern struct easycap_dongle easycap_dongle[];
#include <linux/smp_lock.h>
#include "easycap.h"
-#include "easycap_debug.h"
-#include "easycap_standard.h"
#include "easycap_ioctl.h"
/*--------------------------------------------------------------------------*/
* peasycap->audio_interface, \
* peasycap->audio_altsetting_off);
* HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
- * -ESHUTDOWN. THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT
+ * -ESHUTDOWN. THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
* THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
*/
/*---------------------------------------------------------------------------*/
}
kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
- SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+ SAY("ERROR: cannot lock " \
+ "easycapdc60_dongle[%i].mutex_video\n", kd);
return -ERESTARTSYS;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
/*---------------------------------------------------------------------------*/
/*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
return -ERESTARTSYS;
if (NULL == file) {
SAY("ERROR: file is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
peasycap = file->private_data;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
p = peasycap->pusb_device;
if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
} else {
if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
SAM("ERROR: bad driver version string\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
strcpy(&version[0], EASYCAP_DRIVER_VERSION);
if (0 != rc) {
SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
rc, p1);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].\
+ mutex_video);
return -EINVAL;
}
k[i] = (int)lng;
}
if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
sizeof(struct v4l2_capability))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
sizeof(struct v4l2_input))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
}
default: {
JOM(8, "%i=index: exhausts inputs\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
sizeof(struct v4l2_input))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
index = (__u32)peasycap->input;
JOM(8, "user is told: %i\n", index);
if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
JOM(8, "VIDIOC_S_INPUT\n");
if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if ((0 > index) || (INPUT_MANY <= index)) {
JOM(8, "ERROR: bad requested input: %i\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
JOM(8, "newinput(.,%i) OK\n", (int)index);
} else {
SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_ENUMAUDIO: {
JOM(8, "VIDIOC_ENUMAUDIO\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
sizeof(struct v4l2_audioout))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (0 != v4l2_audioout.index) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
sizeof(struct v4l2_audioout))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
sizeof(struct v4l2_queryctrl))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
}
if (0xFFFFFFFF == easycap_control[i1].id) {
JOM(8, "%i=index: exhausts controls\n", i1);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
sizeof(struct v4l2_queryctrl))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYMENU: {
JOM(8, "VIDIOC_QUERYMENU unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
if (!pv4l2_control) {
SAM("ERROR: out of memory\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM;
}
if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
sizeof(struct v4l2_control))) {
kfree(pv4l2_control);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
pv4l2_control->id);
kfree(pv4l2_control);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
sizeof(struct v4l2_control))) {
kfree(pv4l2_control);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
kfree(pv4l2_control);
if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
sizeof(struct v4l2_control))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
default: {
SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
v4l2_control.id);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_EXT_CTRLS: {
JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
sizeof(struct v4l2_fmtdesc))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
}
default: {
JOM(8, "%i=index: exhausts formats\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
sizeof(struct v4l2_fmtdesc))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
sizeof(struct v4l2_frmsizeenum))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
}
default: {
JOM(8, "%i=index: exhausts framesizes\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
}
default: {
JOM(8, "%i=index: exhausts framesizes\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
}
if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
sizeof(struct v4l2_frmsizeenum))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
sizeof(struct v4l2_frmivalenum))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
}
default: {
JOM(8, "%i=index: exhausts frameintervals\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
}
if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
sizeof(struct v4l2_frmivalenum))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
if (!pv4l2_format) {
SAM("ERROR: out of memory\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM;
}
pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
if (!pv4l2_pix_format) {
SAM("ERROR: out of memory\n");
kfree(pv4l2_format);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM;
}
if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
sizeof(struct v4l2_format))) {
kfree(pv4l2_format);
kfree(pv4l2_pix_format);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
kfree(pv4l2_format);
kfree(pv4l2_pix_format);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
sizeof(struct v4l2_format))) {
kfree(pv4l2_format);
kfree(pv4l2_pix_format);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
kfree(pv4l2_format);
if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
sizeof(struct v4l2_format))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
try);
if (0 > best_format) {
if (-EBUSY == best_format) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EBUSY;
}
JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOENT;
}
/*...........................................................................*/
if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
sizeof(struct v4l2_format))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
sizeof(struct v4l2_cropcap))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
sizeof(struct v4l2_cropcap))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
case VIDIOC_G_CROP:
case VIDIOC_S_CROP: {
JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_QUERYSTD: {
JOM(8, "VIDIOC_QUERYSTD: " \
"EasyCAP is incapable of detecting standard\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
break;
}
if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
sizeof(struct v4l2_standard))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
index = v4l2_standard.index;
}
if (0xFFFF == peasycap_standard->mask) {
JOM(8, "%i=index: exhausts standards\n", index);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
JOM(8, "%i=index: %s\n", index, \
if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
sizeof(struct v4l2_standard))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 > peasycap->standard_offset) {
JOM(8, "%i=peasycap->standard_offset\n", \
peasycap->standard_offset);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EBUSY;
}
if (0 != copy_from_user(&std_id, (void __user *)arg, \
sizeof(v4l2_std_id))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (0 != copy_to_user((void __user *)arg, &std_id, \
sizeof(v4l2_std_id))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&std_id, (void __user *)arg, \
sizeof(v4l2_std_id))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
rc = adjust_standard(peasycap, std_id);
if (0 > rc) {
JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOENT;
}
break;
if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
sizeof(struct v4l2_requestbuffers))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
nbuffers = v4l2_requestbuffers.count;
if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
sizeof(struct v4l2_requestbuffers))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (peasycap->video_eof) {
JOM(8, "returning -EIO because %i=video_eof\n", \
peasycap->video_eof);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO;
}
if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
sizeof(struct v4l2_buffer))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
index = v4l2_buffer.index;
if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
sizeof(struct v4l2_buffer))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
break;
if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
sizeof(struct v4l2_buffer))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
if (v4l2_buffer.index < 0 || \
(v4l2_buffer.index >= peasycap->frame_buffer_many)) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
sizeof(struct v4l2_buffer))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
JOM(8, "returning -EIO because " \
"%i=video_idle %i=video_eof\n", \
peasycap->video_idle, peasycap->video_eof);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO;
}
if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
sizeof(struct v4l2_buffer))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
if (!peasycap->video_isoc_streaming) {
JOM(16, "returning -EIO because video urbs not streaming\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO;
}
/*---------------------------------------------------------------------------*/
if (-EIO == rcdq) {
JOM(8, "returning -EIO because " \
"dqbuf() returned -EIO\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].\
+ mutex_video);
return -EIO;
}
} while (0 != rcdq);
} else {
if (peasycap->video_eof) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EIO;
}
}
if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
- SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
+ JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n", \
peasycap->done[peasycap->frame_read]);
}
peasycap->polled = 0;
if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
sizeof(struct v4l2_buffer))) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
peasycap->merit[i] = 0;
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
submit_video_urbs(peasycap);
if ((struct usb_device *)NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
JOM(8, "calling wake_up on wq_video and wq_audio\n");
wake_up_interruptible(&(peasycap->wq_video));
+#if defined(EASYCAP_NEEDS_ALSA)
+ if (NULL != peasycap->psubstream)
+ snd_pcm_period_elapsed(peasycap->psubstream);
+#else
wake_up_interruptible(&(peasycap->wq_audio));
+#endif /*EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
break;
}
pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
if (!pv4l2_streamparm) {
SAM("ERROR: out of memory\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOMEM;
}
if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
sizeof(struct v4l2_streamparm))) {
kfree(pv4l2_streamparm);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
kfree(pv4l2_streamparm);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
pv4l2_streamparm->parm.capture.capability = 0;
if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
sizeof(struct v4l2_streamparm))) {
kfree(pv4l2_streamparm);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EFAULT;
}
kfree(pv4l2_streamparm);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_PARM: {
JOM(8, "VIDIOC_S_PARM unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_AUDIO: {
JOM(8, "VIDIOC_G_AUDIO unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_AUDIO: {
JOM(8, "VIDIOC_S_AUDIO unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_TUNER: {
JOM(8, "VIDIOC_S_TUNER unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_S_FBUF:
case VIDIOC_OVERLAY: {
JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
case VIDIOC_G_TUNER: {
JOM(8, "VIDIOC_G_TUNER unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
case VIDIOC_G_FREQUENCY:
case VIDIOC_S_FREQUENCY: {
JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -EINVAL;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
default: {
JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ENOIOCTLCMD;
}
}
-mutex_unlock(&easycap_dongle[kd].mutex_video);
-JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
return 0;
}
/*****************************************************************************/
+#if !defined(EASYCAP_NEEDS_ALSA)
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
(defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
long
-easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
- return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
+easyoss_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
+ return (long)easyoss_ioctl((struct inode *)NULL, file, cmd, arg);
}
#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/*---------------------------------------------------------------------------*/
int
-easysnd_ioctl(struct inode *inode, struct file *file,
+easyoss_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct easycap *peasycap;
}
kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
- SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
+ SAY("ERROR: cannot lock "
+ "easycapdc60_dongle[%i].mutex_audio\n", kd);
return -ERESTARTSYS;
}
- JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
/*---------------------------------------------------------------------------*/
/*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
return -ERESTARTSYS;
if (NULL == file) {
SAY("ERROR: file is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
peasycap = file->private_data;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
p = peasycap->pusb_device;
if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
} else {
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
int incoming, outgoing;
JOM(8, "SNDCTL_DSP_SETFMT\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(8, "........... %i=incoming\n", incoming);
JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8);
if (0 != copy_to_user((void __user *)arg, &outgoing, \
sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EINVAL ;
}
break;
int incoming;
JOM(8, "SNDCTL_DSP_STEREO\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(8, "........... %i=incoming\n", incoming);
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
int incoming;
JOM(8, "SNDCTL_DSP_SPEED\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(8, "........... %i=incoming\n", incoming);
#endif /*UPSAMPLE*/
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
int incoming;
JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(8, "........... %i=incoming\n", incoming);
incoming = PCM_ENABLE_INPUT;
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
int incoming;
JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(8, "........... %i=incoming\n", incoming);
int incoming;
JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(8, "........... %i=incoming\n", incoming);
incoming = peasycap->audio_bytes_per_fragment;
if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
sizeof(int))) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
break;
case 0x00005405:
case 0x00005406: {
JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ENOIOCTLCMD;
}
default: {
JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ENOIOCTLCMD;
}
}
-mutex_unlock(&easycap_dongle[kd].mutex_audio);
+mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0;
}
+#endif /*EASYCAP_NEEDS_ALSA*/
/*****************************************************************************/
-
*
*/
/*****************************************************************************/
+#if !defined(EASYCAP_IOCTL_H)
+#define EASYCAP_IOCTL_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
+extern struct easycap_standard easycap_standard[];
extern struct easycap_format easycap_format[];
extern struct v4l2_queryctrl easycap_control[];
+
+#endif /*EASYCAP_IOCTL_H*/
/****************************************************************************/
#include "easycap.h"
-#include "easycap_debug.h"
+#include "easycap_low.h"
/*--------------------------------------------------------------------------*/
const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
(int)50000);
JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0]));
-if (rc != (int)length)
- SAY("ERROR: usb_control_msg returned %i\n", rc);
-
+if (rc != (int)length) {
+ switch (rc) {
+ case -EPIPE: {
+ SAY("usb_control_msg returned -EPIPE\n");
+ break;
+ }
+ default: {
+ SAY("ERROR: usb_control_msg returned %i\n", rc);
+ break;
+ }
+ }
+}
/*--------------------------------------------------------------------------*/
/*
* REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
--- /dev/null
+/*****************************************************************************
+* *
+* easycap_low.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_LOW_H)
+#define EASYCAP_LOW_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
+
+#endif /*EASYCAP_LOW_H*/
/*****************************************************************************/
#include "easycap.h"
-#include "easycap_standard.h"
-#include "easycap_ioctl.h"
+#include "easycap_main.h"
int easycap_debug;
-static int easycap_bars;
+static int easycap_bars = 1;
int easycap_gain = 16;
module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
-/*---------------------------------------------------------------------------*/
-/*
- * dongle_this IS INDISPENSIBLY static BECAUSE FUNCTION easycap_usb_probe()
- * IS CALLED SUCCESSIVELY FOR INTERFACES 0, 1, 2 AND THE POINTER peasycap
- * ALLOCATED DURING THE PROBING OF INTERFACE 0 MUST BE REMEMBERED WHEN
- * PROBING INTERFACES 1 AND 2.
- *
- * IOCTL LOCKING IS DONE AT MODULE LEVEL, NOT DEVICE LEVEL.
-*/
-/*---------------------------------------------------------------------------*/
-
-struct easycap_dongle easycap_dongle[DONGLE_MANY];
-static int dongle_this;
-static int dongle_done;
+struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
+static struct mutex mutex_dongle;
/*---------------------------------------------------------------------------*/
/*
#endif /*EASYCAP_NEEDS_V4L2_FOPS*/
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*--------------------------------------------------------------------------*/
-/*
- * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
- */
-/*--------------------------------------------------------------------------*/
-const struct file_operations easysnd_fops = {
- .owner = THIS_MODULE,
- .open = easysnd_open,
- .release = easysnd_release,
-#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
- .unlocked_ioctl = easysnd_ioctl_noinode,
-#else
- .ioctl = easysnd_ioctl,
-#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
- .read = easysnd_read,
- .llseek = no_llseek,
-};
-struct usb_class_driver easysnd_class = {
-.name = "usb/easysnd%d",
-.fops = &easysnd_fops,
-.minor_base = USB_SKEL_MINOR_BASE,
-};
/****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
if (NULL == peasycap)
return -2;
for (k = 0; k < DONGLE_MANY; k++) {
- if (easycap_dongle[k].peasycap == peasycap) {
+ if (easycapdc60_dongle[k].peasycap == peasycap) {
peasycap->isdongle = k;
return k;
}
m++;
}
}
-JOM(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \
+JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n", \
m * (0x01 << AUDIO_ISOC_ORDER));
/*---------------------------------------------------------------------------*/
+#if !defined(EASYCAP_NEEDS_ALSA)
JOM(4, "freeing audio buffers.\n");
gone = 0;
for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
gone++;
}
}
-JOM(4, "easysnd_delete(): audio buffers freed: %i pages\n", gone);
+JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
+#endif /*!EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
JOM(4, "freeing easycap structure.\n");
allocation_video_urb = peasycap->allocation_video_urb;
registered_audio = peasycap->registered_audio;
kfree(peasycap);
+
if (0 <= kd && DONGLE_MANY > kd) {
- easycap_dongle[kd].peasycap = (struct easycap *)NULL;
- JOT(4, " null-->easycap_dongle[%i].peasycap\n", kd);
- allocation_video_struct -= sizeof(struct easycap);
+ if (mutex_lock_interruptible(&mutex_dongle)) {
+ SAY("ERROR: cannot down mutex_dongle\n");
+ } else {
+ JOM(4, "locked mutex_dongle\n");
+ easycapdc60_dongle[kd].peasycap = (struct easycap *)NULL;
+ mutex_unlock(&mutex_dongle);
+ JOM(4, "unlocked mutex_dongle\n");
+ JOT(4, " null-->easycapdc60_dongle[%i].peasycap\n", kd);
+ allocation_video_struct -= sizeof(struct easycap);
+ }
} else {
- SAY("ERROR: cannot purge easycap_dongle[].peasycap");
+ SAY("ERROR: cannot purge easycapdc60_dongle[].peasycap");
}
/*---------------------------------------------------------------------------*/
SAY("%8i= video urbs after all deletions\n", allocation_video_urb);
/*---------------------------------------------------------------------------*/
kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
- SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+ SAY("ERROR: cannot down "
+ "easycapdc60_dongle[%i].mutex_video\n", kd);
return -ERESTARTSYS;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
/*-------------------------------------------------------------------*/
/*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
return -ERESTARTSYS;
if (NULL == file) {
SAY("ERROR: file is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
peasycap = file->private_data;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap: 0x%08lX\n", \
(unsigned long int) peasycap);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return -ERESTARTSYS;
}
} else
/*---------------------------------------------------------------------------*/
rc = easycap_dqbuf(peasycap, 0);
peasycap->polled = 1;
-mutex_unlock(&easycap_dongle[kd].mutex_video);
+mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
if (0 == rc)
return POLLIN | POLLRDNORM;
else
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
- *
- * FIXME
- *
- *
- * THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE EasyCAP
- * IS PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST.
- * IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops.
- *
- * THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE.
+ * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
+ * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
*/
/*---------------------------------------------------------------------------*/
int
easycap_usb_probe(struct usb_interface *pusb_interface, \
- const struct usb_device_id *id)
+ const struct usb_device_id *pusb_device_id)
{
struct usb_device *pusb_device, *pusb_device1;
struct usb_host_interface *pusb_host_interface;
struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
struct urb *purb;
struct easycap *peasycap;
+int ndong;
struct data_urb *pdata_urb;
size_t wMaxPacketSize;
int ISOCwMaxPacketSize;
__u16 mask;
__s32 value;
struct easycap_format *peasycap_format;
-
-JOT(4, "\n");
-
-if (!dongle_done) {
- dongle_done = 1;
- for (k = 0; k < DONGLE_MANY; k++) {
- easycap_dongle[k].peasycap = (struct easycap *)NULL;
- mutex_init(&easycap_dongle[k].mutex_video);
- mutex_init(&easycap_dongle[k].mutex_audio);
- }
-}
-
-peasycap = (struct easycap *)NULL;
+/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
+#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
+struct v4l2_device *pv4l2_device;
+#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
+#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
+/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
if ((struct usb_interface *)NULL == pusb_interface) {
SAY("ERROR: pusb_interface is NULL\n");
return -EFAULT;
}
+peasycap = (struct easycap *)NULL;
/*---------------------------------------------------------------------------*/
/*
* GET POINTER TO STRUCTURE usb_device
JOT(4, "ERROR: pusb_device1 != pusb_device\n");
return -EFAULT;
}
-
JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
-
/*---------------------------------------------------------------------------*/
pusb_host_interface = pusb_interface->cur_altsetting;
if (NULL == pusb_host_interface) {
*
* THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
* INTERFACES 1 AND 2 ARE PROBED.
- *
- * IF TWO EasyCAPs ARE PLUGGED IN NEARLY SIMULTANEOUSLY THERE WILL
- * BE TROUBLE. BEWARE.
*/
/*---------------------------------------------------------------------------*/
if (0 == bInterfaceNumber) {
* PERFORM URGENT INTIALIZATIONS ...
*/
/*---------------------------------------------------------------------------*/
+ peasycap->minor = -1;
strcpy(&peasycap->telltale[0], TELLTALE);
kref_init(&peasycap->kref);
JOM(8, "intf[%i]: after kref_init(..._video) " \
init_waitqueue_head(&peasycap->wq_video);
init_waitqueue_head(&peasycap->wq_audio);
+ init_waitqueue_head(&peasycap->wq_trigger);
- for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) {
- if (NULL == easycap_dongle[dongle_this].peasycap) {
- if (0 == mutex_is_locked(&easycap_dongle\
- [dongle_this].mutex_video)) {
- if (0 == mutex_is_locked(&easycap_dongle\
- [dongle_this].mutex_audio)) {
- easycap_dongle\
- [dongle_this].peasycap = \
- peasycap;
- JOM(8, "intf[%i]: peasycap-->easycap" \
+ if (mutex_lock_interruptible(&mutex_dongle)) {
+ SAY("ERROR: cannot down mutex_dongle\n");
+ return -ERESTARTSYS;
+ } else {
+/*---------------------------------------------------------------------------*/
+ /*
+ * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
+ * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
+ *
+ * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
+ * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
+ * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
+ */
+/*---------------------------------------------------------------------------*/
+ for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+ if ((NULL == easycapdc60_dongle[ndong].peasycap) && \
+ (!mutex_is_locked(&easycapdc60_dongle\
+ [ndong].mutex_video)) && \
+ (!mutex_is_locked(&easycapdc60_dongle\
+ [ndong].mutex_audio))) {
+ easycapdc60_dongle[ndong].peasycap = peasycap;
+ peasycap->isdongle = ndong;
+ JOM(8, "intf[%i]: peasycap-->easycap" \
"_dongle[%i].peasycap\n", \
- bInterfaceNumber, dongle_this);
- break;
- }
+ bInterfaceNumber, ndong);
+ break;
}
}
+ if (DONGLE_MANY <= ndong) {
+ SAM("ERROR: too many dongles\n");
+ mutex_unlock(&mutex_dongle);
+ return -ENOMEM;
+ }
+ mutex_unlock(&mutex_dongle);
}
- if (DONGLE_MANY <= dongle_this) {
- SAM("ERROR: too many dongles\n");
- return -ENOMEM;
- }
-
peasycap->allocation_video_struct = sizeof(struct easycap);
peasycap->allocation_video_page = 0;
peasycap->allocation_video_urb = 0;
JOM(4, "finished initialization\n");
} else {
/*---------------------------------------------------------------------------*/
- /*
- * FOR INTERFACES 1 AND 2 THE POINTER peasycap IS OBTAINED BY ASSUMING
- * THAT dongle_this HAS NOT CHANGED SINCE INTERFACE 0 WAS PROBED. IF
- * THIS IS NOT THE CASE, FOR EXAMPLE WHEN TWO EASYCAPs ARE PLUGGED IN
- * SIMULTANEOUSLY, THERE WILL BE SERIOUS TROUBLE.
- */
+/*
+ * FIXME
+ *
+ * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
+ * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
+ */
/*---------------------------------------------------------------------------*/
- if ((0 > dongle_this) || (DONGLE_MANY <= dongle_this)) {
- SAY("ERROR: bad dongle count\n");
- return -EFAULT;
+ for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+ if (pusb_device == easycapdc60_dongle[ndong].peasycap->\
+ pusb_device) {
+ peasycap = easycapdc60_dongle[ndong].peasycap;
+ JOT(8, "intf[%i]: easycapdc60_dongle[%i].peasycap-->" \
+ "peasycap\n", bInterfaceNumber, ndong);
+ break;
+ }
}
- peasycap = easycap_dongle[dongle_this].peasycap;
- JOT(8, "intf[%i]: easycap_dongle[%i].peasycap-->peasycap\n", \
- bInterfaceNumber, dongle_this);
-
- if ((struct easycap *)NULL == peasycap) {
+ if (DONGLE_MANY <= ndong) {
+ SAY("ERROR: peasycap is unknown when probing interface %i\n", \
+ bInterfaceNumber);
+ return -ENODEV;
+ }
+ if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL when probing interface %i\n", \
bInterfaceNumber);
- return -EFAULT;
+ return -ENODEV;
}
+#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
+#
+/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+#else
+#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
+/*---------------------------------------------------------------------------*/
+/*
+ * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
+ * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
+ * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
+ * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
+*/
+/*---------------------------------------------------------------------------*/
+ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ pv4l2_device = usb_get_intfdata(pusb_interface);
+ if ((struct v4l2_device *)NULL == pv4l2_device) {
+ SAY("ERROR: pv4l2_device is NULL\n");
+ return -ENODEV;
+ }
+ peasycap = (struct easycap *) \
+ container_of(pv4l2_device, struct easycap, v4l2_device);
+ }
+#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
+#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
}
/*---------------------------------------------------------------------------*/
if ((USB_CLASS_VIDEO == bInterfaceClass) || \
} else {
(peasycap->registered_video)++;
SAM("easycap attached to minor #%d\n", pusb_interface->minor);
+ peasycap->minor = pusb_interface->minor;
break;
}
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
}
/*---------------------------------------------------------------------------*/
/*
- * FIXME
+ * FIXME
*
*
* THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
(peasycap->registered_video)++;
SAM("registered with videodev: %i=minor\n", \
peasycap->video_device.minor);
+ peasycap->minor = peasycap->video_device.minor;
}
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+
break;
}
/*--------------------------------------------------------------------------*/
*/
/*--------------------------------------------------------------------------*/
case 1: {
+#if defined(EASYCAP_SILENT)
+ return -ENOENT;
+#endif /*EASYCAP_SILENT*/
if (!peasycap) {
- SAM("ERROR: peasycap is NULL\n");
+ SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT;
}
/*--------------------------------------------------------------------------*/
}
/*--------------------------------------------------------------------------*/
case 2: {
+#if defined(EASYCAP_SILENT)
+ return -ENOENT;
+#endif /*EASYCAP_SILENT*/
if (!peasycap) {
SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT;
}
if (9 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk |= 0x02;
- SAM("hardware is FOUR-CVBS\n");
+ SAM("audio hardware is microphone\n");
peasycap->microphone = true;
- peasycap->audio_pages_per_fragment = 4;
+ peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
} else if (256 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk &= ~0x02;
- SAM("hardware is CVBS+S-VIDEO\n");
+ SAM("audio hardware is AC'97\n");
peasycap->microphone = false;
- peasycap->audio_pages_per_fragment = 4;
+ peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
} else {
SAM("hardware is unidentified:\n");
SAM("%i=audio_isoc_maxframesize\n", \
JOM(4, "%6i=audio_buffer_page_many\n", \
peasycap->audio_buffer_page_many);
- peasycap->audio_isoc_framesperdesc = 128;
+ peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
JOM(4, "%i=audio_isoc_framesperdesc\n", \
peasycap->audio_isoc_framesperdesc);
INIT_LIST_HEAD(&(peasycap->urb_audio_head));
peasycap->purb_audio_head = &(peasycap->urb_audio_head);
+#if !defined(EASYCAP_NEEDS_ALSA)
JOM(4, "allocating an audio buffer\n");
JOM(4, ".... scattered over %i pages\n", \
peasycap->audio_buffer_page_many);
peasycap->audio_fill = 0;
peasycap->audio_read = 0;
JOM(4, "allocation of audio buffer done: %i pages\n", k);
+#endif /*!EASYCAP_NEEDS_ALSA*/
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i isoc audio buffers of size %i\n", \
AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
"peasycap->audio_isoc_buffer[.].pgo;\n");
JOM(4, " purb->transfer_buffer_length = %i;\n", \
peasycap->audio_isoc_buffer_size);
- JOM(4, " purb->complete = easysnd_complete;\n");
+#if defined(EASYCAP_NEEDS_ALSA)
+ JOM(4, " purb->complete = easycap_alsa_complete;\n");
+#else
+ JOM(4, " purb->complete = easyoss_complete;\n");
+#endif /*EASYCAP_NEEDS_ALSA*/
JOM(4, " purb->context = peasycap;\n");
JOM(4, " purb->start_frame = 0;\n");
JOM(4, " purb->number_of_packets = %i;\n", \
purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
purb->transfer_buffer_length = \
peasycap->audio_isoc_buffer_size;
- purb->complete = easysnd_complete;
+#if defined(EASYCAP_NEEDS_ALSA)
+ purb->complete = easycap_alsa_complete;
+#else
+ purb->complete = easyoss_complete;
+#endif /*EASYCAP_NEEDS_ALSA*/
purb->context = peasycap;
purb->start_frame = 0;
purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
* THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
*/
/*---------------------------------------------------------------------------*/
- rc = usb_register_dev(pusb_interface, &easysnd_class);
+#if defined(EASYCAP_NEEDS_ALSA)
+ JOM(4, "initializing ALSA card\n");
+
+ rc = easycap_alsa_probe(peasycap);
+ if (0 != rc) {
+ err("easycap_alsa_probe() returned %i\n", rc);
+ return -ENODEV;
+ } else {
+ JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",\
+ (int)peasycap->kref.refcount.counter);
+ kref_get(&peasycap->kref);
+ (peasycap->registered_audio)++;
+ }
+
+#else /*EASYCAP_NEEDS_ALSA*/
+ rc = usb_register_dev(pusb_interface, &easyoss_class);
if (0 != rc) {
- err("Not able to get a minor for this device.");
+ SAY("ERROR: usb_register_dev() failed\n");
usb_set_intfdata(pusb_interface, NULL);
return -ENODEV;
} else {
* 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;
}
/*---------------------------------------------------------------------------*/
return -EINVAL;
}
}
-JOM(4, "ends successfully for interface %i\n", \
+SAM("ends successfully for interface %i\n", \
pusb_interface_descriptor->bInterfaceNumber);
return 0;
}
/*
* WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
* UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
+ *
+ * THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
*/
/*---------------------------------------------------------------------------*/
void
case 0: {
if (0 <= kd && DONGLE_MANY > kd) {
wake_up_interruptible(&peasycap->wq_video);
- JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].\
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", \
+ kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].\
mutex_video)) {
- SAY("ERROR: cannot lock easycap_dongle[%i]." \
+ SAY("ERROR: cannot lock easycapdc60_dongle[%i]." \
"mutex_video\n", kd);
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
} else
SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
/*---------------------------------------------------------------------------*/
if (!peasycap->v4l2_device.name[0]) {
SAM("ERROR: peasycap->v4l2_device.name is empty\n");
if (0 <= kd && DONGLE_MANY > kd)
- mutex_unlock(&easycap_dongle[kd].mutex_video);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
return;
}
v4l2_device_disconnect(&peasycap->v4l2_device);
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
if (0 <= kd && DONGLE_MANY > kd) {
- mutex_unlock(&easycap_dongle[kd].mutex_video);
- JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
}
break;
}
case 2: {
if (0 <= kd && DONGLE_MANY > kd) {
wake_up_interruptible(&peasycap->wq_audio);
- JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].\
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", \
+ kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].\
mutex_audio)) {
- SAY("ERROR: cannot lock easycap_dongle[%i]." \
+ SAY("ERROR: cannot lock easycapdc60_dongle[%i]." \
"mutex_audio\n", kd);
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
} else
SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
+#if defined(EASYCAP_NEEDS_ALSA)
- usb_deregister_dev(pusb_interface, &easysnd_class);
- (peasycap->registered_audio)--;
+
+ if (0 != snd_card_free(peasycap->psnd_card)) {
+ SAY("ERROR: snd_card_free() failed\n");
+ } else {
+ peasycap->psnd_card = (struct snd_card *)NULL;
+ (peasycap->registered_audio)--;
+ }
+
+
+#else /*EASYCAP_NEEDS_ALSA*/
+ usb_deregister_dev(pusb_interface, &easyoss_class);
+ (peasycap->registered_audio)--;
JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
- SAM("easysnd detached from minor #%d\n", minor);
+ SAM("easyoss detached from minor #%d\n", minor);
+#endif /*EASYCAP_NEEDS_ALSA*/
if (0 <= kd && DONGLE_MANY > kd) {
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
- JOM(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
}
break;
}
/*---------------------------------------------------------------------------*/
/*
* CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
+ * (ALSO WHEN ALSA HAS BEEN IN USE)
*/
/*---------------------------------------------------------------------------*/
if (!peasycap->kref.refcount.counter) {
return;
}
if (0 <= kd && DONGLE_MANY > kd) {
- JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
- SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+ SAY("ERROR: cannot down "
+ "easycapdc60_dongle[%i].mutex_video\n", kd);
SAM("ending unsuccessfully: may cause memory leak\n");
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
- JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd);
- if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
- SAY("ERROR: cannot down easycap_dongle[%i].mutex_audio\n", kd);
- mutex_unlock(&(easycap_dongle[kd].mutex_video));
- JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
+ JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", kd);
+ if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
+ SAY("ERROR: cannot down "
+ "easycapdc60_dongle[%i].mutex_audio\n", kd);
+ mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
+ JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
SAM("ending unsuccessfully: may cause memory leak\n");
return;
}
- JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
}
JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", \
bInterfaceNumber, (int)peasycap->kref.refcount.counter);
kref_put(&peasycap->kref, easycap_delete);
JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
if (0 <= kd && DONGLE_MANY > kd) {
- mutex_unlock(&(easycap_dongle[kd].mutex_audio));
- JOT(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd);
- mutex_unlock(&easycap_dongle[kd].mutex_video);
- JOT(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+ mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
+ JOT(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+ JOT(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
}
/*---------------------------------------------------------------------------*/
JOM(4, "ends\n");
int __init
easycap_module_init(void)
{
-int result;
+int k, rc;
SAY("========easycap=======\n");
JOT(4, "begins. %i=debug %i=bars %i=gain\n", easycap_debug, easycap_bars, \
easycap_gain);
SAY("version: " EASYCAP_DRIVER_VERSION "\n");
+
+mutex_init(&mutex_dongle);
+for (k = 0; k < DONGLE_MANY; k++) {
+ easycapdc60_dongle[k].peasycap = (struct easycap *)NULL;
+ mutex_init(&easycapdc60_dongle[k].mutex_video);
+ mutex_init(&easycapdc60_dongle[k].mutex_audio);
+}
/*---------------------------------------------------------------------------*/
/*
* REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
*/
/*---------------------------------------------------------------------------*/
JOT(4, "registering driver easycap\n");
-
-result = usb_register(&easycap_usb_driver);
-if (0 != result)
- SAY("ERROR: usb_register returned %i\n", result);
+rc = usb_register(&easycap_usb_driver);
+if (0 != rc)
+ SAY("ERROR: usb_register returned %i\n", rc);
JOT(4, "ends\n");
-return result;
+return rc;
}
/*****************************************************************************/
void __exit
--- /dev/null
+/*****************************************************************************
+* *
+* 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*/
/*****************************************************************************/
#include "easycap.h"
-#include "easycap_debug.h"
+#include "easycap_settings.h"
/*---------------------------------------------------------------------------*/
/*
--- /dev/null
+/*****************************************************************************
+* *
+* easycap_settings.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_SETTINGS_H)
+#define EASYCAP_SETTINGS_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
+
+#endif /*EASYCAP_SETTINGS_H*/
/*****************************************************************************/
#include "easycap.h"
-#include "easycap_debug.h"
#include "easycap_sound.h"
+#if defined(EASYCAP_NEEDS_ALSA)
+/*--------------------------------------------------------------------------*/
+/*
+ * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
+ */
+/*--------------------------------------------------------------------------*/
+static const struct snd_pcm_hardware alsa_hardware = {
+ .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
+ .rate_min = 32000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * \
+ AUDIO_FRAGMENT_MANY,
+ .period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
+ .period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
+ .periods_min = AUDIO_FRAGMENT_MANY,
+ .periods_max = AUDIO_FRAGMENT_MANY * 2,
+};
+
+static struct snd_pcm_ops easycap_alsa_pcm_ops = {
+ .open = easycap_alsa_open,
+ .close = easycap_alsa_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = easycap_alsa_hw_params,
+ .hw_free = easycap_alsa_hw_free,
+ .prepare = easycap_alsa_prepare,
+ .ack = easycap_alsa_ack,
+ .trigger = easycap_alsa_trigger,
+ .pointer = easycap_alsa_pointer,
+ .page = easycap_alsa_page,
+};
+
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ * THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS
+ * MEANS MODULE easycap. BEWARE.
+*/
+/*---------------------------------------------------------------------------*/
+int
+easycap_alsa_probe(struct easycap *peasycap)
+{
+int rc;
+struct snd_card *psnd_card;
+struct snd_pcm *psnd_pcm;
+
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return -ENODEV;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return -EFAULT;
+}
+if (0 > peasycap->minor) {
+ SAY("ERROR: no minor\n");
+ return -ENODEV;
+}
+
+peasycap->alsa_hardware = alsa_hardware;
+if (true == peasycap->microphone) {
+ peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
+ peasycap->alsa_hardware.rate_min = 32000;
+ peasycap->alsa_hardware.rate_max = 32000;
+} else {
+ peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
+ peasycap->alsa_hardware.rate_min = 48000;
+ peasycap->alsa_hardware.rate_max = 48000;
+}
+
+#if defined(EASYCAP_NEEDS_CARD_CREATE)
+ if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa", \
+ THIS_MODULE, 0, \
+ &psnd_card)) {
+ SAY("ERROR: Cannot do ALSA snd_card_create()\n");
+ return -EFAULT;
+ }
+#else
+ psnd_card = snd_card_new(SNDRV_DEFAULT_IDX1, "easycap_alsa", \
+ THIS_MODULE, 0);
+ if (NULL == psnd_card) {
+ SAY("ERROR: Cannot do ALSA snd_card_new()\n");
+ return -EFAULT;
+ }
+#endif /*EASYCAP_NEEDS_CARD_CREATE*/
+
+ sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
+ strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
+ strcpy(&psnd_card->shortname[0], "easycap_alsa");
+ sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
+
+ psnd_card->dev = &peasycap->pusb_device->dev;
+ psnd_card->private_data = peasycap;
+ peasycap->psnd_card = psnd_card;
+
+ rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
+ if (0 != rc) {
+ SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
+ snd_card_free(psnd_card);
+ return -EFAULT;
+ }
+
+ snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE, \
+ &easycap_alsa_pcm_ops);
+ psnd_pcm->info_flags = 0;
+ strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
+ psnd_pcm->private_data = peasycap;
+ peasycap->psnd_pcm = psnd_pcm;
+ peasycap->psubstream = (struct snd_pcm_substream *)NULL;
+
+ rc = snd_card_register(psnd_card);
+ if (0 != rc) {
+ SAM("ERROR: Cannot do ALSA snd_card_register()\n");
+ snd_card_free(psnd_card);
+ return -EFAULT;
+ } else {
+ ;
+ SAM("registered %s\n", &psnd_card->id[0]);
+ }
+return 0;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
+ * PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
+ * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
+ */
+/*---------------------------------------------------------------------------*/
+void
+easycap_alsa_complete(struct urb *purb)
+{
+struct easycap *peasycap;
+struct snd_pcm_substream *pss;
+struct snd_pcm_runtime *prt;
+int dma_bytes, fragment_bytes;
+int isfragment;
+__u8 *p1, *p2;
+__s16 s16;
+int i, j, more, much, rc;
+#if defined(UPSAMPLE)
+int k;
+__s16 oldaudio, newaudio, delta;
+#endif /*UPSAMPLE*/
+
+JOT(16, "\n");
+
+if (NULL == purb) {
+ SAY("ERROR: purb is NULL\n");
+ return;
+}
+peasycap = purb->context;
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return;
+}
+much = 0;
+if (peasycap->audio_idle) {
+ JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n", \
+ peasycap->audio_idle, peasycap->audio_isoc_streaming);
+ if (peasycap->audio_isoc_streaming)
+ goto resubmit;
+}
+/*---------------------------------------------------------------------------*/
+pss = peasycap->psubstream;
+if (NULL == pss)
+ goto resubmit;
+prt = pss->runtime;
+if (NULL == prt)
+ goto resubmit;
+dma_bytes = (int)prt->dma_bytes;
+if (0 == dma_bytes)
+ goto resubmit;
+fragment_bytes = 4 * ((int)prt->period_size);
+if (0 == fragment_bytes)
+ goto resubmit;
+/* -------------------------------------------------------------------------*/
+if (purb->status) {
+ if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
+ JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
+ return;
+ }
+ SAM("ERROR: non-zero urb status:\n");
+ switch (purb->status) {
+ case -EINPROGRESS: {
+ SAM("-EINPROGRESS\n");
+ break;
+ }
+ case -ENOSR: {
+ SAM("-ENOSR\n");
+ break;
+ }
+ case -EPIPE: {
+ SAM("-EPIPE\n");
+ break;
+ }
+ case -EOVERFLOW: {
+ SAM("-EOVERFLOW\n");
+ break;
+ }
+ case -EPROTO: {
+ SAM("-EPROTO\n");
+ break;
+ }
+ case -EILSEQ: {
+ SAM("-EILSEQ\n");
+ break;
+ }
+ case -ETIMEDOUT: {
+ SAM("-ETIMEDOUT\n");
+ break;
+ }
+ case -EMSGSIZE: {
+ SAM("-EMSGSIZE\n");
+ break;
+ }
+ case -EOPNOTSUPP: {
+ SAM("-EOPNOTSUPP\n");
+ break;
+ }
+ case -EPFNOSUPPORT: {
+ SAM("-EPFNOSUPPORT\n");
+ break;
+ }
+ case -EAFNOSUPPORT: {
+ SAM("-EAFNOSUPPORT\n");
+ break;
+ }
+ case -EADDRINUSE: {
+ SAM("-EADDRINUSE\n");
+ break;
+ }
+ case -EADDRNOTAVAIL: {
+ SAM("-EADDRNOTAVAIL\n");
+ break;
+ }
+ case -ENOBUFS: {
+ SAM("-ENOBUFS\n");
+ break;
+ }
+ case -EISCONN: {
+ SAM("-EISCONN\n");
+ break;
+ }
+ case -ENOTCONN: {
+ SAM("-ENOTCONN\n");
+ break;
+ }
+ case -ESHUTDOWN: {
+ SAM("-ESHUTDOWN\n");
+ break;
+ }
+ case -ENOENT: {
+ SAM("-ENOENT\n");
+ break;
+ }
+ case -ECONNRESET: {
+ SAM("-ECONNRESET\n");
+ break;
+ }
+ case -ENOSPC: {
+ SAM("ENOSPC\n");
+ break;
+ }
+ default: {
+ SAM("unknown error: %i\n", purb->status);
+ break;
+ }
+ }
+ goto resubmit;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * PROCEED HERE WHEN NO ERROR
+ */
+/*---------------------------------------------------------------------------*/
+
+#if defined(UPSAMPLE)
+oldaudio = peasycap->oldaudio;
+#endif /*UPSAMPLE*/
+
+for (i = 0; i < purb->number_of_packets; i++) {
+ switch (purb->iso_frame_desc[i].status) {
+ case 0: {
+ break;
+ }
+ case -ENOENT: {
+ SAM("-ENOENT\n");
+ break;
+ }
+ case -EINPROGRESS: {
+ SAM("-EINPROGRESS\n");
+ break;
+ }
+ case -EPROTO: {
+ SAM("-EPROTO\n");
+ break;
+ }
+ case -EILSEQ: {
+ SAM("-EILSEQ\n");
+ break;
+ }
+ case -ETIME: {
+ SAM("-ETIME\n");
+ break;
+ }
+ case -ETIMEDOUT: {
+ SAM("-ETIMEDOUT\n");
+ break;
+ }
+ case -EPIPE: {
+ SAM("-EPIPE\n");
+ break;
+ }
+ case -ECOMM: {
+ SAM("-ECOMM\n");
+ break;
+ }
+ case -ENOSR: {
+ SAM("-ENOSR\n");
+ break;
+ }
+ case -EOVERFLOW: {
+ SAM("-EOVERFLOW\n");
+ break;
+ }
+ case -EREMOTEIO: {
+ SAM("-EREMOTEIO\n");
+ break;
+ }
+ case -ENODEV: {
+ SAM("-ENODEV\n");
+ break;
+ }
+ case -EXDEV: {
+ SAM("-EXDEV\n");
+ break;
+ }
+ case -EINVAL: {
+ SAM("-EINVAL\n");
+ break;
+ }
+ case -ECONNRESET: {
+ SAM("-ECONNRESET\n");
+ break;
+ }
+ case -ENOSPC: {
+ SAM("-ENOSPC\n");
+ break;
+ }
+ case -ESHUTDOWN: {
+ SAM("-ESHUTDOWN\n");
+ break;
+ }
+ case -EPERM: {
+ SAM("-EPERM\n");
+ break;
+ }
+ default: {
+ SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
+ break;
+ }
+ }
+ if (!purb->iso_frame_desc[i].status) {
+ more = purb->iso_frame_desc[i].actual_length;
+ if (!more)
+ peasycap->audio_mt++;
+ else {
+ if (peasycap->audio_mt) {
+ JOM(12, "%4i empty audio urb frames\n", \
+ peasycap->audio_mt);
+ peasycap->audio_mt = 0;
+ }
+
+ p1 = (__u8 *)(purb->transfer_buffer + \
+ purb->iso_frame_desc[i].offset);
+
+/*---------------------------------------------------------------------------*/
+/*
+ * COPY more BYTES FROM ISOC BUFFER TO THE DMA BUFFER,
+ * CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
+ */
+/*---------------------------------------------------------------------------*/
+ while (more) {
+ if (0 > more) {
+ SAM("MISTAKE: more is negative\n");
+ return;
+ }
+ much = dma_bytes - peasycap->dma_fill;
+ if (0 > much) {
+ SAM("MISTAKE: much is negative\n");
+ return;
+ }
+ if (0 == much) {
+ peasycap->dma_fill = 0;
+ peasycap->dma_next = fragment_bytes;
+ JOM(8, "wrapped dma buffer\n");
+ }
+ if (false == peasycap->microphone) {
+ if (much > more)
+ much = more;
+ memcpy(prt->dma_area + \
+ peasycap->dma_fill, \
+ p1, much);
+ p1 += much;
+ more -= much;
+ } else {
+#if defined(UPSAMPLE)
+ if (much % 16)
+ JOM(8, "MISTAKE? much" \
+ " is not divisible by 16\n");
+ if (much > (16 * \
+ more))
+ much = 16 * \
+ more;
+ p2 = (__u8 *)(prt->dma_area + \
+ peasycap->dma_fill);
+
+ for (j = 0; j < (much/16); j++) {
+ newaudio = ((int) *p1) - 128;
+ newaudio = 128 * \
+ newaudio;
+
+ delta = (newaudio - oldaudio) \
+ / 4;
+ s16 = oldaudio + delta;
+
+ for (k = 0; k < 4; k++) {
+ *p2 = (0x00FF & s16);
+ *(p2 + 1) = (0xFF00 & \
+ s16) >> 8;
+ p2 += 2;
+ *p2 = (0x00FF & s16);
+ *(p2 + 1) = (0xFF00 & \
+ s16) >> 8;
+ p2 += 2;
+ s16 += delta;
+ }
+ p1++;
+ more--;
+ oldaudio = s16;
+ }
+#else /*!UPSAMPLE*/
+ if (much > (2 * more))
+ much = 2 * more;
+ p2 = (__u8 *)(prt->dma_area + \
+ peasycap->dma_fill);
+
+ for (j = 0; j < (much / 2); j++) {
+ s16 = ((int) *p1) - 128;
+ s16 = 128 * \
+ s16;
+ *p2 = (0x00FF & s16);
+ *(p2 + 1) = (0xFF00 & s16) >> \
+ 8;
+ p1++; p2 += 2;
+ more--;
+ }
+#endif /*UPSAMPLE*/
+ }
+ peasycap->dma_fill += much;
+ if (peasycap->dma_fill >= peasycap->dma_next) {
+ isfragment = peasycap->dma_fill / \
+ fragment_bytes;
+ if (0 > isfragment) {
+ SAM("MISTAKE: isfragment is " \
+ "negative\n");
+ return;
+ }
+ peasycap->dma_read = (isfragment \
+ - 1) * fragment_bytes;
+ peasycap->dma_next = (isfragment \
+ + 1) * fragment_bytes;
+ if (dma_bytes < peasycap->dma_next) {
+ peasycap->dma_next = \
+ fragment_bytes;
+ }
+ if (0 <= peasycap->dma_read) {
+ JOM(8, "snd_pcm_period_elap" \
+ "sed(), %i=" \
+ "isfragment\n", \
+ isfragment);
+ snd_pcm_period_elapsed(pss);
+ }
+ }
+ }
+ }
+ } else {
+ JOM(12, "discarding audio samples because " \
+ "%i=purb->iso_frame_desc[i].status\n", \
+ purb->iso_frame_desc[i].status);
+ }
+
+#if defined(UPSAMPLE)
+peasycap->oldaudio = oldaudio;
+#endif /*UPSAMPLE*/
+
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * RESUBMIT THIS URB
+ */
+/*---------------------------------------------------------------------------*/
+resubmit:
+if (peasycap->audio_isoc_streaming) {
+ rc = usb_submit_urb(purb, GFP_ATOMIC);
+ if (0 != rc) {
+ if ((-ENODEV != rc) && (-ENOENT != rc)) {
+ SAM("ERROR: while %i=audio_idle, " \
+ "usb_submit_urb() failed " \
+ "with rc:\n", peasycap->audio_idle);
+ }
+ switch (rc) {
+ case -ENODEV:
+ case -ENOENT:
+ break;
+ case -ENOMEM: {
+ SAM("-ENOMEM\n");
+ break;
+ }
+ case -ENXIO: {
+ SAM("-ENXIO\n");
+ break;
+ }
+ case -EINVAL: {
+ SAM("-EINVAL\n");
+ break;
+ }
+ case -EAGAIN: {
+ SAM("-EAGAIN\n");
+ break;
+ }
+ case -EFBIG: {
+ SAM("-EFBIG\n");
+ break;
+ }
+ case -EPIPE: {
+ SAM("-EPIPE\n");
+ break;
+ }
+ case -EMSGSIZE: {
+ SAM("-EMSGSIZE\n");
+ break;
+ }
+ case -ENOSPC: {
+ SAM("-ENOSPC\n");
+ break;
+ }
+ case -EPERM: {
+ SAM("-EPERM\n");
+ break;
+ }
+ default: {
+ SAM("unknown error: %i\n", rc);
+ break;
+ }
+ }
+ if (0 < peasycap->audio_isoc_streaming)
+ (peasycap->audio_isoc_streaming)--;
+ }
+}
+return;
+}
+/*****************************************************************************/
+int
+easycap_alsa_open(struct snd_pcm_substream *pss)
+{
+struct snd_pcm *psnd_pcm;
+struct snd_card *psnd_card;
+struct easycap *peasycap;
+
+JOT(4, "\n");
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+psnd_pcm = pss->pcm;
+if (NULL == psnd_pcm) {
+ SAY("ERROR: psnd_pcm is NULL\n");
+ return -EFAULT;
+}
+psnd_card = psnd_pcm->card;
+if (NULL == psnd_card) {
+ SAY("ERROR: psnd_card is NULL\n");
+ return -EFAULT;
+}
+
+peasycap = psnd_card->private_data;
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return -EFAULT;
+}
+if (peasycap->psnd_card != psnd_card) {
+ SAM("ERROR: bad peasycap->psnd_card\n");
+ return -EFAULT;
+}
+if (NULL != peasycap->psubstream) {
+ SAM("ERROR: bad peasycap->psubstream\n");
+ return -EFAULT;
+}
+pss->private_data = peasycap;
+peasycap->psubstream = pss;
+pss->runtime->hw = peasycap->alsa_hardware;
+pss->runtime->private_data = peasycap;
+pss->private_data = peasycap;
+
+if (0 != easycap_sound_setup(peasycap)) {
+ JOM(4, "ending unsuccessfully\n");
+ return -EFAULT;
+}
+JOM(4, "ending successfully\n");
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_close(struct snd_pcm_substream *pss)
+{
+struct easycap *peasycap;
+
+JOT(4, "\n");
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return -EFAULT;
+}
+pss->private_data = NULL;
+peasycap->psubstream = (struct snd_pcm_substream *)NULL;
+JOT(4, "ending successfully\n");
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_hw_params(struct snd_pcm_substream *pss, \
+ struct snd_pcm_hw_params *phw)
+{
+int rc;
+
+JOT(4, "%i\n", (params_buffer_bytes(phw)));
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
+if (0 != rc)
+ return rc;
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
+{
+struct snd_pcm_runtime *prt;
+JOT(4, "\n");
+
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+prt = pss->runtime;
+if (NULL == prt) {
+ SAY("ERROR: substream.runtime is NULL\n");
+ return -EFAULT;
+}
+if (prt->dma_area) {
+ if (prt->dma_bytes > sz)
+ return 0;
+ vfree(prt->dma_area);
+}
+prt->dma_area = vmalloc(sz);
+if (NULL == prt->dma_area)
+ return -ENOMEM;
+prt->dma_bytes = sz;
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_hw_free(struct snd_pcm_substream *pss)
+{
+struct snd_pcm_runtime *prt;
+JOT(4, "\n");
+
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+prt = pss->runtime;
+if (NULL == prt) {
+ SAY("ERROR: substream.runtime is NULL\n");
+ return -EFAULT;
+}
+if (NULL != prt->dma_area) {
+ JOT(8, "0x%08lX=prt->dma_area\n", (unsigned long int)prt->dma_area);
+ vfree(prt->dma_area);
+ prt->dma_area = NULL;
+} else
+ JOT(8, "dma_area already freed\n");
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_prepare(struct snd_pcm_substream *pss)
+{
+struct easycap *peasycap;
+struct snd_pcm_runtime *prt;
+
+JOT(4, "\n");
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+prt = pss->runtime;
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return -EFAULT;
+}
+
+JOM(16, "ALSA decides %8i Hz=rate\n", (int)pss->runtime->rate);
+JOM(16, "ALSA decides %8i =period_size\n", (int)pss->runtime->period_size);
+JOM(16, "ALSA decides %8i =periods\n", (int)pss->runtime->periods);
+JOM(16, "ALSA decides %8i =buffer_size\n", (int)pss->runtime->buffer_size);
+JOM(16, "ALSA decides %8i =dma_bytes\n", (int)pss->runtime->dma_bytes);
+JOM(16, "ALSA decides %8i =boundary\n", (int)pss->runtime->boundary);
+JOM(16, "ALSA decides %8i =period_step\n", (int)pss->runtime->period_step);
+JOM(16, "ALSA decides %8i =sample_bits\n", (int)pss->runtime->sample_bits);
+JOM(16, "ALSA decides %8i =frame_bits\n", (int)pss->runtime->frame_bits);
+JOM(16, "ALSA decides %8i =min_align\n", (int)pss->runtime->min_align);
+JOM(12, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
+JOM(12, "ALSA decides %8i =hw_ptr_interrupt\n", \
+ (int)pss->runtime->hw_ptr_interrupt);
+if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
+ SAY("MISTAKE: unexpected ALSA parameters\n");
+ return -ENOENT;
+}
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_ack(struct snd_pcm_substream *pss)
+{
+return 0;
+}
+/*****************************************************************************/
+int
+easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
+{
+struct easycap *peasycap;
+int retval;
+
+JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START, \
+ SNDRV_PCM_TRIGGER_STOP);
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return -EFAULT;
+}
+
+switch (cmd) {
+case SNDRV_PCM_TRIGGER_START: {
+ peasycap->audio_idle = 0;
+ break;
+}
+case SNDRV_PCM_TRIGGER_STOP: {
+ peasycap->audio_idle = 1;
+ break;
+}
+default:
+ retval = -EINVAL;
+}
+return 0;
+}
+/*****************************************************************************/
+snd_pcm_uframes_t
+easycap_alsa_pointer(struct snd_pcm_substream *pss)
+{
+struct easycap *peasycap;
+snd_pcm_uframes_t offset;
+
+JOT(16, "\n");
+if (NULL == pss) {
+ SAY("ERROR: pss is NULL\n");
+ return -EFAULT;
+}
+peasycap = snd_pcm_substream_chip(pss);
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL\n");
+ return -EFAULT;
+}
+if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+ SAY("ERROR: bad peasycap\n");
+ return -EFAULT;
+}
+if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
+ JOM(8, "returning -EIO because " \
+ "%i=audio_idle %i=audio_eof\n", \
+ peasycap->audio_idle, peasycap->audio_eof);
+ return -EIO;
+}
+/*---------------------------------------------------------------------------*/
+if (0 > peasycap->dma_read) {
+ JOM(8, "returning -EBUSY\n");
+ return -EBUSY;
+}
+offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
+JOM(8, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
+JOM(8, "ALSA decides %8i =hw_ptr_interrupt\n", \
+ (int)pss->runtime->hw_ptr_interrupt);
+JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n", \
+ (int)offset, peasycap->dma_read, peasycap->dma_next);
+return offset;
+}
+/*****************************************************************************/
+struct page *
+easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
+{
+return vmalloc_to_page(pss->runtime->dma_area + offset);
+}
+/*****************************************************************************/
+
+#else /*!EASYCAP_NEEDS_ALSA*/
+
+/*****************************************************************************/
+/**************************** **************************/
+/**************************** Open Sound System **************************/
+/**************************** **************************/
+/*****************************************************************************/
+/*--------------------------------------------------------------------------*/
+/*
+ * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
+ */
+/*--------------------------------------------------------------------------*/
+const struct file_operations easyoss_fops = {
+ .owner = THIS_MODULE,
+ .open = easyoss_open,
+ .release = easyoss_release,
+#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
+ .unlocked_ioctl = easyoss_ioctl_noinode,
+#else
+ .ioctl = easyoss_ioctl,
+#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
+ .read = easyoss_read,
+ .llseek = no_llseek,
+};
+struct usb_class_driver easyoss_class = {
+.name = "usb/easyoss%d",
+.fops = &easyoss_fops,
+.minor_base = USB_SKEL_MINOR_BASE,
+};
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
*/
/*---------------------------------------------------------------------------*/
void
-easysnd_complete(struct urb *purb)
+easyoss_complete(struct urb *purb)
{
struct easycap *peasycap;
struct data_buffer *paudio_buffer;
SAY("ERROR: bad peasycap\n");
return;
}
-
much = 0;
-
if (peasycap->audio_idle) {
JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n", \
peasycap->audio_idle, peasycap->audio_isoc_streaming);
if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) {
- if (-ENODEV != rc)
+ if (-ENODEV != rc && -ENOENT != rc) {
SAM("ERROR: while %i=audio_idle, " \
"usb_submit_urb() failed with rc:\n", \
peasycap->audio_idle);
+ }
switch (rc) {
+ case -ENODEV:
+ case -ENOENT:
+ break;
case -ENOMEM: {
SAM("-ENOMEM\n");
break;
}
- case -ENODEV: {
- break;
- }
case -ENXIO: {
SAM("-ENXIO\n");
break;
SAM("-ENOSPC\n");
break;
}
+ case -EPERM: {
+ SAM("-EPERM\n");
+ break;
+ }
default: {
- SAM("unknown error: 0x%08X\n", rc);
+ SAM("unknown error: %i\n", rc);
break;
}
}
SAM("ENOSPC\n");
break;
}
- default: {
- SAM("unknown error code 0x%08X\n", purb->status);
+ case -EPERM: {
+ SAM("-EPERM\n");
break;
}
+ default: {
+ SAM("unknown error: %i\n", purb->status);
+ break;
}
-/*---------------------------------------------------------------------------*/
-/*
- * RESUBMIT THIS URB AFTER AN ERROR
- *
- * (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH)
- */
-/*---------------------------------------------------------------------------*/
- if (peasycap->audio_isoc_streaming) {
- rc = usb_submit_urb(purb, GFP_ATOMIC);
- if (0 != rc) {
- SAM("ERROR: while %i=audio_idle, usb_submit_urb() "
- "failed with rc:\n", peasycap->audio_idle);
- switch (rc) {
- case -ENOMEM: {
- SAM("-ENOMEM\n");
- break;
- }
- case -ENODEV: {
- SAM("-ENODEV\n");
- break;
- }
- case -ENXIO: {
- SAM("-ENXIO\n");
- break;
- }
- case -EINVAL: {
- SAM("-EINVAL\n");
- break;
- }
- case -EAGAIN: {
- SAM("-EAGAIN\n");
- break;
- }
- case -EFBIG: {
- SAM("-EFBIG\n");
- break;
- }
- case -EPIPE: {
- SAM("-EPIPE\n");
- break;
- }
- case -EMSGSIZE: {
- SAM("-EMSGSIZE\n");
- break;
- }
- default: {
- SAM("0x%08X\n", rc); break;
- }
- }
- }
}
- return;
+ goto resubmit;
}
/*---------------------------------------------------------------------------*/
/*
case 0: {
break;
}
+ case -ENODEV: {
+ SAM("-ENODEV\n");
+ break;
+ }
case -ENOENT: {
SAM("-ENOENT\n");
break;
SAM("-EREMOTEIO\n");
break;
}
- case -ENODEV: {
- SAM("-ENODEV\n");
- break;
- }
case -EXDEV: {
SAM("-EXDEV\n");
break;
SAM("-ESHUTDOWN\n");
break;
}
+ case -EPERM: {
+ SAM("-EPERM\n");
+ break;
+ }
default: {
- SAM("unknown error:0x%08X\n", purb->iso_frame_desc[i].status);
+ SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
break;
}
}
peasycap->audio_mt++;
else {
if (peasycap->audio_mt) {
- JOM(16, "%4i empty audio urb frames\n", \
+ JOM(12, "%4i empty audio urb frames\n", \
peasycap->audio_mt);
peasycap->audio_mt = 0;
}
/*---------------------------------------------------------------------------*/
while (more) {
if (0 > more) {
- SAM("easysnd_complete: MISTAKE: " \
- "more is negative\n");
+ SAM("MISTAKE: more is negative\n");
return;
}
if (peasycap->audio_buffer_page_many <= \
paudio_buffer->pgo)) {
#if defined(TESTTONE)
- easysnd_testtone(peasycap, \
+ easyoss_testtone(peasycap, \
peasycap->audio_fill);
#endif /*TESTTONE*/
peasycap->audio_fill)
peasycap->audio_fill = 0;
- JOM(12, "bumped peasycap->" \
+ JOM(8, "bumped peasycap->" \
"audio_fill to %i\n", \
peasycap->audio_fill);
more--;
oldaudio = s16;
}
-#else
+#else /*!UPSAMPLE*/
if (much > (2 * more))
much = 2 * more;
p2 = (__u8 *)paudio_buffer->pto;
}
/*---------------------------------------------------------------------------*/
/*
- * RESUBMIT THIS URB AFTER NO ERROR
+ * RESUBMIT THIS URB
*/
/*---------------------------------------------------------------------------*/
+resubmit:
if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (0 != rc) {
- if (-ENODEV != rc) {
+ if (-ENODEV != rc && -ENOENT != rc) {
SAM("ERROR: while %i=audio_idle, " \
- "usb_submit_urb() failed " \
- "with rc:\n", peasycap->audio_idle);
+ "usb_submit_urb() failed " \
+ "with rc:\n", peasycap->audio_idle);
}
switch (rc) {
+ case -ENODEV:
+ case -ENOENT:
+ break;
case -ENOMEM: {
SAM("-ENOMEM\n");
break;
}
- case -ENODEV: {
- break;
- }
case -ENXIO: {
SAM("-ENXIO\n");
break;
SAM("-ENOSPC\n");
break;
}
+ case -EPERM: {
+ SAM("-EPERM\n");
+ break;
+ }
default: {
- SAM("unknown error: 0x%08X\n", rc);
+ SAM("unknown error: %i\n", rc);
break;
}
}
/*---------------------------------------------------------------------------*/
/*
* THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
- * STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
+ * STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
* HAVE AN IOCTL INTERFACE.
*/
/*---------------------------------------------------------------------------*/
int
-easysnd_open(struct inode *inode, struct file *file)
+easyoss_open(struct inode *inode, struct file *file)
{
struct usb_interface *pusb_interface;
struct easycap *peasycap;
-int subminor, rc;
+int subminor;
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
file->private_data = peasycap;
-/*---------------------------------------------------------------------------*/
-/*
- * INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-JOM(4, "starting initialization\n");
-
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device is NULL\n");
- return -ENODEV;
-}
-JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
-
-rc = audio_setup(peasycap);
-if (0 <= rc)
- JOM(8, "audio_setup() returned %i\n", rc);
-else
- JOM(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc);
-
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device has become NULL\n");
- return -ENODEV;
-}
-/*---------------------------------------------------------------------------*/
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
- SAM("ERROR: peasycap->pusb_device has become NULL\n");
- return -ENODEV;
+if (0 != easycap_sound_setup(peasycap)) {
+ ;
+ ;
}
-rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
- peasycap->audio_altsetting_on);
-JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
- peasycap->audio_altsetting_on, rc);
-
-rc = wakeup_device(peasycap->pusb_device);
-if (0 == rc)
- JOM(8, "wakeup_device() returned %i\n", rc);
-else
- JOM(8, "ERROR: wakeup_device() returned %i\n", rc);
-
-peasycap->audio_eof = 0;
-peasycap->audio_idle = 0;
-
-peasycap->timeval1.tv_sec = 0;
-peasycap->timeval1.tv_usec = 0;
-
-submit_audio_urbs(peasycap);
-
-JOM(4, "finished initialization\n");
return 0;
}
/*****************************************************************************/
int
-easysnd_release(struct inode *inode, struct file *file)
+easyoss_release(struct inode *inode, struct file *file)
{
struct easycap *peasycap;
}
/*****************************************************************************/
ssize_t
-easysnd_read(struct file *file, char __user *puserspacebuffer, \
+easyoss_read(struct file *file, char __user *puserspacebuffer, \
size_t kount, loff_t *poff)
{
struct timeval timeval;
*/
/*---------------------------------------------------------------------------*/
-JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
+JOT(8, "%5i=kount %5i=*poff\n", (int)kount, (int)(*poff));
if (NULL == file) {
SAY("ERROR: file is NULL\n");
}
peasycap = file->private_data;
if (NULL == peasycap) {
- SAY("ERROR in easysnd_read(): peasycap is NULL\n");
+ SAY("ERROR in easyoss_read(): peasycap is NULL\n");
return -EFAULT;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
return -EFAULT;
}
if (NULL == peasycap->pusb_device) {
- SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n");
+ SAY("ERROR: peasycap->pusb_device is NULL\n");
return -EFAULT;
}
kd = isdongle(peasycap);
if (0 <= kd && DONGLE_MANY > kd) {
- if (mutex_lock_interruptible(&(easycap_dongle[kd].mutex_audio))) {
- SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
+ if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
+ SAY("ERROR: "
+ "cannot lock easycapdc60_dongle[%i].mutex_audio\n", kd);
return -ERESTARTSYS;
}
- JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
+ JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
/*---------------------------------------------------------------------------*/
/*
* MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
return -ERESTARTSYS;
if (NULL == file) {
SAY("ERROR: file is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
peasycap = file->private_data;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap: 0x%08lX\n", \
(unsigned long int) peasycap);
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
if (NULL == peasycap->pusb_device) {
SAM("ERROR: peasycap->pusb_device is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
} else {
if ((0 > peasycap->audio_read) || \
(peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
SAM("ERROR: peasycap->audio_read out of range\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
if ((struct data_buffer *)NULL == pdata_buffer) {
SAM("ERROR: pdata_buffer is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
JOM(12, "before wait, %i=frag read %i=frag fill\n", \
(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
if (file->f_flags & O_NONBLOCK) {
JOM(16, "returning -EAGAIN as instructed\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EAGAIN;
}
rc = wait_event_interruptible(peasycap->wq_audio, \
(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
if (0 != rc) {
SAM("aborted by signal\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
if (peasycap->audio_eof) {
JOM(8, "returning 0 because %i=audio_eof\n", \
peasycap->audio_eof);
kill_audio_urbs(peasycap);
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0;
}
if (peasycap->audio_idle) {
JOM(16, "returning 0 because %i=audio_idle\n", \
peasycap->audio_idle);
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0;
}
if (!peasycap->audio_isoc_streaming) {
JOM(16, "returning 0 because audio urbs not streaming\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return 0;
}
}
(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
szret = (size_t)0;
+fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
while (fragment == (peasycap->audio_read / \
peasycap->audio_pages_per_fragment)) {
if (NULL == pdata_buffer->pgo) {
SAM("ERROR: pdata_buffer->pgo is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
if (NULL == pdata_buffer->pto) {
SAM("ERROR: pdata_buffer->pto is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
if (0 > kount1) {
- SAM("easysnd_read: MISTAKE: kount1 is negative\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ SAM("MISTAKE: kount1 is negative\n");
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -ERESTARTSYS;
}
if (!kount1) {
(peasycap->audio_buffer_page_many <= \
peasycap->audio_read)) {
SAM("ERROR: peasycap->audio_read out of range\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
if ((struct data_buffer *)NULL == pdata_buffer) {
SAM("ERROR: pdata_buffer is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
if (NULL == pdata_buffer->pgo) {
SAM("ERROR: pdata_buffer->pgo is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
if (NULL == pdata_buffer->pto) {
SAM("ERROR: pdata_buffer->pto is NULL\n");
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
if (0 != rc) {
SAM("ERROR: copy_to_user() returned %li\n", rc);
- mutex_unlock(&easycap_dongle[kd].mutex_audio);
+ mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
return -EFAULT;
}
*poff += (loff_t)more;
JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
peasycap->dnbydt = sdr.quotient;
+mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
JOM(8, "returning %li\n", (long int)szret);
-mutex_unlock(&easycap_dongle[kd].mutex_audio);
return szret;
}
/*****************************************************************************/
+
+#endif /*!EASYCAP_NEEDS_ALSA*/
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ * COMMON AUDIO INITIALIZATION
+ */
+/*---------------------------------------------------------------------------*/
+int
+easycap_sound_setup(struct easycap *peasycap)
+{
+int rc;
+
+JOM(4, "starting initialization\n");
+
+if (NULL == peasycap) {
+ SAY("ERROR: peasycap is NULL.\n");
+ return -EFAULT;
+}
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+ SAM("ERROR: peasycap->pusb_device is NULL\n");
+ return -ENODEV;
+}
+JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
+
+rc = audio_setup(peasycap);
+JOM(8, "audio_setup() returned %i\n", rc);
+
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+ SAM("ERROR: peasycap->pusb_device has become NULL\n");
+ return -ENODEV;
+}
+/*---------------------------------------------------------------------------*/
+if ((struct usb_device *)NULL == peasycap->pusb_device) {
+ SAM("ERROR: peasycap->pusb_device has become NULL\n");
+ return -ENODEV;
+}
+rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
+ peasycap->audio_altsetting_on);
+JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
+ peasycap->audio_altsetting_on, rc);
+
+rc = wakeup_device(peasycap->pusb_device);
+JOM(8, "wakeup_device() returned %i\n", rc);
+
+peasycap->audio_eof = 0;
+peasycap->audio_idle = 0;
+
+peasycap->timeval1.tv_sec = 0;
+peasycap->timeval1.tv_usec = 0;
+
+submit_audio_urbs(peasycap);
+
+JOM(4, "finished initialization\n");
+return 0;
+}
+/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* SUBMIT ALL AUDIO URBS.
peasycap->audio_isoc_buffer[isbuf].pgo;
purb->transfer_buffer_length = \
peasycap->audio_isoc_buffer_size;
- purb->complete = easysnd_complete;
+#if defined(EASYCAP_NEEDS_ALSA)
+ purb->complete = easycap_alsa_complete;
+#else
+ purb->complete = easyoss_complete;
+#endif /*EASYCAP_NEEDS_ALSA*/
purb->context = peasycap;
purb->start_frame = 0;
purb->number_of_packets = \
SAM("ERROR: usb_submit_urb() failed" \
" for urb with rc:\n");
switch (rc) {
- case -ENOMEM: {
- SAM("-ENOMEM\n");
- break;
- }
case -ENODEV: {
SAM("-ENODEV\n");
break;
}
+ case -ENOENT: {
+ SAM("-ENOENT\n");
+ break;
+ }
+ case -ENOMEM: {
+ SAM("-ENOMEM\n");
+ break;
+ }
case -ENXIO: {
SAM("-ENXIO\n");
break;
nospc++;
break;
}
+ case -EPERM: {
+ SAM("-EPERM\n");
+ break;
+ }
default: {
- SAM("unknown error code %i\n",\
- rc);
+ SAM("unknown error: %i\n", rc);
break;
}
}
}
peasycap->audio_isoc_streaming = 0;
} else {
- peasycap->audio_isoc_streaming = 1;
+ peasycap->audio_isoc_streaming = m;
JOM(4, "submitted %i audio urbs\n", m);
}
} else
*
*/
/*****************************************************************************/
+#if !defined(EASYCAP_SOUND_H)
+#define EASYCAP_SOUND_H
+
+extern int easycap_debug;
+extern int easycap_gain;
+extern struct easycap_dongle easycapdc60_dongle[];
extern struct easycap *peasycap;
extern struct usb_driver easycap_usb_driver;
+#if defined(EASYCAP_NEEDS_ALSA)
+extern struct snd_pcm_hardware easycap_pcm_hardware;
+#else
+extern struct usb_class_driver easyoss_class;
+extern const struct file_operations easyoss_fops;
+#endif /*EASYCAP_NEEDS_ALSA*/
+
+#endif /*EASYCAP_SOUND_H*/
+++ /dev/null
-/*****************************************************************************
-* *
-* easycap_standard.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
- *
-*/
-/*****************************************************************************/
-extern struct easycap_standard easycap_standard[];
/*****************************************************************************/
#include "easycap.h"
-#include "easycap_debug.h"
+#include "easycap_testcard.h"
/*****************************************************************************/
#define TESTCARD_BYTESPERLINE (2 * 720)
};
/*****************************************************************************/
void
-easysnd_testtone(struct easycap *peasycap, int audio_fill)
+easyoss_testtone(struct easycap *peasycap, int audio_fill)
{
int i1;
unsigned char *p2;
--- /dev/null
+/*****************************************************************************
+* *
+* 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*/