diff options
Diffstat (limited to 'drivers/staging/easycap/easycap_sound.c')
-rw-r--r-- | drivers/staging/easycap/easycap_sound.c | 1385 |
1 files changed, 517 insertions, 868 deletions
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c index 24d8bb4..626450a 100644 --- a/drivers/staging/easycap/easycap_sound.c +++ b/drivers/staging/easycap/easycap_sound.c @@ -29,28 +29,55 @@ /*****************************************************************************/ #include "easycap.h" -#include "easycap_debug.h" -#include "easycap_sound.h" + +#ifndef CONFIG_EASYCAP_OSS +/*--------------------------------------------------------------------------*/ +/* + * 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, +}; + /*****************************************************************************/ /*---------------------------------------------------------------------------*/ /* - * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS + * 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 -easysnd_complete(struct urb *purb) +easycap_alsa_complete(struct urb *purb) { struct easycap *peasycap; -struct data_buffer *paudio_buffer; -__u8 *p1, *p2; -__s16 s16; -int i, j, more, much, leap, rc; -#if defined(UPSAMPLE) +struct snd_pcm_substream *pss; +struct snd_pcm_runtime *prt; +int dma_bytes, fragment_bytes; +int isfragment; +u8 *p1, *p2; +s16 tmp; +int i, j, more, much, rc; +#ifdef UPSAMPLE int k; -__s16 oldaudio, newaudio, delta; +s16 oldaudio, newaudio, delta; #endif /*UPSAMPLE*/ JOT(16, "\n"); @@ -68,970 +95,630 @@ 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", \ + 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) - 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: { - 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; - } - default: { - SAM("unknown error: 0x%08X\n", rc); - break; - } - } - } - } -return; -} -/*---------------------------------------------------------------------------*/ + 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 code 0x%08X\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; + SAM("ERROR: non-zero urb status: -%s: %d\n", + strerror(purb->status), purb->status); + goto resubmit; } /*---------------------------------------------------------------------------*/ /* * PROCEED HERE WHEN NO ERROR */ /*---------------------------------------------------------------------------*/ -#if defined(UPSAMPLE) + +#ifdef 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; - } - default: { - SAM("unknown error:0x%08X\n", purb->iso_frame_desc[i].status); - break; - } + if (purb->iso_frame_desc[i].status < 0) { + SAM("-%s: %d\n", + strerror(purb->iso_frame_desc[i].status), + purb->iso_frame_desc[i].status); } if (!purb->iso_frame_desc[i].status) { more = purb->iso_frame_desc[i].actual_length; - -#if defined(TESTTONE) - if (!more) - more = purb->iso_frame_desc[i].length; -#endif - if (!more) peasycap->audio_mt++; else { if (peasycap->audio_mt) { - JOM(16, "%4i empty audio urb frames\n", \ + JOM(12, "%4i empty audio urb frames\n", peasycap->audio_mt); peasycap->audio_mt = 0; } - p1 = (__u8 *)(purb->transfer_buffer + \ + 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, + * 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("easysnd_complete: MISTAKE: " \ - "more is negative\n"); + SAM("MISTAKE: more is negative\n"); return; } - if (peasycap->audio_buffer_page_many <= \ - peasycap->audio_fill) { - SAM("ERROR: bad " \ - "peasycap->audio_fill\n"); + much = dma_bytes - peasycap->dma_fill; + if (0 > much) { + SAM("MISTAKE: much is negative\n"); return; } - - paudio_buffer = &peasycap->audio_buffer\ - [peasycap->audio_fill]; - if (PAGE_SIZE < (paudio_buffer->pto - \ - paudio_buffer->pgo)) { - SAM("ERROR: bad paudio_buffer->pto\n"); - return; - } - if (PAGE_SIZE == (paudio_buffer->pto - \ - paudio_buffer->pgo)) { - -#if defined(TESTTONE) - easysnd_testtone(peasycap, \ - peasycap->audio_fill); -#endif /*TESTTONE*/ - - paudio_buffer->pto = \ - paudio_buffer->pgo; - (peasycap->audio_fill)++; - if (peasycap->\ - audio_buffer_page_many <= \ - peasycap->audio_fill) - peasycap->audio_fill = 0; - - JOM(12, "bumped peasycap->" \ - "audio_fill to %i\n", \ - peasycap->audio_fill); - - paudio_buffer = &peasycap->\ - audio_buffer\ - [peasycap->audio_fill]; - paudio_buffer->pto = \ - paudio_buffer->pgo; - - if (!(peasycap->audio_fill % \ - peasycap->\ - audio_pages_per_fragment)) { - JOM(12, "wakeup call on wq_" \ - "audio, %i=frag reading %i" \ - "=fragment fill\n", \ - (peasycap->audio_read / \ - peasycap->\ - audio_pages_per_fragment), \ - (peasycap->audio_fill / \ - peasycap->\ - audio_pages_per_fragment)); - wake_up_interruptible\ - (&(peasycap->wq_audio)); - } + if (0 == much) { + peasycap->dma_fill = 0; + peasycap->dma_next = fragment_bytes; + JOM(8, "wrapped dma buffer\n"); } - - much = PAGE_SIZE - (int)(paudio_buffer->pto -\ - paudio_buffer->pgo); - if (false == peasycap->microphone) { if (much > more) much = more; - - memcpy(paudio_buffer->pto, p1, much); + memcpy(prt->dma_area + + peasycap->dma_fill, + p1, much); p1 += much; more -= much; } else { -#if defined(UPSAMPLE) +#ifdef UPSAMPLE if (much % 16) - JOM(8, "MISTAKE? much" \ + JOM(8, "MISTAKE? much" " is not divisible by 16\n"); - if (much > (16 * \ + if (much > (16 * more)) - much = 16 * \ + much = 16 * more; - p2 = (__u8 *)paudio_buffer->pto; + p2 = (u8 *)(prt->dma_area + + peasycap->dma_fill); for (j = 0; j < (much/16); j++) { newaudio = ((int) *p1) - 128; - newaudio = 128 * \ + newaudio = 128 * newaudio; - delta = (newaudio - oldaudio) \ + delta = (newaudio - oldaudio) / 4; - s16 = oldaudio + delta; + tmp = oldaudio + delta; for (k = 0; k < 4; k++) { - *p2 = (0x00FF & s16); - *(p2 + 1) = (0xFF00 & \ - s16) >> 8; + *p2 = (0x00FF & tmp); + *(p2 + 1) = (0xFF00 & + tmp) >> 8; p2 += 2; - *p2 = (0x00FF & s16); - *(p2 + 1) = (0xFF00 & \ - s16) >> 8; + *p2 = (0x00FF & tmp); + *(p2 + 1) = (0xFF00 & + tmp) >> 8; p2 += 2; - - s16 += delta; + tmp += delta; } p1++; more--; - oldaudio = s16; + oldaudio = tmp; } -#else +#else /*!UPSAMPLE*/ if (much > (2 * more)) much = 2 * more; - p2 = (__u8 *)paudio_buffer->pto; + 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) >> \ + tmp = ((int) *p1) - 128; + tmp = 128 * tmp; + *p2 = (0x00FF & tmp); + *(p2 + 1) = (0xFF00 & tmp) >> 8; p1++; p2 += 2; more--; } #endif /*UPSAMPLE*/ } - (paudio_buffer->pto) += much; + 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", \ + JOM(12, "discarding audio samples because " + "%i=purb->iso_frame_desc[i].status\n", purb->iso_frame_desc[i].status); } -#if defined(UPSAMPLE) +#ifdef UPSAMPLE peasycap->oldaudio = oldaudio; #endif /*UPSAMPLE*/ } /*---------------------------------------------------------------------------*/ /* - * 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) { - 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: { - 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; - } - default: { - SAM("unknown error: 0x%08X\n", rc); - break; - } + 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); } + if (0 < peasycap->audio_isoc_streaming) + (peasycap->audio_isoc_streaming)--; } } return; } /*****************************************************************************/ -/*---------------------------------------------------------------------------*/ -/* - * 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 - * HAVE AN IOCTL INTERFACE. - */ -/*---------------------------------------------------------------------------*/ -int -easysnd_open(struct inode *inode, struct file *file) +static int easycap_alsa_open(struct snd_pcm_substream *pss) { -struct usb_interface *pusb_interface; +struct snd_pcm *psnd_pcm; +struct snd_card *psnd_card; struct easycap *peasycap; -int subminor, rc; -/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -#if defined(EASYCAP_IS_VIDEODEV_CLIENT) -#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) -struct v4l2_device *pv4l2_device; -#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ -#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -JOT(4, "begins\n"); - -subminor = iminor(inode); - -pusb_interface = usb_find_interface(&easycap_usb_driver, subminor); -if (NULL == pusb_interface) { - SAY("ERROR: pusb_interface is NULL\n"); - SAY("ending unsuccessfully\n"); - return -1; +JOT(4, "\n"); +if (NULL == pss) { + SAY("ERROR: pss is NULL\n"); + return -EFAULT; } -peasycap = usb_get_intfdata(pusb_interface); +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"); - SAY("ending unsuccessfully\n"); - return -1; + SAY("ERROR: peasycap is NULL\n"); + return -EFAULT; } -/*---------------------------------------------------------------------------*/ -#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) -# -/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ -#else -#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) -/*---------------------------------------------------------------------------*/ -/* - * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS - * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(), - * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE. - * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED. -*/ -/*---------------------------------------------------------------------------*/ if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { - pv4l2_device = usb_get_intfdata(pusb_interface); - if ((struct v4l2_device *)NULL == pv4l2_device) { - SAY("ERROR: pv4l2_device is NULL\n"); - return -EFAULT; - } - peasycap = (struct easycap *) \ - container_of(pv4l2_device, struct easycap, v4l2_device); + SAY("ERROR: bad peasycap\n"); + return -EFAULT; } -#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ -# -#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ -/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ -/*---------------------------------------------------------------------------*/ -if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { - SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); +if (peasycap->psnd_card != psnd_card) { + SAM("ERROR: bad peasycap->psnd_card\n"); return -EFAULT; } -/*---------------------------------------------------------------------------*/ - -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; +if (NULL != peasycap->psubstream) { + SAM("ERROR: bad peasycap->psubstream\n"); + return -EFAULT; } -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); +pss->private_data = peasycap; +peasycap->psubstream = pss; +pss->runtime->hw = peasycap->alsa_hardware; +pss->runtime->private_data = peasycap; +pss->private_data = peasycap; -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)) { + JOM(4, "ending unsuccessfully\n"); + return -EFAULT; } -/*---------------------------------------------------------------------------*/ -if ((struct usb_device *)NULL == peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device has become NULL\n"); - return -ENODEV; +JOM(4, "ending successfully\n"); +return 0; } -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); +/*****************************************************************************/ +static int easycap_alsa_close(struct snd_pcm_substream *pss) +{ +struct easycap *peasycap; -peasycap->audio_eof = 0; -peasycap->audio_idle = 0; +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 = NULL; +JOT(4, "ending successfully\n"); +return 0; +} +/*****************************************************************************/ +static int easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz) +{ +struct snd_pcm_runtime *prt; +JOT(4, "\n"); -peasycap->timeval1.tv_sec = 0; -peasycap->timeval1.tv_usec = 0; +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; +} +/*****************************************************************************/ +static int easycap_alsa_hw_params(struct snd_pcm_substream *pss, + struct snd_pcm_hw_params *phw) +{ +int rc; -submit_audio_urbs(peasycap); +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 (rc) + return rc; +return 0; +} +/*****************************************************************************/ +static int easycap_alsa_hw_free(struct snd_pcm_substream *pss) +{ +struct snd_pcm_runtime *prt; +JOT(4, "\n"); -JOM(4, "finished initialization\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 -easysnd_release(struct inode *inode, struct file *file) +static int easycap_alsa_prepare(struct snd_pcm_substream *pss) { struct easycap *peasycap; +struct snd_pcm_runtime *prt; -JOT(4, "begins\n"); - -peasycap = file->private_data; +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"); + SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { - SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + SAY("ERROR: bad peasycap\n"); return -EFAULT; } -if (0 != kill_audio_urbs(peasycap)) { - SAM("ERROR: kill_audio_urbs() failed\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; } -JOM(4, "ending successfully\n"); return 0; } /*****************************************************************************/ -ssize_t -easysnd_read(struct file *file, char __user *puserspacebuffer, \ - size_t kount, loff_t *poff) +static int easycap_alsa_ack(struct snd_pcm_substream *pss) +{ + return 0; +} +/*****************************************************************************/ +static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd) { -struct timeval timeval; -long long int above, below, mean; -struct signed_div_result sdr; -unsigned char *p0; -long int kount1, more, rc, l0, lm; -int fragment, kd; struct easycap *peasycap; -struct data_buffer *pdata_buffer; -size_t szret; +int retval; -/*---------------------------------------------------------------------------*/ -/* - * DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE. - * - ****************************************************************************** - ***** N.B. IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ****** - ***** THIS CONDITION SIGNIFIES END-OF-FILE. ****** - ****************************************************************************** - */ -/*---------------------------------------------------------------------------*/ +JOT(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; +} -JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); +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; +} +/*****************************************************************************/ +static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss) +{ +struct easycap *peasycap; +snd_pcm_uframes_t offset; -if (NULL == file) { - SAY("ERROR: file is NULL\n"); - return -ERESTARTSYS; +JOT(16, "\n"); +if (NULL == pss) { + SAY("ERROR: pss is NULL\n"); + return -EFAULT; } -peasycap = file->private_data; +peasycap = snd_pcm_substream_chip(pss); if (NULL == peasycap) { - SAY("ERROR in easysnd_read(): peasycap is NULL\n"); + SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { - SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap); + SAY("ERROR: bad peasycap\n"); return -EFAULT; } -if (NULL == peasycap->pusb_device) { - SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\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; } -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); - return -ERESTARTSYS; - } - JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd); /*---------------------------------------------------------------------------*/ -/* - * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap, - * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL. - * IF NECESSARY, BAIL OUT. -*/ -/*---------------------------------------------------------------------------*/ - if (kd != isdongle(peasycap)) - return -ERESTARTSYS; - if (NULL == file) { - SAY("ERROR: file is NULL\n"); - mutex_unlock(&easycap_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); - 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); - return -ERESTARTSYS; - } - if (NULL == peasycap->pusb_device) { - SAM("ERROR: peasycap->pusb_device is NULL\n"); - mutex_unlock(&easycap_dongle[kd].mutex_audio); - return -ERESTARTSYS; - } -} else { +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; +} +/*****************************************************************************/ +static struct page *easycap_alsa_page(struct snd_pcm_substream *pss, + unsigned long offset) +{ + return vmalloc_to_page(pss->runtime->dma_area + offset); +} +/*****************************************************************************/ + +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, +}; + +/*****************************************************************************/ /*---------------------------------------------------------------------------*/ /* - * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE - * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT. + * THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS + * MEANS MODULE easycap. BEWARE. */ /*---------------------------------------------------------------------------*/ - return -ERESTARTSYS; -} -/*---------------------------------------------------------------------------*/ -if (file->f_flags & O_NONBLOCK) - JOT(16, "NONBLOCK kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); -else - JOT(8, "BLOCKING kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); +int easycap_alsa_probe(struct easycap *peasycap) +{ +int rc; +struct snd_card *psnd_card; +struct snd_pcm *psnd_pcm; -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); - return -EFAULT; +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL\n"); + return -ENODEV; } -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); +if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) { + SAY("ERROR: bad peasycap\n"); return -EFAULT; } -JOM(12, "before wait, %i=frag read %i=frag fill\n", \ - (peasycap->audio_read / peasycap->audio_pages_per_fragment), \ - (peasycap->audio_fill / peasycap->audio_pages_per_fragment)); -fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment); -while ((fragment == (peasycap->audio_fill / \ - peasycap->audio_pages_per_fragment)) || \ - (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) { - if (file->f_flags & O_NONBLOCK) { - JOM(16, "returning -EAGAIN as instructed\n"); - mutex_unlock(&easycap_dongle[kd].mutex_audio); - return -EAGAIN; - } - rc = wait_event_interruptible(peasycap->wq_audio, \ - (peasycap->audio_idle || peasycap->audio_eof || \ - ((fragment != (peasycap->audio_fill / \ - peasycap->audio_pages_per_fragment)) && \ - (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))))); - if (0 != rc) { - SAM("aborted by signal\n"); - mutex_unlock(&easycap_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); - 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); - return 0; - } - if (!peasycap->audio_isoc_streaming) { - JOM(16, "returning 0 because audio urbs not streaming\n"); - mutex_unlock(&easycap_dongle[kd].mutex_audio); - return 0; - } +if (0 > peasycap->minor) { + SAY("ERROR: no minor\n"); + return -ENODEV; } -JOM(12, "after wait, %i=frag read %i=frag fill\n", \ - (peasycap->audio_read / peasycap->audio_pages_per_fragment), \ - (peasycap->audio_fill / peasycap->audio_pages_per_fragment)); -szret = (size_t)0; -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); - return -EFAULT; - } - if (NULL == pdata_buffer->pto) { - SAM("ERROR: pdata_buffer->pto is NULL\n"); - mutex_unlock(&easycap_dongle[kd].mutex_audio); + +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 (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; } - 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); - return -ERESTARTSYS; - } - if (!kount1) { - (peasycap->audio_read)++; - if (peasycap->audio_buffer_page_many <= peasycap->audio_read) - peasycap->audio_read = 0; - JOM(12, "bumped peasycap->audio_read to %i\n", \ - peasycap->audio_read); - if (fragment != (peasycap->audio_read / \ - peasycap->audio_pages_per_fragment)) - break; + 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]); - 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); - 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); - return -EFAULT; - } - if (NULL == pdata_buffer->pgo) { - SAM("ERROR: pdata_buffer->pgo is NULL\n"); - mutex_unlock(&easycap_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); - return -EFAULT; - } - kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); - } - JOM(12, "ready to send %li bytes\n", (long int) kount1); - JOM(12, "still to send %li bytes\n", (long int) kount); - more = kount1; - if (more > kount) - more = kount; - JOM(12, "agreed to send %li bytes from page %i\n", \ - more, peasycap->audio_read); - if (!more) - break; + psnd_card->dev = &peasycap->pusb_device->dev; + psnd_card->private_data = peasycap; + peasycap->psnd_card = psnd_card; -/*---------------------------------------------------------------------------*/ -/* - * ACCUMULATE DYNAMIC-RANGE INFORMATION - */ -/*---------------------------------------------------------------------------*/ - p0 = (unsigned char *)pdata_buffer->pgo; l0 = 0; lm = more/2; - while (l0 < lm) { - SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau, \ - &peasycap->audio_square); l0++; p0 += 2; + rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm); + if (rc) { + SAM("ERROR: Cannot do ALSA snd_pcm_new()\n"); + snd_card_free(psnd_card); + return -EFAULT; } -/*---------------------------------------------------------------------------*/ - 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); + + 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 = NULL; + + rc = snd_card_register(psnd_card); + if (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]); } - *poff += (loff_t)more; - szret += (size_t)more; - pdata_buffer->pto += more; - puserspacebuffer += more; - kount -= (size_t)more; -} -JOM(12, "after read, %i=frag read %i=frag fill\n", \ - (peasycap->audio_read / peasycap->audio_pages_per_fragment), \ - (peasycap->audio_fill / peasycap->audio_pages_per_fragment)); -if (kount < 0) { - SAM("MISTAKE: %li=kount %li=szret\n", \ - (long int)kount, (long int)szret); +return 0; } +#endif /*! CONFIG_EASYCAP_OSS */ + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ /*---------------------------------------------------------------------------*/ /* - * CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL + * COMMON AUDIO INITIALIZATION */ /*---------------------------------------------------------------------------*/ -if (peasycap->audio_sample) { - below = peasycap->audio_sample; - above = peasycap->audio_square; - sdr = signed_div(above, below); - above = sdr.quotient; - mean = peasycap->audio_niveau; - sdr = signed_div(mean, peasycap->audio_sample); +int +easycap_sound_setup(struct easycap *peasycap) +{ +int rc; - JOM(8, "%8lli=mean %8lli=meansquare after %lli samples, =>\n", \ - sdr.quotient, above, peasycap->audio_sample); +JOM(4, "starting initialization\n"); - sdr = signed_div(above, 32768); - JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient); +if (NULL == peasycap) { + SAY("ERROR: peasycap is NULL.\n"); + return -EFAULT; } -/*---------------------------------------------------------------------------*/ -/* - * UPDATE THE AUDIO CLOCK - */ -/*---------------------------------------------------------------------------*/ -do_gettimeofday(&timeval); -if (!peasycap->timeval1.tv_sec) { - peasycap->audio_bytes = 0; - peasycap->timeval3 = timeval; - peasycap->timeval1 = peasycap->timeval3; - sdr.quotient = 192000; -} else { - peasycap->audio_bytes += (long long int) szret; - below = ((long long int)(1000000)) * \ - ((long long int)(timeval.tv_sec - \ - peasycap->timeval3.tv_sec)) + \ - (long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec); - above = 1000000 * ((long long int) peasycap->audio_bytes); +if (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 (below) - sdr = signed_div(above, below); - else - sdr.quotient = 192000; +if (NULL == peasycap->pusb_device) { + SAM("ERROR: peasycap->pusb_device has become NULL\n"); + return -ENODEV; } -JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient); -peasycap->dnbydt = sdr.quotient; +/*---------------------------------------------------------------------------*/ +if (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); -JOM(8, "returning %li\n", (long int)szret); -mutex_unlock(&easycap_dongle[kd].mutex_audio); -return szret; +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; } /*****************************************************************************/ /*---------------------------------------------------------------------------*/ @@ -1052,21 +739,21 @@ if (NULL == peasycap) { SAY("ERROR: peasycap is NULL\n"); return -EFAULT; } -if ((struct list_head *)NULL == peasycap->purb_audio_head) { +if (NULL == peasycap->purb_audio_head) { SAM("ERROR: peasycap->urb_audio_head uninitialized\n"); return -EFAULT; } -if ((struct usb_device *)NULL == peasycap->pusb_device) { +if (NULL == peasycap->pusb_device) { SAM("ERROR: peasycap->pusb_device is NULL\n"); return -EFAULT; } if (!peasycap->audio_isoc_streaming) { JOM(4, "initial submission of all audio urbs\n"); rc = usb_set_interface(peasycap->pusb_device, - peasycap->audio_interface, \ + peasycap->audio_interface, peasycap->audio_altsetting_on); - JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", \ - peasycap->audio_interface, \ + JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", + peasycap->audio_interface, peasycap->audio_altsetting_on, rc); isbad = 0; nospc = 0; m = 0; @@ -1079,78 +766,40 @@ if (!peasycap->audio_isoc_streaming) { purb->interval = 1; purb->dev = peasycap->pusb_device; - purb->pipe = \ - usb_rcvisocpipe(peasycap->pusb_device,\ + purb->pipe = + usb_rcvisocpipe(peasycap->pusb_device, peasycap->audio_endpointnumber); purb->transfer_flags = URB_ISO_ASAP; - purb->transfer_buffer = \ + purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo; - purb->transfer_buffer_length = \ + purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size; - purb->complete = easysnd_complete; +#ifdef CONFIG_EASYCAP_OSS + purb->complete = easyoss_complete; +#else /* CONFIG_EASYCAP_OSS */ + purb->complete = easycap_alsa_complete; +#endif /* CONFIG_EASYCAP_OSS */ purb->context = peasycap; purb->start_frame = 0; - purb->number_of_packets = \ + purb->number_of_packets = peasycap->audio_isoc_framesperdesc; - for (j = 0; j < peasycap->\ - audio_isoc_framesperdesc; \ + for (j = 0; j < peasycap-> + audio_isoc_framesperdesc; j++) { - purb->iso_frame_desc[j].offset = j * \ - peasycap->\ + purb->iso_frame_desc[j].offset = j * + peasycap-> audio_isoc_maxframesize; - purb->iso_frame_desc[j].length = \ - peasycap->\ + purb->iso_frame_desc[j].length = + peasycap-> audio_isoc_maxframesize; } rc = usb_submit_urb(purb, GFP_KERNEL); - if (0 != rc) { + if (rc) { isbad++; - 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 -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: { - nospc++; - break; - } - default: { - SAM("unknown error code %i\n",\ - rc); - break; - } - } + SAM("ERROR: usb_submit_urb() failed" + " for urb with rc: -%s: %d\n", + strerror(rc), rc); } else { m++; } @@ -1169,7 +818,7 @@ if (!peasycap->audio_isoc_streaming) { if (isbad) { JOM(4, "attempting cleanup instead of submitting\n"); list_for_each(plist_head, (peasycap->purb_audio_head)) { - pdata_urb = list_entry(plist_head, struct data_urb, \ + pdata_urb = list_entry(plist_head, struct data_urb, list_head); if (NULL != pdata_urb) { purb = pdata_urb->purb; @@ -1179,7 +828,7 @@ if (!peasycap->audio_isoc_streaming) { } 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 @@ -1205,15 +854,15 @@ if (NULL == peasycap) { return -EFAULT; } if (peasycap->audio_isoc_streaming) { - if ((struct list_head *)NULL != peasycap->purb_audio_head) { + if (NULL != peasycap->purb_audio_head) { peasycap->audio_isoc_streaming = 0; JOM(4, "killing audio urbs\n"); m = 0; list_for_each(plist_head, (peasycap->purb_audio_head)) { pdata_urb = list_entry(plist_head, struct data_urb, list_head); - if ((struct data_urb *)NULL != pdata_urb) { - if ((struct urb *)NULL != pdata_urb->purb) { + if (NULL != pdata_urb) { + if (NULL != pdata_urb->purb) { usb_kill_urb(pdata_urb->purb); m++; } @@ -1225,7 +874,7 @@ if (peasycap->audio_isoc_streaming) { return -EFAULT; } } else { - JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n", \ + JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n", peasycap->audio_isoc_streaming); } return 0; |