/******************************************************************************
* *
* easycap_sound.c *
* *
* Audio driver for EasyCAP USB2.0 Video Capture Device DC60 *
* *
* *
******************************************************************************/
/*
*
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
*
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*****************************************************************************/
#include "easycap.h"
/*****************************************************************************/
/**************************** **************************/
/**************************** Open Sound System **************************/
/**************************** **************************/
/*****************************************************************************/
/*--------------------------------------------------------------------------*/
/*
* PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
*/
/*--------------------------------------------------------------------------*/
/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*
* ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
* PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
* IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
*/
/*---------------------------------------------------------------------------*/
void
easyoss_complete(struct urb *purb)
{
struct easycap *peasycap;
struct data_buffer *paudio_buffer;
u8 *p1, *p2;
s16 tmp;
int i, j, more, much, leap, rc;
#ifdef UPSAMPLE
int k;
s16 oldaudio, newaudio, delta;
#endif /*UPSAMPLE*/
JOT(16, "\n");
if (NULL == purb) {
SAY("ERROR: purb is NULL\n");
return;
}
peasycap = purb->context;
if (NULL == peasycap) {
SAY("ERROR: peasycap is NULL\n");
return;
}
if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
SAY("ERROR: bad peasycap\n");
return;
}
much = 0;
if (peasycap->audio_idle) {
JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n",
peasycap->audio_idle, peasycap->audio_isoc_streaming);
if (peasycap->audio_isoc_streaming) {
rc = usb_submit_urb(purb, GFP_ATOMIC);
if (rc) {
if (-ENODEV != rc && -ENOENT != rc) {
SAM("ERROR: while %i=audio_idle, "
"usb_submit_urb() failed with rc: -%s: %d\n",
peasycap->audio_idle,
strerror(rc), rc);
}
}
}
return;
}
/*---------------------------------------------------------------------------*/
if (purb->status) {
if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
return;
}
SAM("ERROR: non-zero urb status: -%s: %d\n",
strerror(purb->status), purb->status);
goto resubmit;
}
/*---------------------------------------------------------------------------*/
/*
* PROCEED HERE WHEN NO ERROR
*/
/*---------------------------------------------------------------------------*/
#ifdef UPSAMPLE
oldaudio = peasycap->oldaudio;
#endif /*UPSAMPLE*/
for (i = 0; i < purb->number_of_packets; i++) {
if (!purb->iso_frame_desc[i].status) {
SAM("-%s\n", strerror(purb->iso_frame_desc[i].status));
more = purb->iso_frame_desc[i].actual_length;
#ifdef TESTTONE
if (!more)
more = purb->iso_frame_desc[i].length;
#endif
if (!more)
peasycap->audio_mt++;
else {
if (peasycap->audio_mt) {
JOM(12, "%4i empty audio urb frames\n",
peasycap->audio_mt);
peasycap->audio_mt = 0;
}
p1 = (u8 *)(purb->transfer_buffer +
purb->iso_frame_desc[i].offset);
leap = 0;
p1 += leap;
more -= leap;
/*---------------------------------------------------------------------------*/
/*
* COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
* CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
*/
/*---------------------------------------------------------------------------*/
while (more) {
if (0 > more) {
SAM("MISTAKE: more is negative\n");
return;
}
if (peasycap->audio_buffer_page_many <=
peasycap->audio_fill) {
SAM("ERROR: bad "
"peasycap->audio_fill\n");
return;
}
paudio_buffer = &peasycap->audio_buffer
[peasycap->audio_fill];
if