staging: easycap: drop redunant backslashes from the code
[linux-2.6.git] / drivers / staging / easycap / easycap_sound.c
blob8d1c0620344dc411aca73a801401657b9d18ceae
1 /******************************************************************************
2 * *
3 * easycap_sound.c *
4 * *
5 * Audio driver for EasyCAP USB2.0 Video Capture Device DC60 *
6 * *
7 * *
8 ******************************************************************************/
9 /*
11 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
14 * This is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * The software is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this software; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 /*****************************************************************************/
31 #include "easycap.h"
32 #include "easycap_sound.h"
34 #if defined(EASYCAP_NEEDS_ALSA)
35 /*--------------------------------------------------------------------------*/
37 * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
39 /*--------------------------------------------------------------------------*/
40 static const struct snd_pcm_hardware alsa_hardware = {
41 .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
42 SNDRV_PCM_INFO_MMAP |
43 SNDRV_PCM_INFO_INTERLEAVED |
44 SNDRV_PCM_INFO_MMAP_VALID,
45 .formats = SNDRV_PCM_FMTBIT_S16_LE,
46 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
47 .rate_min = 32000,
48 .rate_max = 48000,
49 .channels_min = 2,
50 .channels_max = 2,
51 .buffer_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT *
52 AUDIO_FRAGMENT_MANY,
53 .period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
54 .period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
55 .periods_min = AUDIO_FRAGMENT_MANY,
56 .periods_max = AUDIO_FRAGMENT_MANY * 2,
59 static struct snd_pcm_ops easycap_alsa_pcm_ops = {
60 .open = easycap_alsa_open,
61 .close = easycap_alsa_close,
62 .ioctl = snd_pcm_lib_ioctl,
63 .hw_params = easycap_alsa_hw_params,
64 .hw_free = easycap_alsa_hw_free,
65 .prepare = easycap_alsa_prepare,
66 .ack = easycap_alsa_ack,
67 .trigger = easycap_alsa_trigger,
68 .pointer = easycap_alsa_pointer,
69 .page = easycap_alsa_page,
72 /*****************************************************************************/
73 /*---------------------------------------------------------------------------*/
75 * THE FUNCTION snd_card_create() HAS THIS_MODULE AS AN ARGUMENT. THIS
76 * MEANS MODULE easycap. BEWARE.
78 /*---------------------------------------------------------------------------*/
79 int
80 easycap_alsa_probe(struct easycap *peasycap)
82 int rc;
83 struct snd_card *psnd_card;
84 struct snd_pcm *psnd_pcm;
86 if (NULL == peasycap) {
87 SAY("ERROR: peasycap is NULL\n");
88 return -ENODEV;
90 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
91 SAY("ERROR: bad peasycap\n");
92 return -EFAULT;
94 if (0 > peasycap->minor) {
95 SAY("ERROR: no minor\n");
96 return -ENODEV;
99 peasycap->alsa_hardware = alsa_hardware;
100 if (true == peasycap->microphone) {
101 peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
102 peasycap->alsa_hardware.rate_min = 32000;
103 peasycap->alsa_hardware.rate_max = 32000;
104 } else {
105 peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
106 peasycap->alsa_hardware.rate_min = 48000;
107 peasycap->alsa_hardware.rate_max = 48000;
110 #if defined(EASYCAP_NEEDS_CARD_CREATE)
111 if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa",
112 THIS_MODULE, 0,
113 &psnd_card)) {
114 SAY("ERROR: Cannot do ALSA snd_card_create()\n");
115 return -EFAULT;
117 #else
118 psnd_card = snd_card_new(SNDRV_DEFAULT_IDX1, "easycap_alsa",
119 THIS_MODULE, 0);
120 if (NULL == psnd_card) {
121 SAY("ERROR: Cannot do ALSA snd_card_new()\n");
122 return -EFAULT;
124 #endif /*EASYCAP_NEEDS_CARD_CREATE*/
126 sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
127 strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
128 strcpy(&psnd_card->shortname[0], "easycap_alsa");
129 sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
131 psnd_card->dev = &peasycap->pusb_device->dev;
132 psnd_card->private_data = peasycap;
133 peasycap->psnd_card = psnd_card;
135 rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
136 if (0 != rc) {
137 SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
138 snd_card_free(psnd_card);
139 return -EFAULT;
142 snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE,
143 &easycap_alsa_pcm_ops);
144 psnd_pcm->info_flags = 0;
145 strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
146 psnd_pcm->private_data = peasycap;
147 peasycap->psnd_pcm = psnd_pcm;
148 peasycap->psubstream = (struct snd_pcm_substream *)NULL;
150 rc = snd_card_register(psnd_card);
151 if (0 != rc) {
152 SAM("ERROR: Cannot do ALSA snd_card_register()\n");
153 snd_card_free(psnd_card);
154 return -EFAULT;
155 } else {
157 SAM("registered %s\n", &psnd_card->id[0]);
159 return 0;
161 /*****************************************************************************/
162 /*---------------------------------------------------------------------------*/
164 * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
165 * PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
166 * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
168 /*---------------------------------------------------------------------------*/
169 void
170 easycap_alsa_complete(struct urb *purb)
172 struct easycap *peasycap;
173 struct snd_pcm_substream *pss;
174 struct snd_pcm_runtime *prt;
175 int dma_bytes, fragment_bytes;
176 int isfragment;
177 __u8 *p1, *p2;
178 __s16 s16;
179 int i, j, more, much, rc;
180 #if defined(UPSAMPLE)
181 int k;
182 __s16 oldaudio, newaudio, delta;
183 #endif /*UPSAMPLE*/
185 JOT(16, "\n");
187 if (NULL == purb) {
188 SAY("ERROR: purb is NULL\n");
189 return;
191 peasycap = purb->context;
192 if (NULL == peasycap) {
193 SAY("ERROR: peasycap is NULL\n");
194 return;
196 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
197 SAY("ERROR: bad peasycap\n");
198 return;
200 much = 0;
201 if (peasycap->audio_idle) {
202 JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n",
203 peasycap->audio_idle, peasycap->audio_isoc_streaming);
204 if (peasycap->audio_isoc_streaming)
205 goto resubmit;
207 /*---------------------------------------------------------------------------*/
208 pss = peasycap->psubstream;
209 if (NULL == pss)
210 goto resubmit;
211 prt = pss->runtime;
212 if (NULL == prt)
213 goto resubmit;
214 dma_bytes = (int)prt->dma_bytes;
215 if (0 == dma_bytes)
216 goto resubmit;
217 fragment_bytes = 4 * ((int)prt->period_size);
218 if (0 == fragment_bytes)
219 goto resubmit;
220 /* -------------------------------------------------------------------------*/
221 if (purb->status) {
222 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
223 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
224 return;
226 SAM("ERROR: non-zero urb status:\n");
227 switch (purb->status) {
228 case -EINPROGRESS: {
229 SAM("-EINPROGRESS\n");
230 break;
232 case -ENOSR: {
233 SAM("-ENOSR\n");
234 break;
236 case -EPIPE: {
237 SAM("-EPIPE\n");
238 break;
240 case -EOVERFLOW: {
241 SAM("-EOVERFLOW\n");
242 break;
244 case -EPROTO: {
245 SAM("-EPROTO\n");
246 break;
248 case -EILSEQ: {
249 SAM("-EILSEQ\n");
250 break;
252 case -ETIMEDOUT: {
253 SAM("-ETIMEDOUT\n");
254 break;
256 case -EMSGSIZE: {
257 SAM("-EMSGSIZE\n");
258 break;
260 case -EOPNOTSUPP: {
261 SAM("-EOPNOTSUPP\n");
262 break;
264 case -EPFNOSUPPORT: {
265 SAM("-EPFNOSUPPORT\n");
266 break;
268 case -EAFNOSUPPORT: {
269 SAM("-EAFNOSUPPORT\n");
270 break;
272 case -EADDRINUSE: {
273 SAM("-EADDRINUSE\n");
274 break;
276 case -EADDRNOTAVAIL: {
277 SAM("-EADDRNOTAVAIL\n");
278 break;
280 case -ENOBUFS: {
281 SAM("-ENOBUFS\n");
282 break;
284 case -EISCONN: {
285 SAM("-EISCONN\n");
286 break;
288 case -ENOTCONN: {
289 SAM("-ENOTCONN\n");
290 break;
292 case -ESHUTDOWN: {
293 SAM("-ESHUTDOWN\n");
294 break;
296 case -ENOENT: {
297 SAM("-ENOENT\n");
298 break;
300 case -ECONNRESET: {
301 SAM("-ECONNRESET\n");
302 break;
304 case -ENOSPC: {
305 SAM("ENOSPC\n");
306 break;
308 default: {
309 SAM("unknown error: %i\n", purb->status);
310 break;
313 goto resubmit;
315 /*---------------------------------------------------------------------------*/
317 * PROCEED HERE WHEN NO ERROR
319 /*---------------------------------------------------------------------------*/
321 #if defined(UPSAMPLE)
322 oldaudio = peasycap->oldaudio;
323 #endif /*UPSAMPLE*/
325 for (i = 0; i < purb->number_of_packets; i++) {
326 switch (purb->iso_frame_desc[i].status) {
327 case 0: {
328 break;
330 case -ENOENT: {
331 SAM("-ENOENT\n");
332 break;
334 case -EINPROGRESS: {
335 SAM("-EINPROGRESS\n");
336 break;
338 case -EPROTO: {
339 SAM("-EPROTO\n");
340 break;
342 case -EILSEQ: {
343 SAM("-EILSEQ\n");
344 break;
346 case -ETIME: {
347 SAM("-ETIME\n");
348 break;
350 case -ETIMEDOUT: {
351 SAM("-ETIMEDOUT\n");
352 break;
354 case -EPIPE: {
355 SAM("-EPIPE\n");
356 break;
358 case -ECOMM: {
359 SAM("-ECOMM\n");
360 break;
362 case -ENOSR: {
363 SAM("-ENOSR\n");
364 break;
366 case -EOVERFLOW: {
367 SAM("-EOVERFLOW\n");
368 break;
370 case -EREMOTEIO: {
371 SAM("-EREMOTEIO\n");
372 break;
374 case -ENODEV: {
375 SAM("-ENODEV\n");
376 break;
378 case -EXDEV: {
379 SAM("-EXDEV\n");
380 break;
382 case -EINVAL: {
383 SAM("-EINVAL\n");
384 break;
386 case -ECONNRESET: {
387 SAM("-ECONNRESET\n");
388 break;
390 case -ENOSPC: {
391 SAM("-ENOSPC\n");
392 break;
394 case -ESHUTDOWN: {
395 SAM("-ESHUTDOWN\n");
396 break;
398 case -EPERM: {
399 SAM("-EPERM\n");
400 break;
402 default: {
403 SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
404 break;
407 if (!purb->iso_frame_desc[i].status) {
408 more = purb->iso_frame_desc[i].actual_length;
409 if (!more)
410 peasycap->audio_mt++;
411 else {
412 if (peasycap->audio_mt) {
413 JOM(12, "%4i empty audio urb frames\n",
414 peasycap->audio_mt);
415 peasycap->audio_mt = 0;
418 p1 = (__u8 *)(purb->transfer_buffer +
419 purb->iso_frame_desc[i].offset);
421 /*---------------------------------------------------------------------------*/
423 * COPY more BYTES FROM ISOC BUFFER TO THE DMA BUFFER,
424 * CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
426 /*---------------------------------------------------------------------------*/
427 while (more) {
428 if (0 > more) {
429 SAM("MISTAKE: more is negative\n");
430 return;
432 much = dma_bytes - peasycap->dma_fill;
433 if (0 > much) {
434 SAM("MISTAKE: much is negative\n");
435 return;
437 if (0 == much) {
438 peasycap->dma_fill = 0;
439 peasycap->dma_next = fragment_bytes;
440 JOM(8, "wrapped dma buffer\n");
442 if (false == peasycap->microphone) {
443 if (much > more)
444 much = more;
445 memcpy(prt->dma_area +
446 peasycap->dma_fill,
447 p1, much);
448 p1 += much;
449 more -= much;
450 } else {
451 #if defined(UPSAMPLE)
452 if (much % 16)
453 JOM(8, "MISTAKE? much"
454 " is not divisible by 16\n");
455 if (much > (16 *
456 more))
457 much = 16 *
458 more;
459 p2 = (__u8 *)(prt->dma_area +
460 peasycap->dma_fill);
462 for (j = 0; j < (much/16); j++) {
463 newaudio = ((int) *p1) - 128;
464 newaudio = 128 *
465 newaudio;
467 delta = (newaudio - oldaudio)
468 / 4;
469 s16 = oldaudio + delta;
471 for (k = 0; k < 4; k++) {
472 *p2 = (0x00FF & s16);
473 *(p2 + 1) = (0xFF00 &
474 s16) >> 8;
475 p2 += 2;
476 *p2 = (0x00FF & s16);
477 *(p2 + 1) = (0xFF00 &
478 s16) >> 8;
479 p2 += 2;
480 s16 += delta;
482 p1++;
483 more--;
484 oldaudio = s16;
486 #else /*!UPSAMPLE*/
487 if (much > (2 * more))
488 much = 2 * more;
489 p2 = (__u8 *)(prt->dma_area +
490 peasycap->dma_fill);
492 for (j = 0; j < (much / 2); j++) {
493 s16 = ((int) *p1) - 128;
494 s16 = 128 *
495 s16;
496 *p2 = (0x00FF & s16);
497 *(p2 + 1) = (0xFF00 & s16) >>
499 p1++; p2 += 2;
500 more--;
502 #endif /*UPSAMPLE*/
504 peasycap->dma_fill += much;
505 if (peasycap->dma_fill >= peasycap->dma_next) {
506 isfragment = peasycap->dma_fill /
507 fragment_bytes;
508 if (0 > isfragment) {
509 SAM("MISTAKE: isfragment is "
510 "negative\n");
511 return;
513 peasycap->dma_read = (isfragment
514 - 1) * fragment_bytes;
515 peasycap->dma_next = (isfragment
516 + 1) * fragment_bytes;
517 if (dma_bytes < peasycap->dma_next) {
518 peasycap->dma_next =
519 fragment_bytes;
521 if (0 <= peasycap->dma_read) {
522 JOM(8, "snd_pcm_period_elap"
523 "sed(), %i="
524 "isfragment\n",
525 isfragment);
526 snd_pcm_period_elapsed(pss);
531 } else {
532 JOM(12, "discarding audio samples because "
533 "%i=purb->iso_frame_desc[i].status\n",
534 purb->iso_frame_desc[i].status);
537 #if defined(UPSAMPLE)
538 peasycap->oldaudio = oldaudio;
539 #endif /*UPSAMPLE*/
542 /*---------------------------------------------------------------------------*/
544 * RESUBMIT THIS URB
546 /*---------------------------------------------------------------------------*/
547 resubmit:
548 if (peasycap->audio_isoc_streaming) {
549 rc = usb_submit_urb(purb, GFP_ATOMIC);
550 if (0 != rc) {
551 if ((-ENODEV != rc) && (-ENOENT != rc)) {
552 SAM("ERROR: while %i=audio_idle, "
553 "usb_submit_urb() failed "
554 "with rc:\n", peasycap->audio_idle);
556 switch (rc) {
557 case -ENODEV:
558 case -ENOENT:
559 break;
560 case -ENOMEM: {
561 SAM("-ENOMEM\n");
562 break;
564 case -ENXIO: {
565 SAM("-ENXIO\n");
566 break;
568 case -EINVAL: {
569 SAM("-EINVAL\n");
570 break;
572 case -EAGAIN: {
573 SAM("-EAGAIN\n");
574 break;
576 case -EFBIG: {
577 SAM("-EFBIG\n");
578 break;
580 case -EPIPE: {
581 SAM("-EPIPE\n");
582 break;
584 case -EMSGSIZE: {
585 SAM("-EMSGSIZE\n");
586 break;
588 case -ENOSPC: {
589 SAM("-ENOSPC\n");
590 break;
592 case -EPERM: {
593 SAM("-EPERM\n");
594 break;
596 default: {
597 SAM("unknown error: %i\n", rc);
598 break;
601 if (0 < peasycap->audio_isoc_streaming)
602 (peasycap->audio_isoc_streaming)--;
605 return;
607 /*****************************************************************************/
609 easycap_alsa_open(struct snd_pcm_substream *pss)
611 struct snd_pcm *psnd_pcm;
612 struct snd_card *psnd_card;
613 struct easycap *peasycap;
615 JOT(4, "\n");
616 if (NULL == pss) {
617 SAY("ERROR: pss is NULL\n");
618 return -EFAULT;
620 psnd_pcm = pss->pcm;
621 if (NULL == psnd_pcm) {
622 SAY("ERROR: psnd_pcm is NULL\n");
623 return -EFAULT;
625 psnd_card = psnd_pcm->card;
626 if (NULL == psnd_card) {
627 SAY("ERROR: psnd_card is NULL\n");
628 return -EFAULT;
631 peasycap = psnd_card->private_data;
632 if (NULL == peasycap) {
633 SAY("ERROR: peasycap is NULL\n");
634 return -EFAULT;
636 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
637 SAY("ERROR: bad peasycap\n");
638 return -EFAULT;
640 if (peasycap->psnd_card != psnd_card) {
641 SAM("ERROR: bad peasycap->psnd_card\n");
642 return -EFAULT;
644 if (NULL != peasycap->psubstream) {
645 SAM("ERROR: bad peasycap->psubstream\n");
646 return -EFAULT;
648 pss->private_data = peasycap;
649 peasycap->psubstream = pss;
650 pss->runtime->hw = peasycap->alsa_hardware;
651 pss->runtime->private_data = peasycap;
652 pss->private_data = peasycap;
654 if (0 != easycap_sound_setup(peasycap)) {
655 JOM(4, "ending unsuccessfully\n");
656 return -EFAULT;
658 JOM(4, "ending successfully\n");
659 return 0;
661 /*****************************************************************************/
663 easycap_alsa_close(struct snd_pcm_substream *pss)
665 struct easycap *peasycap;
667 JOT(4, "\n");
668 if (NULL == pss) {
669 SAY("ERROR: pss is NULL\n");
670 return -EFAULT;
672 peasycap = snd_pcm_substream_chip(pss);
673 if (NULL == peasycap) {
674 SAY("ERROR: peasycap is NULL\n");
675 return -EFAULT;
677 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
678 SAY("ERROR: bad peasycap\n");
679 return -EFAULT;
681 pss->private_data = NULL;
682 peasycap->psubstream = (struct snd_pcm_substream *)NULL;
683 JOT(4, "ending successfully\n");
684 return 0;
686 /*****************************************************************************/
688 easycap_alsa_hw_params(struct snd_pcm_substream *pss,
689 struct snd_pcm_hw_params *phw)
691 int rc;
693 JOT(4, "%i\n", (params_buffer_bytes(phw)));
694 if (NULL == pss) {
695 SAY("ERROR: pss is NULL\n");
696 return -EFAULT;
698 rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
699 if (0 != rc)
700 return rc;
701 return 0;
703 /*****************************************************************************/
705 easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
707 struct snd_pcm_runtime *prt;
708 JOT(4, "\n");
710 if (NULL == pss) {
711 SAY("ERROR: pss is NULL\n");
712 return -EFAULT;
714 prt = pss->runtime;
715 if (NULL == prt) {
716 SAY("ERROR: substream.runtime is NULL\n");
717 return -EFAULT;
719 if (prt->dma_area) {
720 if (prt->dma_bytes > sz)
721 return 0;
722 vfree(prt->dma_area);
724 prt->dma_area = vmalloc(sz);
725 if (NULL == prt->dma_area)
726 return -ENOMEM;
727 prt->dma_bytes = sz;
728 return 0;
730 /*****************************************************************************/
732 easycap_alsa_hw_free(struct snd_pcm_substream *pss)
734 struct snd_pcm_runtime *prt;
735 JOT(4, "\n");
737 if (NULL == pss) {
738 SAY("ERROR: pss is NULL\n");
739 return -EFAULT;
741 prt = pss->runtime;
742 if (NULL == prt) {
743 SAY("ERROR: substream.runtime is NULL\n");
744 return -EFAULT;
746 if (NULL != prt->dma_area) {
747 JOT(8, "0x%08lX=prt->dma_area\n", (unsigned long int)prt->dma_area);
748 vfree(prt->dma_area);
749 prt->dma_area = NULL;
750 } else
751 JOT(8, "dma_area already freed\n");
752 return 0;
754 /*****************************************************************************/
756 easycap_alsa_prepare(struct snd_pcm_substream *pss)
758 struct easycap *peasycap;
759 struct snd_pcm_runtime *prt;
761 JOT(4, "\n");
762 if (NULL == pss) {
763 SAY("ERROR: pss is NULL\n");
764 return -EFAULT;
766 prt = pss->runtime;
767 peasycap = snd_pcm_substream_chip(pss);
768 if (NULL == peasycap) {
769 SAY("ERROR: peasycap is NULL\n");
770 return -EFAULT;
772 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
773 SAY("ERROR: bad peasycap\n");
774 return -EFAULT;
777 JOM(16, "ALSA decides %8i Hz=rate\n", (int)pss->runtime->rate);
778 JOM(16, "ALSA decides %8i =period_size\n", (int)pss->runtime->period_size);
779 JOM(16, "ALSA decides %8i =periods\n", (int)pss->runtime->periods);
780 JOM(16, "ALSA decides %8i =buffer_size\n", (int)pss->runtime->buffer_size);
781 JOM(16, "ALSA decides %8i =dma_bytes\n", (int)pss->runtime->dma_bytes);
782 JOM(16, "ALSA decides %8i =boundary\n", (int)pss->runtime->boundary);
783 JOM(16, "ALSA decides %8i =period_step\n", (int)pss->runtime->period_step);
784 JOM(16, "ALSA decides %8i =sample_bits\n", (int)pss->runtime->sample_bits);
785 JOM(16, "ALSA decides %8i =frame_bits\n", (int)pss->runtime->frame_bits);
786 JOM(16, "ALSA decides %8i =min_align\n", (int)pss->runtime->min_align);
787 JOM(12, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
788 JOM(12, "ALSA decides %8i =hw_ptr_interrupt\n",
789 (int)pss->runtime->hw_ptr_interrupt);
790 if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
791 SAY("MISTAKE: unexpected ALSA parameters\n");
792 return -ENOENT;
794 return 0;
796 /*****************************************************************************/
798 easycap_alsa_ack(struct snd_pcm_substream *pss)
800 return 0;
802 /*****************************************************************************/
804 easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
806 struct easycap *peasycap;
807 int retval;
809 JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
810 SNDRV_PCM_TRIGGER_STOP);
811 if (NULL == pss) {
812 SAY("ERROR: pss is NULL\n");
813 return -EFAULT;
815 peasycap = snd_pcm_substream_chip(pss);
816 if (NULL == peasycap) {
817 SAY("ERROR: peasycap is NULL\n");
818 return -EFAULT;
820 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
821 SAY("ERROR: bad peasycap\n");
822 return -EFAULT;
825 switch (cmd) {
826 case SNDRV_PCM_TRIGGER_START: {
827 peasycap->audio_idle = 0;
828 break;
830 case SNDRV_PCM_TRIGGER_STOP: {
831 peasycap->audio_idle = 1;
832 break;
834 default:
835 retval = -EINVAL;
837 return 0;
839 /*****************************************************************************/
840 snd_pcm_uframes_t
841 easycap_alsa_pointer(struct snd_pcm_substream *pss)
843 struct easycap *peasycap;
844 snd_pcm_uframes_t offset;
846 JOT(16, "\n");
847 if (NULL == pss) {
848 SAY("ERROR: pss is NULL\n");
849 return -EFAULT;
851 peasycap = snd_pcm_substream_chip(pss);
852 if (NULL == peasycap) {
853 SAY("ERROR: peasycap is NULL\n");
854 return -EFAULT;
856 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
857 SAY("ERROR: bad peasycap\n");
858 return -EFAULT;
860 if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
861 JOM(8, "returning -EIO because "
862 "%i=audio_idle %i=audio_eof\n",
863 peasycap->audio_idle, peasycap->audio_eof);
864 return -EIO;
866 /*---------------------------------------------------------------------------*/
867 if (0 > peasycap->dma_read) {
868 JOM(8, "returning -EBUSY\n");
869 return -EBUSY;
871 offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
872 JOM(8, "ALSA decides %8i =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
873 JOM(8, "ALSA decides %8i =hw_ptr_interrupt\n",
874 (int)pss->runtime->hw_ptr_interrupt);
875 JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n",
876 (int)offset, peasycap->dma_read, peasycap->dma_next);
877 return offset;
879 /*****************************************************************************/
880 struct page *
881 easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
883 return vmalloc_to_page(pss->runtime->dma_area + offset);
885 /*****************************************************************************/
887 #else /*!EASYCAP_NEEDS_ALSA*/
889 /*****************************************************************************/
890 /**************************** **************************/
891 /**************************** Open Sound System **************************/
892 /**************************** **************************/
893 /*****************************************************************************/
894 /*--------------------------------------------------------------------------*/
896 * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
898 /*--------------------------------------------------------------------------*/
899 const struct file_operations easyoss_fops = {
900 .owner = THIS_MODULE,
901 .open = easyoss_open,
902 .release = easyoss_release,
903 #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
904 .unlocked_ioctl = easyoss_ioctl_noinode,
905 #else
906 .ioctl = easyoss_ioctl,
907 #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
908 .read = easyoss_read,
909 .llseek = no_llseek,
911 struct usb_class_driver easyoss_class = {
912 .name = "usb/easyoss%d",
913 .fops = &easyoss_fops,
914 .minor_base = USB_SKEL_MINOR_BASE,
916 /*****************************************************************************/
917 /*---------------------------------------------------------------------------*/
919 * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
920 * PROVIDED peasycap->audio_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
921 * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
923 /*---------------------------------------------------------------------------*/
924 void
925 easyoss_complete(struct urb *purb)
927 struct easycap *peasycap;
928 struct data_buffer *paudio_buffer;
929 __u8 *p1, *p2;
930 __s16 s16;
931 int i, j, more, much, leap, rc;
932 #if defined(UPSAMPLE)
933 int k;
934 __s16 oldaudio, newaudio, delta;
935 #endif /*UPSAMPLE*/
937 JOT(16, "\n");
939 if (NULL == purb) {
940 SAY("ERROR: purb is NULL\n");
941 return;
943 peasycap = purb->context;
944 if (NULL == peasycap) {
945 SAY("ERROR: peasycap is NULL\n");
946 return;
948 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
949 SAY("ERROR: bad peasycap\n");
950 return;
952 much = 0;
953 if (peasycap->audio_idle) {
954 JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n",
955 peasycap->audio_idle, peasycap->audio_isoc_streaming);
956 if (peasycap->audio_isoc_streaming) {
957 rc = usb_submit_urb(purb, GFP_ATOMIC);
958 if (0 != rc) {
959 if (-ENODEV != rc && -ENOENT != rc) {
960 SAM("ERROR: while %i=audio_idle, "
961 "usb_submit_urb() failed with rc:\n",
962 peasycap->audio_idle);
964 switch (rc) {
965 case -ENODEV:
966 case -ENOENT:
967 break;
968 case -ENOMEM: {
969 SAM("-ENOMEM\n");
970 break;
972 case -ENXIO: {
973 SAM("-ENXIO\n");
974 break;
976 case -EINVAL: {
977 SAM("-EINVAL\n");
978 break;
980 case -EAGAIN: {
981 SAM("-EAGAIN\n");
982 break;
984 case -EFBIG: {
985 SAM("-EFBIG\n");
986 break;
988 case -EPIPE: {
989 SAM("-EPIPE\n");
990 break;
992 case -EMSGSIZE: {
993 SAM("-EMSGSIZE\n");
994 break;
996 case -ENOSPC: {
997 SAM("-ENOSPC\n");
998 break;
1000 case -EPERM: {
1001 SAM("-EPERM\n");
1002 break;
1004 default: {
1005 SAM("unknown error: %i\n", rc);
1006 break;
1011 return;
1013 /*---------------------------------------------------------------------------*/
1014 if (purb->status) {
1015 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
1016 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
1017 return;
1019 SAM("ERROR: non-zero urb status:\n");
1020 switch (purb->status) {
1021 case -EINPROGRESS: {
1022 SAM("-EINPROGRESS\n");
1023 break;
1025 case -ENOSR: {
1026 SAM("-ENOSR\n");
1027 break;
1029 case -EPIPE: {
1030 SAM("-EPIPE\n");
1031 break;
1033 case -EOVERFLOW: {
1034 SAM("-EOVERFLOW\n");
1035 break;
1037 case -EPROTO: {
1038 SAM("-EPROTO\n");
1039 break;
1041 case -EILSEQ: {
1042 SAM("-EILSEQ\n");
1043 break;
1045 case -ETIMEDOUT: {
1046 SAM("-ETIMEDOUT\n");
1047 break;
1049 case -EMSGSIZE: {
1050 SAM("-EMSGSIZE\n");
1051 break;
1053 case -EOPNOTSUPP: {
1054 SAM("-EOPNOTSUPP\n");
1055 break;
1057 case -EPFNOSUPPORT: {
1058 SAM("-EPFNOSUPPORT\n");
1059 break;
1061 case -EAFNOSUPPORT: {
1062 SAM("-EAFNOSUPPORT\n");
1063 break;
1065 case -EADDRINUSE: {
1066 SAM("-EADDRINUSE\n");
1067 break;
1069 case -EADDRNOTAVAIL: {
1070 SAM("-EADDRNOTAVAIL\n");
1071 break;
1073 case -ENOBUFS: {
1074 SAM("-ENOBUFS\n");
1075 break;
1077 case -EISCONN: {
1078 SAM("-EISCONN\n");
1079 break;
1081 case -ENOTCONN: {
1082 SAM("-ENOTCONN\n");
1083 break;
1085 case -ESHUTDOWN: {
1086 SAM("-ESHUTDOWN\n");
1087 break;
1089 case -ENOENT: {
1090 SAM("-ENOENT\n");
1091 break;
1093 case -ECONNRESET: {
1094 SAM("-ECONNRESET\n");
1095 break;
1097 case -ENOSPC: {
1098 SAM("ENOSPC\n");
1099 break;
1101 case -EPERM: {
1102 SAM("-EPERM\n");
1103 break;
1105 default: {
1106 SAM("unknown error: %i\n", purb->status);
1107 break;
1110 goto resubmit;
1112 /*---------------------------------------------------------------------------*/
1114 * PROCEED HERE WHEN NO ERROR
1116 /*---------------------------------------------------------------------------*/
1117 #if defined(UPSAMPLE)
1118 oldaudio = peasycap->oldaudio;
1119 #endif /*UPSAMPLE*/
1121 for (i = 0; i < purb->number_of_packets; i++) {
1122 switch (purb->iso_frame_desc[i].status) {
1123 case 0: {
1124 break;
1126 case -ENODEV: {
1127 SAM("-ENODEV\n");
1128 break;
1130 case -ENOENT: {
1131 SAM("-ENOENT\n");
1132 break;
1134 case -EINPROGRESS: {
1135 SAM("-EINPROGRESS\n");
1136 break;
1138 case -EPROTO: {
1139 SAM("-EPROTO\n");
1140 break;
1142 case -EILSEQ: {
1143 SAM("-EILSEQ\n");
1144 break;
1146 case -ETIME: {
1147 SAM("-ETIME\n");
1148 break;
1150 case -ETIMEDOUT: {
1151 SAM("-ETIMEDOUT\n");
1152 break;
1154 case -EPIPE: {
1155 SAM("-EPIPE\n");
1156 break;
1158 case -ECOMM: {
1159 SAM("-ECOMM\n");
1160 break;
1162 case -ENOSR: {
1163 SAM("-ENOSR\n");
1164 break;
1166 case -EOVERFLOW: {
1167 SAM("-EOVERFLOW\n");
1168 break;
1170 case -EREMOTEIO: {
1171 SAM("-EREMOTEIO\n");
1172 break;
1174 case -EXDEV: {
1175 SAM("-EXDEV\n");
1176 break;
1178 case -EINVAL: {
1179 SAM("-EINVAL\n");
1180 break;
1182 case -ECONNRESET: {
1183 SAM("-ECONNRESET\n");
1184 break;
1186 case -ENOSPC: {
1187 SAM("-ENOSPC\n");
1188 break;
1190 case -ESHUTDOWN: {
1191 SAM("-ESHUTDOWN\n");
1192 break;
1194 case -EPERM: {
1195 SAM("-EPERM\n");
1196 break;
1198 default: {
1199 SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
1200 break;
1203 if (!purb->iso_frame_desc[i].status) {
1204 more = purb->iso_frame_desc[i].actual_length;
1206 #if defined(TESTTONE)
1207 if (!more)
1208 more = purb->iso_frame_desc[i].length;
1209 #endif
1211 if (!more)
1212 peasycap->audio_mt++;
1213 else {
1214 if (peasycap->audio_mt) {
1215 JOM(12, "%4i empty audio urb frames\n",
1216 peasycap->audio_mt);
1217 peasycap->audio_mt = 0;
1220 p1 = (__u8 *)(purb->transfer_buffer +
1221 purb->iso_frame_desc[i].offset);
1223 leap = 0;
1224 p1 += leap;
1225 more -= leap;
1226 /*---------------------------------------------------------------------------*/
1228 * COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
1229 * CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
1231 /*---------------------------------------------------------------------------*/
1232 while (more) {
1233 if (0 > more) {
1234 SAM("MISTAKE: more is negative\n");
1235 return;
1237 if (peasycap->audio_buffer_page_many <=
1238 peasycap->audio_fill) {
1239 SAM("ERROR: bad "
1240 "peasycap->audio_fill\n");
1241 return;
1244 paudio_buffer = &peasycap->audio_buffer
1245 [peasycap->audio_fill];
1246 if (PAGE_SIZE < (paudio_buffer->pto -
1247 paudio_buffer->pgo)) {
1248 SAM("ERROR: bad paudio_buffer->pto\n");
1249 return;
1251 if (PAGE_SIZE == (paudio_buffer->pto -
1252 paudio_buffer->pgo)) {
1254 #if defined(TESTTONE)
1255 easyoss_testtone(peasycap,
1256 peasycap->audio_fill);
1257 #endif /*TESTTONE*/
1259 paudio_buffer->pto =
1260 paudio_buffer->pgo;
1261 (peasycap->audio_fill)++;
1262 if (peasycap->
1263 audio_buffer_page_many <=
1264 peasycap->audio_fill)
1265 peasycap->audio_fill = 0;
1267 JOM(8, "bumped peasycap->"
1268 "audio_fill to %i\n",
1269 peasycap->audio_fill);
1271 paudio_buffer = &peasycap->
1272 audio_buffer
1273 [peasycap->audio_fill];
1274 paudio_buffer->pto =
1275 paudio_buffer->pgo;
1277 if (!(peasycap->audio_fill %
1278 peasycap->
1279 audio_pages_per_fragment)) {
1280 JOM(12, "wakeup call on wq_"
1281 "audio, %i=frag reading %i"
1282 "=fragment fill\n",
1283 (peasycap->audio_read /
1284 peasycap->
1285 audio_pages_per_fragment),
1286 (peasycap->audio_fill /
1287 peasycap->
1288 audio_pages_per_fragment));
1289 wake_up_interruptible
1290 (&(peasycap->wq_audio));
1294 much = PAGE_SIZE - (int)(paudio_buffer->pto -
1295 paudio_buffer->pgo);
1297 if (false == peasycap->microphone) {
1298 if (much > more)
1299 much = more;
1301 memcpy(paudio_buffer->pto, p1, much);
1302 p1 += much;
1303 more -= much;
1304 } else {
1305 #if defined(UPSAMPLE)
1306 if (much % 16)
1307 JOM(8, "MISTAKE? much"
1308 " is not divisible by 16\n");
1309 if (much > (16 *
1310 more))
1311 much = 16 *
1312 more;
1313 p2 = (__u8 *)paudio_buffer->pto;
1315 for (j = 0; j < (much/16); j++) {
1316 newaudio = ((int) *p1) - 128;
1317 newaudio = 128 *
1318 newaudio;
1320 delta = (newaudio - oldaudio)
1321 / 4;
1322 s16 = oldaudio + delta;
1324 for (k = 0; k < 4; k++) {
1325 *p2 = (0x00FF & s16);
1326 *(p2 + 1) = (0xFF00 &
1327 s16) >> 8;
1328 p2 += 2;
1329 *p2 = (0x00FF & s16);
1330 *(p2 + 1) = (0xFF00 &
1331 s16) >> 8;
1332 p2 += 2;
1334 s16 += delta;
1336 p1++;
1337 more--;
1338 oldaudio = s16;
1340 #else /*!UPSAMPLE*/
1341 if (much > (2 * more))
1342 much = 2 * more;
1343 p2 = (__u8 *)paudio_buffer->pto;
1345 for (j = 0; j < (much / 2); j++) {
1346 s16 = ((int) *p1) - 128;
1347 s16 = 128 *
1348 s16;
1349 *p2 = (0x00FF & s16);
1350 *(p2 + 1) = (0xFF00 & s16) >>
1352 p1++; p2 += 2;
1353 more--;
1355 #endif /*UPSAMPLE*/
1357 (paudio_buffer->pto) += much;
1360 } else {
1361 JOM(12, "discarding audio samples because "
1362 "%i=purb->iso_frame_desc[i].status\n",
1363 purb->iso_frame_desc[i].status);
1366 #if defined(UPSAMPLE)
1367 peasycap->oldaudio = oldaudio;
1368 #endif /*UPSAMPLE*/
1371 /*---------------------------------------------------------------------------*/
1373 * RESUBMIT THIS URB
1375 /*---------------------------------------------------------------------------*/
1376 resubmit:
1377 if (peasycap->audio_isoc_streaming) {
1378 rc = usb_submit_urb(purb, GFP_ATOMIC);
1379 if (0 != rc) {
1380 if (-ENODEV != rc && -ENOENT != rc) {
1381 SAM("ERROR: while %i=audio_idle, "
1382 "usb_submit_urb() failed "
1383 "with rc:\n", peasycap->audio_idle);
1385 switch (rc) {
1386 case -ENODEV:
1387 case -ENOENT:
1388 break;
1389 case -ENOMEM: {
1390 SAM("-ENOMEM\n");
1391 break;
1393 case -ENXIO: {
1394 SAM("-ENXIO\n");
1395 break;
1397 case -EINVAL: {
1398 SAM("-EINVAL\n");
1399 break;
1401 case -EAGAIN: {
1402 SAM("-EAGAIN\n");
1403 break;
1405 case -EFBIG: {
1406 SAM("-EFBIG\n");
1407 break;
1409 case -EPIPE: {
1410 SAM("-EPIPE\n");
1411 break;
1413 case -EMSGSIZE: {
1414 SAM("-EMSGSIZE\n");
1415 break;
1417 case -ENOSPC: {
1418 SAM("-ENOSPC\n");
1419 break;
1421 case -EPERM: {
1422 SAM("-EPERM\n");
1423 break;
1425 default: {
1426 SAM("unknown error: %i\n", rc);
1427 break;
1432 return;
1434 /*****************************************************************************/
1435 /*---------------------------------------------------------------------------*/
1437 * THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
1438 * STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
1439 * HAVE AN IOCTL INTERFACE.
1441 /*---------------------------------------------------------------------------*/
1443 easyoss_open(struct inode *inode, struct file *file)
1445 struct usb_interface *pusb_interface;
1446 struct easycap *peasycap;
1447 int subminor;
1448 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
1449 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
1450 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
1451 struct v4l2_device *pv4l2_device;
1452 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
1453 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
1454 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
1456 JOT(4, "begins\n");
1458 subminor = iminor(inode);
1460 pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
1461 if (NULL == pusb_interface) {
1462 SAY("ERROR: pusb_interface is NULL\n");
1463 SAY("ending unsuccessfully\n");
1464 return -1;
1466 peasycap = usb_get_intfdata(pusb_interface);
1467 if (NULL == peasycap) {
1468 SAY("ERROR: peasycap is NULL\n");
1469 SAY("ending unsuccessfully\n");
1470 return -1;
1472 /*---------------------------------------------------------------------------*/
1473 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
1475 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
1476 #else
1477 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
1478 /*---------------------------------------------------------------------------*/
1480 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
1481 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
1482 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
1483 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
1485 /*---------------------------------------------------------------------------*/
1486 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1487 pv4l2_device = usb_get_intfdata(pusb_interface);
1488 if ((struct v4l2_device *)NULL == pv4l2_device) {
1489 SAY("ERROR: pv4l2_device is NULL\n");
1490 return -EFAULT;
1492 peasycap = (struct easycap *)
1493 container_of(pv4l2_device, struct easycap, v4l2_device);
1495 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
1497 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
1498 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
1499 /*---------------------------------------------------------------------------*/
1500 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1501 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1502 return -EFAULT;
1504 /*---------------------------------------------------------------------------*/
1506 file->private_data = peasycap;
1508 if (0 != easycap_sound_setup(peasycap)) {
1512 return 0;
1514 /*****************************************************************************/
1516 easyoss_release(struct inode *inode, struct file *file)
1518 struct easycap *peasycap;
1520 JOT(4, "begins\n");
1522 peasycap = file->private_data;
1523 if (NULL == peasycap) {
1524 SAY("ERROR: peasycap is NULL.\n");
1525 return -EFAULT;
1527 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1528 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1529 return -EFAULT;
1531 if (0 != kill_audio_urbs(peasycap)) {
1532 SAM("ERROR: kill_audio_urbs() failed\n");
1533 return -EFAULT;
1535 JOM(4, "ending successfully\n");
1536 return 0;
1538 /*****************************************************************************/
1539 ssize_t
1540 easyoss_read(struct file *file, char __user *puserspacebuffer,
1541 size_t kount, loff_t *poff)
1543 struct timeval timeval;
1544 long long int above, below, mean;
1545 struct signed_div_result sdr;
1546 unsigned char *p0;
1547 long int kount1, more, rc, l0, lm;
1548 int fragment, kd;
1549 struct easycap *peasycap;
1550 struct data_buffer *pdata_buffer;
1551 size_t szret;
1553 /*---------------------------------------------------------------------------*/
1555 * DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
1557 ******************************************************************************
1558 ***** N.B. IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
1559 ***** THIS CONDITION SIGNIFIES END-OF-FILE. ******
1560 ******************************************************************************
1562 /*---------------------------------------------------------------------------*/
1564 JOT(8, "%5i=kount %5i=*poff\n", (int)kount, (int)(*poff));
1566 if (NULL == file) {
1567 SAY("ERROR: file is NULL\n");
1568 return -ERESTARTSYS;
1570 peasycap = file->private_data;
1571 if (NULL == peasycap) {
1572 SAY("ERROR in easyoss_read(): peasycap is NULL\n");
1573 return -EFAULT;
1575 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1576 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1577 return -EFAULT;
1579 if (NULL == peasycap->pusb_device) {
1580 SAY("ERROR: peasycap->pusb_device is NULL\n");
1581 return -EFAULT;
1583 kd = isdongle(peasycap);
1584 if (0 <= kd && DONGLE_MANY > kd) {
1585 if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
1586 SAY("ERROR: "
1587 "cannot lock easycapdc60_dongle[%i].mutex_audio\n", kd);
1588 return -ERESTARTSYS;
1590 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
1591 /*---------------------------------------------------------------------------*/
1593 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
1594 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1595 * IF NECESSARY, BAIL OUT.
1597 /*---------------------------------------------------------------------------*/
1598 if (kd != isdongle(peasycap))
1599 return -ERESTARTSYS;
1600 if (NULL == file) {
1601 SAY("ERROR: file is NULL\n");
1602 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1603 return -ERESTARTSYS;
1605 peasycap = file->private_data;
1606 if (NULL == peasycap) {
1607 SAY("ERROR: peasycap is NULL\n");
1608 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1609 return -ERESTARTSYS;
1611 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1612 SAY("ERROR: bad peasycap: 0x%08lX\n",
1613 (unsigned long int) peasycap);
1614 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1615 return -ERESTARTSYS;
1617 if (NULL == peasycap->pusb_device) {
1618 SAM("ERROR: peasycap->pusb_device is NULL\n");
1619 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1620 return -ERESTARTSYS;
1622 } else {
1623 /*---------------------------------------------------------------------------*/
1625 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1626 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1628 /*---------------------------------------------------------------------------*/
1629 return -ERESTARTSYS;
1631 /*---------------------------------------------------------------------------*/
1632 if (file->f_flags & O_NONBLOCK)
1633 JOT(16, "NONBLOCK kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
1634 else
1635 JOT(8, "BLOCKING kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
1637 if ((0 > peasycap->audio_read) ||
1638 (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
1639 SAM("ERROR: peasycap->audio_read out of range\n");
1640 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1641 return -EFAULT;
1643 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
1644 if ((struct data_buffer *)NULL == pdata_buffer) {
1645 SAM("ERROR: pdata_buffer is NULL\n");
1646 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1647 return -EFAULT;
1649 JOM(12, "before wait, %i=frag read %i=frag fill\n",
1650 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
1651 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
1652 fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
1653 while ((fragment == (peasycap->audio_fill /
1654 peasycap->audio_pages_per_fragment)) ||
1655 (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
1656 if (file->f_flags & O_NONBLOCK) {
1657 JOM(16, "returning -EAGAIN as instructed\n");
1658 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1659 return -EAGAIN;
1661 rc = wait_event_interruptible(peasycap->wq_audio,
1662 (peasycap->audio_idle || peasycap->audio_eof ||
1663 ((fragment != (peasycap->audio_fill /
1664 peasycap->audio_pages_per_fragment)) &&
1665 (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
1666 if (0 != rc) {
1667 SAM("aborted by signal\n");
1668 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1669 return -ERESTARTSYS;
1671 if (peasycap->audio_eof) {
1672 JOM(8, "returning 0 because %i=audio_eof\n",
1673 peasycap->audio_eof);
1674 kill_audio_urbs(peasycap);
1675 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1676 return 0;
1678 if (peasycap->audio_idle) {
1679 JOM(16, "returning 0 because %i=audio_idle\n",
1680 peasycap->audio_idle);
1681 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1682 return 0;
1684 if (!peasycap->audio_isoc_streaming) {
1685 JOM(16, "returning 0 because audio urbs not streaming\n");
1686 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1687 return 0;
1690 JOM(12, "after wait, %i=frag read %i=frag fill\n",
1691 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
1692 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
1693 szret = (size_t)0;
1694 fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
1695 while (fragment == (peasycap->audio_read /
1696 peasycap->audio_pages_per_fragment)) {
1697 if (NULL == pdata_buffer->pgo) {
1698 SAM("ERROR: pdata_buffer->pgo is NULL\n");
1699 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1700 return -EFAULT;
1702 if (NULL == pdata_buffer->pto) {
1703 SAM("ERROR: pdata_buffer->pto is NULL\n");
1704 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1705 return -EFAULT;
1707 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
1708 if (0 > kount1) {
1709 SAM("MISTAKE: kount1 is negative\n");
1710 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1711 return -ERESTARTSYS;
1713 if (!kount1) {
1714 (peasycap->audio_read)++;
1715 if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
1716 peasycap->audio_read = 0;
1717 JOM(12, "bumped peasycap->audio_read to %i\n",
1718 peasycap->audio_read);
1720 if (fragment != (peasycap->audio_read /
1721 peasycap->audio_pages_per_fragment))
1722 break;
1724 if ((0 > peasycap->audio_read) ||
1725 (peasycap->audio_buffer_page_many <=
1726 peasycap->audio_read)) {
1727 SAM("ERROR: peasycap->audio_read out of range\n");
1728 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1729 return -EFAULT;
1731 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
1732 if ((struct data_buffer *)NULL == pdata_buffer) {
1733 SAM("ERROR: pdata_buffer is NULL\n");
1734 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1735 return -EFAULT;
1737 if (NULL == pdata_buffer->pgo) {
1738 SAM("ERROR: pdata_buffer->pgo is NULL\n");
1739 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1740 return -EFAULT;
1742 if (NULL == pdata_buffer->pto) {
1743 SAM("ERROR: pdata_buffer->pto is NULL\n");
1744 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1745 return -EFAULT;
1747 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
1749 JOM(12, "ready to send %li bytes\n", (long int) kount1);
1750 JOM(12, "still to send %li bytes\n", (long int) kount);
1751 more = kount1;
1752 if (more > kount)
1753 more = kount;
1754 JOM(12, "agreed to send %li bytes from page %i\n",
1755 more, peasycap->audio_read);
1756 if (!more)
1757 break;
1759 /*---------------------------------------------------------------------------*/
1761 * ACCUMULATE DYNAMIC-RANGE INFORMATION
1763 /*---------------------------------------------------------------------------*/
1764 p0 = (unsigned char *)pdata_buffer->pgo; l0 = 0; lm = more/2;
1765 while (l0 < lm) {
1766 SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau,
1767 &peasycap->audio_square); l0++; p0 += 2;
1769 /*---------------------------------------------------------------------------*/
1770 rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
1771 if (0 != rc) {
1772 SAM("ERROR: copy_to_user() returned %li\n", rc);
1773 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1774 return -EFAULT;
1776 *poff += (loff_t)more;
1777 szret += (size_t)more;
1778 pdata_buffer->pto += more;
1779 puserspacebuffer += more;
1780 kount -= (size_t)more;
1782 JOM(12, "after read, %i=frag read %i=frag fill\n",
1783 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
1784 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
1785 if (kount < 0) {
1786 SAM("MISTAKE: %li=kount %li=szret\n",
1787 (long int)kount, (long int)szret);
1789 /*---------------------------------------------------------------------------*/
1791 * CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
1793 /*---------------------------------------------------------------------------*/
1794 if (peasycap->audio_sample) {
1795 below = peasycap->audio_sample;
1796 above = peasycap->audio_square;
1797 sdr = signed_div(above, below);
1798 above = sdr.quotient;
1799 mean = peasycap->audio_niveau;
1800 sdr = signed_div(mean, peasycap->audio_sample);
1802 JOM(8, "%8lli=mean %8lli=meansquare after %lli samples, =>\n",
1803 sdr.quotient, above, peasycap->audio_sample);
1805 sdr = signed_div(above, 32768);
1806 JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
1808 /*---------------------------------------------------------------------------*/
1810 * UPDATE THE AUDIO CLOCK
1812 /*---------------------------------------------------------------------------*/
1813 do_gettimeofday(&timeval);
1814 if (!peasycap->timeval1.tv_sec) {
1815 peasycap->audio_bytes = 0;
1816 peasycap->timeval3 = timeval;
1817 peasycap->timeval1 = peasycap->timeval3;
1818 sdr.quotient = 192000;
1819 } else {
1820 peasycap->audio_bytes += (long long int) szret;
1821 below = ((long long int)(1000000)) *
1822 ((long long int)(timeval.tv_sec -
1823 peasycap->timeval3.tv_sec)) +
1824 (long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
1825 above = 1000000 * ((long long int) peasycap->audio_bytes);
1827 if (below)
1828 sdr = signed_div(above, below);
1829 else
1830 sdr.quotient = 192000;
1832 JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
1833 peasycap->dnbydt = sdr.quotient;
1835 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1836 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
1837 JOM(8, "returning %li\n", (long int)szret);
1838 return szret;
1840 /*****************************************************************************/
1842 #endif /*!EASYCAP_NEEDS_ALSA*/
1844 /*****************************************************************************/
1845 /*****************************************************************************/
1846 /*****************************************************************************/
1847 /*****************************************************************************/
1848 /*****************************************************************************/
1849 /*****************************************************************************/
1850 /*---------------------------------------------------------------------------*/
1852 * COMMON AUDIO INITIALIZATION
1854 /*---------------------------------------------------------------------------*/
1856 easycap_sound_setup(struct easycap *peasycap)
1858 int rc;
1860 JOM(4, "starting initialization\n");
1862 if (NULL == peasycap) {
1863 SAY("ERROR: peasycap is NULL.\n");
1864 return -EFAULT;
1866 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1867 SAM("ERROR: peasycap->pusb_device is NULL\n");
1868 return -ENODEV;
1870 JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
1872 rc = audio_setup(peasycap);
1873 JOM(8, "audio_setup() returned %i\n", rc);
1875 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1876 SAM("ERROR: peasycap->pusb_device has become NULL\n");
1877 return -ENODEV;
1879 /*---------------------------------------------------------------------------*/
1880 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1881 SAM("ERROR: peasycap->pusb_device has become NULL\n");
1882 return -ENODEV;
1884 rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
1885 peasycap->audio_altsetting_on);
1886 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
1887 peasycap->audio_altsetting_on, rc);
1889 rc = wakeup_device(peasycap->pusb_device);
1890 JOM(8, "wakeup_device() returned %i\n", rc);
1892 peasycap->audio_eof = 0;
1893 peasycap->audio_idle = 0;
1895 peasycap->timeval1.tv_sec = 0;
1896 peasycap->timeval1.tv_usec = 0;
1898 submit_audio_urbs(peasycap);
1900 JOM(4, "finished initialization\n");
1901 return 0;
1903 /*****************************************************************************/
1904 /*---------------------------------------------------------------------------*/
1906 * SUBMIT ALL AUDIO URBS.
1908 /*---------------------------------------------------------------------------*/
1910 submit_audio_urbs(struct easycap *peasycap)
1912 struct data_urb *pdata_urb;
1913 struct urb *purb;
1914 struct list_head *plist_head;
1915 int j, isbad, nospc, m, rc;
1916 int isbuf;
1918 if (NULL == peasycap) {
1919 SAY("ERROR: peasycap is NULL\n");
1920 return -EFAULT;
1922 if ((struct list_head *)NULL == peasycap->purb_audio_head) {
1923 SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
1924 return -EFAULT;
1926 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1927 SAM("ERROR: peasycap->pusb_device is NULL\n");
1928 return -EFAULT;
1930 if (!peasycap->audio_isoc_streaming) {
1931 JOM(4, "initial submission of all audio urbs\n");
1932 rc = usb_set_interface(peasycap->pusb_device,
1933 peasycap->audio_interface,
1934 peasycap->audio_altsetting_on);
1935 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
1936 peasycap->audio_interface,
1937 peasycap->audio_altsetting_on, rc);
1939 isbad = 0; nospc = 0; m = 0;
1940 list_for_each(plist_head, (peasycap->purb_audio_head)) {
1941 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
1942 if (NULL != pdata_urb) {
1943 purb = pdata_urb->purb;
1944 if (NULL != purb) {
1945 isbuf = pdata_urb->isbuf;
1947 purb->interval = 1;
1948 purb->dev = peasycap->pusb_device;
1949 purb->pipe =
1950 usb_rcvisocpipe(peasycap->pusb_device,
1951 peasycap->audio_endpointnumber);
1952 purb->transfer_flags = URB_ISO_ASAP;
1953 purb->transfer_buffer =
1954 peasycap->audio_isoc_buffer[isbuf].pgo;
1955 purb->transfer_buffer_length =
1956 peasycap->audio_isoc_buffer_size;
1957 #if defined(EASYCAP_NEEDS_ALSA)
1958 purb->complete = easycap_alsa_complete;
1959 #else
1960 purb->complete = easyoss_complete;
1961 #endif /*EASYCAP_NEEDS_ALSA*/
1962 purb->context = peasycap;
1963 purb->start_frame = 0;
1964 purb->number_of_packets =
1965 peasycap->audio_isoc_framesperdesc;
1966 for (j = 0; j < peasycap->
1967 audio_isoc_framesperdesc;
1968 j++) {
1969 purb->iso_frame_desc[j].offset = j *
1970 peasycap->
1971 audio_isoc_maxframesize;
1972 purb->iso_frame_desc[j].length =
1973 peasycap->
1974 audio_isoc_maxframesize;
1977 rc = usb_submit_urb(purb, GFP_KERNEL);
1978 if (0 != rc) {
1979 isbad++;
1980 SAM("ERROR: usb_submit_urb() failed"
1981 " for urb with rc:\n");
1982 switch (rc) {
1983 case -ENODEV: {
1984 SAM("-ENODEV\n");
1985 break;
1987 case -ENOENT: {
1988 SAM("-ENOENT\n");
1989 break;
1991 case -ENOMEM: {
1992 SAM("-ENOMEM\n");
1993 break;
1995 case -ENXIO: {
1996 SAM("-ENXIO\n");
1997 break;
1999 case -EINVAL: {
2000 SAM("-EINVAL\n");
2001 break;
2003 case -EAGAIN: {
2004 SAM("-EAGAIN\n");
2005 break;
2007 case -EFBIG: {
2008 SAM("-EFBIG\n");
2009 break;
2011 case -EPIPE: {
2012 SAM("-EPIPE\n");
2013 break;
2015 case -EMSGSIZE: {
2016 SAM("-EMSGSIZE\n");
2017 break;
2019 case -ENOSPC: {
2020 nospc++;
2021 break;
2023 case -EPERM: {
2024 SAM("-EPERM\n");
2025 break;
2027 default: {
2028 SAM("unknown error: %i\n", rc);
2029 break;
2032 } else {
2033 m++;
2035 } else {
2036 isbad++;
2038 } else {
2039 isbad++;
2042 if (nospc) {
2043 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
2044 SAM("..... possibly inadequate USB bandwidth\n");
2045 peasycap->audio_eof = 1;
2047 if (isbad) {
2048 JOM(4, "attempting cleanup instead of submitting\n");
2049 list_for_each(plist_head, (peasycap->purb_audio_head)) {
2050 pdata_urb = list_entry(plist_head, struct data_urb,
2051 list_head);
2052 if (NULL != pdata_urb) {
2053 purb = pdata_urb->purb;
2054 if (NULL != purb)
2055 usb_kill_urb(purb);
2058 peasycap->audio_isoc_streaming = 0;
2059 } else {
2060 peasycap->audio_isoc_streaming = m;
2061 JOM(4, "submitted %i audio urbs\n", m);
2063 } else
2064 JOM(4, "already streaming audio urbs\n");
2066 return 0;
2068 /*****************************************************************************/
2069 /*---------------------------------------------------------------------------*/
2071 * KILL ALL AUDIO URBS.
2073 /*---------------------------------------------------------------------------*/
2075 kill_audio_urbs(struct easycap *peasycap)
2077 int m;
2078 struct list_head *plist_head;
2079 struct data_urb *pdata_urb;
2081 if (NULL == peasycap) {
2082 SAY("ERROR: peasycap is NULL\n");
2083 return -EFAULT;
2085 if (peasycap->audio_isoc_streaming) {
2086 if ((struct list_head *)NULL != peasycap->purb_audio_head) {
2087 peasycap->audio_isoc_streaming = 0;
2088 JOM(4, "killing audio urbs\n");
2089 m = 0;
2090 list_for_each(plist_head, (peasycap->purb_audio_head)) {
2091 pdata_urb = list_entry(plist_head, struct data_urb,
2092 list_head);
2093 if ((struct data_urb *)NULL != pdata_urb) {
2094 if ((struct urb *)NULL != pdata_urb->purb) {
2095 usb_kill_urb(pdata_urb->purb);
2096 m++;
2100 JOM(4, "%i audio urbs killed\n", m);
2101 } else {
2102 SAM("ERROR: peasycap->purb_audio_head is NULL\n");
2103 return -EFAULT;
2105 } else {
2106 JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n",
2107 peasycap->audio_isoc_streaming);
2109 return 0;
2111 /*****************************************************************************/