4bfaf06fb32a60948b5632aab8f97adaec1292e5
[pandora-kernel.git] / drivers / staging / easycap / easycap_sound.c
1 /******************************************************************************
2 *                                                                             *
3 *  easycap_sound.c                                                            *
4 *                                                                             *
5 *  Audio driver for EasyCAP USB2.0 Video Capture Device DC60                  *
6 *                                                                             *
7 *                                                                             *
8 ******************************************************************************/
9 /*
10  *
11  *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
12  *
13  *
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.
18  *
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.
23  *
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
27  *
28 */
29 /*****************************************************************************/
30
31 #include "easycap.h"
32 #include "easycap_sound.h"
33
34 #if defined(EASYCAP_NEEDS_ALSA)
35 /*--------------------------------------------------------------------------*/
36 /*
37  *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
38  */
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,
57 };
58
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,
70 };
71
72 /*****************************************************************************/
73 /*---------------------------------------------------------------------------*/
74 /*
75  *  THE FUNCTION snd_card_create() HAS  THIS_MODULE  AS AN ARGUMENT.  THIS
76  *  MEANS MODULE easycap.  BEWARE.
77 */
78 /*---------------------------------------------------------------------------*/
79 int
80 easycap_alsa_probe(struct easycap *peasycap)
81 {
82 int rc;
83 struct snd_card *psnd_card;
84 struct snd_pcm *psnd_pcm;
85
86 if (NULL == peasycap) {
87         SAY("ERROR: peasycap is NULL\n");
88         return -ENODEV;
89 }
90 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
91         SAY("ERROR: bad peasycap\n");
92         return -EFAULT;
93 }
94 if (0 > peasycap->minor) {
95         SAY("ERROR: no minor\n");
96         return -ENODEV;
97 }
98
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;
108 }
109
110         if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa",
111                                         THIS_MODULE, 0,
112                                         &psnd_card)) {
113                 SAY("ERROR: Cannot do ALSA snd_card_create()\n");
114                 return -EFAULT;
115         }
116
117         sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
118         strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
119         strcpy(&psnd_card->shortname[0], "easycap_alsa");
120         sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
121
122         psnd_card->dev = &peasycap->pusb_device->dev;
123         psnd_card->private_data = peasycap;
124         peasycap->psnd_card = psnd_card;
125
126         rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
127         if (0 != rc) {
128                 SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
129                 snd_card_free(psnd_card);
130                 return -EFAULT;
131         }
132
133         snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE,
134                                                         &easycap_alsa_pcm_ops);
135         psnd_pcm->info_flags = 0;
136         strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
137         psnd_pcm->private_data = peasycap;
138         peasycap->psnd_pcm = psnd_pcm;
139         peasycap->psubstream = (struct snd_pcm_substream *)NULL;
140
141         rc = snd_card_register(psnd_card);
142         if (0 != rc) {
143                 SAM("ERROR: Cannot do ALSA snd_card_register()\n");
144                 snd_card_free(psnd_card);
145                 return -EFAULT;
146         } else {
147         ;
148         SAM("registered %s\n", &psnd_card->id[0]);
149         }
150 return 0;
151 }
152 /*****************************************************************************/
153 /*---------------------------------------------------------------------------*/
154 /*
155  *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
156  *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
157  *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
158  */
159 /*---------------------------------------------------------------------------*/
160 void
161 easycap_alsa_complete(struct urb *purb)
162 {
163 struct easycap *peasycap;
164 struct snd_pcm_substream *pss;
165 struct snd_pcm_runtime *prt;
166 int dma_bytes, fragment_bytes;
167 int isfragment;
168 __u8 *p1, *p2;
169 __s16 s16;
170 int i, j, more, much, rc;
171 #if defined(UPSAMPLE)
172 int k;
173 __s16 oldaudio, newaudio, delta;
174 #endif /*UPSAMPLE*/
175
176 JOT(16, "\n");
177
178 if (NULL == purb) {
179         SAY("ERROR: purb is NULL\n");
180         return;
181 }
182 peasycap = purb->context;
183 if (NULL == peasycap) {
184         SAY("ERROR: peasycap is NULL\n");
185         return;
186 }
187 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
188         SAY("ERROR: bad peasycap\n");
189         return;
190 }
191 much = 0;
192 if (peasycap->audio_idle) {
193         JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
194                         peasycap->audio_idle, peasycap->audio_isoc_streaming);
195         if (peasycap->audio_isoc_streaming)
196                 goto resubmit;
197 }
198 /*---------------------------------------------------------------------------*/
199 pss = peasycap->psubstream;
200 if (NULL == pss)
201         goto resubmit;
202 prt = pss->runtime;
203 if (NULL == prt)
204         goto resubmit;
205 dma_bytes = (int)prt->dma_bytes;
206 if (0 == dma_bytes)
207         goto resubmit;
208 fragment_bytes = 4 * ((int)prt->period_size);
209 if (0 == fragment_bytes)
210         goto resubmit;
211 /* -------------------------------------------------------------------------*/
212 if (purb->status) {
213         if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
214                 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
215                 return;
216         }
217         SAM("ERROR: non-zero urb status:\n");
218         switch (purb->status) {
219         case -EINPROGRESS: {
220                 SAM("-EINPROGRESS\n");
221                 break;
222         }
223         case -ENOSR: {
224                 SAM("-ENOSR\n");
225                 break;
226         }
227         case -EPIPE: {
228                 SAM("-EPIPE\n");
229                 break;
230         }
231         case -EOVERFLOW: {
232                 SAM("-EOVERFLOW\n");
233                 break;
234         }
235         case -EPROTO: {
236                 SAM("-EPROTO\n");
237                 break;
238         }
239         case -EILSEQ: {
240                 SAM("-EILSEQ\n");
241                 break;
242         }
243         case -ETIMEDOUT: {
244                 SAM("-ETIMEDOUT\n");
245                 break;
246         }
247         case -EMSGSIZE: {
248                 SAM("-EMSGSIZE\n");
249                 break;
250         }
251         case -EOPNOTSUPP: {
252                 SAM("-EOPNOTSUPP\n");
253                 break;
254         }
255         case -EPFNOSUPPORT: {
256                 SAM("-EPFNOSUPPORT\n");
257                 break;
258         }
259         case -EAFNOSUPPORT: {
260                 SAM("-EAFNOSUPPORT\n");
261                 break;
262         }
263         case -EADDRINUSE: {
264                 SAM("-EADDRINUSE\n");
265                 break;
266         }
267         case -EADDRNOTAVAIL: {
268                 SAM("-EADDRNOTAVAIL\n");
269                 break;
270         }
271         case -ENOBUFS: {
272                 SAM("-ENOBUFS\n");
273                 break;
274         }
275         case -EISCONN: {
276                 SAM("-EISCONN\n");
277                 break;
278         }
279         case -ENOTCONN: {
280                 SAM("-ENOTCONN\n");
281                 break;
282         }
283         case -ESHUTDOWN: {
284                 SAM("-ESHUTDOWN\n");
285                 break;
286         }
287         case -ENOENT: {
288                 SAM("-ENOENT\n");
289                 break;
290         }
291         case -ECONNRESET: {
292                 SAM("-ECONNRESET\n");
293                 break;
294         }
295         case -ENOSPC: {
296                 SAM("ENOSPC\n");
297                 break;
298         }
299         default: {
300                 SAM("unknown error: %i\n", purb->status);
301                 break;
302         }
303         }
304         goto resubmit;
305 }
306 /*---------------------------------------------------------------------------*/
307 /*
308  *  PROCEED HERE WHEN NO ERROR
309  */
310 /*---------------------------------------------------------------------------*/
311
312 #if defined(UPSAMPLE)
313 oldaudio = peasycap->oldaudio;
314 #endif /*UPSAMPLE*/
315
316 for (i = 0;  i < purb->number_of_packets; i++) {
317         switch (purb->iso_frame_desc[i].status) {
318         case  0: {
319                 break;
320         }
321         case -ENOENT: {
322                 SAM("-ENOENT\n");
323                 break;
324         }
325         case -EINPROGRESS: {
326                 SAM("-EINPROGRESS\n");
327                 break;
328         }
329         case -EPROTO: {
330                 SAM("-EPROTO\n");
331                 break;
332         }
333         case -EILSEQ: {
334                 SAM("-EILSEQ\n");
335                 break;
336         }
337         case -ETIME: {
338                 SAM("-ETIME\n");
339                 break;
340         }
341         case -ETIMEDOUT: {
342                 SAM("-ETIMEDOUT\n");
343                 break;
344         }
345         case -EPIPE: {
346                 SAM("-EPIPE\n");
347                 break;
348         }
349         case -ECOMM: {
350                 SAM("-ECOMM\n");
351                 break;
352         }
353         case -ENOSR: {
354                 SAM("-ENOSR\n");
355                 break;
356         }
357         case -EOVERFLOW: {
358                 SAM("-EOVERFLOW\n");
359                 break;
360         }
361         case -EREMOTEIO: {
362                 SAM("-EREMOTEIO\n");
363                 break;
364         }
365         case -ENODEV: {
366                 SAM("-ENODEV\n");
367                 break;
368         }
369         case -EXDEV: {
370                 SAM("-EXDEV\n");
371                 break;
372         }
373         case -EINVAL: {
374                 SAM("-EINVAL\n");
375                 break;
376         }
377         case -ECONNRESET: {
378                 SAM("-ECONNRESET\n");
379                 break;
380         }
381         case -ENOSPC: {
382                 SAM("-ENOSPC\n");
383                 break;
384         }
385         case -ESHUTDOWN: {
386                 SAM("-ESHUTDOWN\n");
387                 break;
388         }
389         case -EPERM: {
390                 SAM("-EPERM\n");
391                 break;
392         }
393         default: {
394                 SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
395                 break;
396         }
397         }
398         if (!purb->iso_frame_desc[i].status) {
399                 more = purb->iso_frame_desc[i].actual_length;
400                 if (!more)
401                         peasycap->audio_mt++;
402                 else {
403                         if (peasycap->audio_mt) {
404                                 JOM(12, "%4i empty audio urb frames\n",
405                                                         peasycap->audio_mt);
406                                 peasycap->audio_mt = 0;
407                         }
408
409                         p1 = (__u8 *)(purb->transfer_buffer +
410                                         purb->iso_frame_desc[i].offset);
411
412 /*---------------------------------------------------------------------------*/
413 /*
414  *  COPY more BYTES FROM ISOC BUFFER TO THE DMA BUFFER,
415  *  CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
416  */
417 /*---------------------------------------------------------------------------*/
418                         while (more) {
419                                 if (0 > more) {
420                                         SAM("MISTAKE: more is negative\n");
421                                         return;
422                                 }
423                                 much = dma_bytes - peasycap->dma_fill;
424                                 if (0 > much) {
425                                         SAM("MISTAKE: much is negative\n");
426                                         return;
427                                 }
428                                 if (0 == much) {
429                                         peasycap->dma_fill = 0;
430                                         peasycap->dma_next = fragment_bytes;
431                                         JOM(8, "wrapped dma buffer\n");
432                                 }
433                                 if (false == peasycap->microphone) {
434                                         if (much > more)
435                                                 much = more;
436                                         memcpy(prt->dma_area +
437                                                 peasycap->dma_fill,
438                                                                 p1, much);
439                                         p1 += much;
440                                         more -= much;
441                                 } else {
442 #if defined(UPSAMPLE)
443                                         if (much % 16)
444                                                 JOM(8, "MISTAKE? much"
445                                                 " is not divisible by 16\n");
446                                         if (much > (16 *
447                                                         more))
448                                                 much = 16 *
449                                                         more;
450                                         p2 = (__u8 *)(prt->dma_area +
451                                                 peasycap->dma_fill);
452
453                                         for (j = 0;  j < (much/16);  j++) {
454                                                 newaudio =  ((int) *p1) - 128;
455                                                 newaudio = 128 *
456                                                                 newaudio;
457
458                                                 delta = (newaudio - oldaudio)
459                                                                         / 4;
460                                                 s16 = oldaudio + delta;
461
462                                                 for (k = 0;  k < 4;  k++) {
463                                                         *p2 = (0x00FF & s16);
464                                                         *(p2 + 1) = (0xFF00 &
465                                                                 s16) >> 8;
466                                                         p2 += 2;
467                                                         *p2 = (0x00FF & s16);
468                                                         *(p2 + 1) = (0xFF00 &
469                                                                 s16) >> 8;
470                                                         p2 += 2;
471                                                         s16 += delta;
472                                                 }
473                                                 p1++;
474                                                 more--;
475                                                 oldaudio = s16;
476                                         }
477 #else /*!UPSAMPLE*/
478                                         if (much > (2 * more))
479                                                 much = 2 * more;
480                                         p2 = (__u8 *)(prt->dma_area +
481                                                 peasycap->dma_fill);
482
483                                         for (j = 0;  j < (much / 2);  j++) {
484                                                 s16 =  ((int) *p1) - 128;
485                                                 s16 = 128 *
486                                                                 s16;
487                                                 *p2 = (0x00FF & s16);
488                                                 *(p2 + 1) = (0xFF00 & s16) >>
489                                                                         8;
490                                                 p1++;  p2 += 2;
491                                                 more--;
492                                         }
493 #endif /*UPSAMPLE*/
494                                 }
495                                 peasycap->dma_fill += much;
496                                 if (peasycap->dma_fill >= peasycap->dma_next) {
497                                         isfragment = peasycap->dma_fill /
498                                                 fragment_bytes;
499                                         if (0 > isfragment) {
500                                                 SAM("MISTAKE: isfragment is "
501                                                         "negative\n");
502                                                 return;
503                                         }
504                                         peasycap->dma_read = (isfragment
505                                                 - 1) * fragment_bytes;
506                                         peasycap->dma_next = (isfragment
507                                                 + 1) * fragment_bytes;
508                                         if (dma_bytes < peasycap->dma_next) {
509                                                 peasycap->dma_next =
510                                                                 fragment_bytes;
511                                         }
512                                         if (0 <= peasycap->dma_read) {
513                                                 JOM(8, "snd_pcm_period_elap"
514                                                         "sed(), %i="
515                                                         "isfragment\n",
516                                                         isfragment);
517                                                 snd_pcm_period_elapsed(pss);
518                                         }
519                                 }
520                         }
521                 }
522         } else {
523                 JOM(12, "discarding audio samples because "
524                         "%i=purb->iso_frame_desc[i].status\n",
525                                 purb->iso_frame_desc[i].status);
526         }
527
528 #if defined(UPSAMPLE)
529 peasycap->oldaudio = oldaudio;
530 #endif /*UPSAMPLE*/
531
532 }
533 /*---------------------------------------------------------------------------*/
534 /*
535  *  RESUBMIT THIS URB
536  */
537 /*---------------------------------------------------------------------------*/
538 resubmit:
539 if (peasycap->audio_isoc_streaming) {
540         rc = usb_submit_urb(purb, GFP_ATOMIC);
541         if (0 != rc) {
542                 if ((-ENODEV != rc) && (-ENOENT != rc)) {
543                         SAM("ERROR: while %i=audio_idle, "
544                                 "usb_submit_urb() failed "
545                                 "with rc:\n", peasycap->audio_idle);
546                 }
547                 switch (rc) {
548                 case -ENODEV:
549                 case -ENOENT:
550                         break;
551                 case -ENOMEM: {
552                         SAM("-ENOMEM\n");
553                         break;
554                 }
555                 case -ENXIO: {
556                         SAM("-ENXIO\n");
557                         break;
558                 }
559                 case -EINVAL: {
560                         SAM("-EINVAL\n");
561                         break;
562                 }
563                 case -EAGAIN: {
564                         SAM("-EAGAIN\n");
565                         break;
566                 }
567                 case -EFBIG: {
568                         SAM("-EFBIG\n");
569                         break;
570                 }
571                 case -EPIPE: {
572                         SAM("-EPIPE\n");
573                         break;
574                 }
575                 case -EMSGSIZE: {
576                         SAM("-EMSGSIZE\n");
577                         break;
578                 }
579                 case -ENOSPC: {
580                         SAM("-ENOSPC\n");
581                         break;
582                 }
583                 case -EPERM: {
584                         SAM("-EPERM\n");
585                         break;
586                 }
587                 default: {
588                         SAM("unknown error: %i\n", rc);
589                         break;
590                 }
591                 }
592                 if (0 < peasycap->audio_isoc_streaming)
593                         (peasycap->audio_isoc_streaming)--;
594         }
595 }
596 return;
597 }
598 /*****************************************************************************/
599 int
600 easycap_alsa_open(struct snd_pcm_substream *pss)
601 {
602 struct snd_pcm *psnd_pcm;
603 struct snd_card *psnd_card;
604 struct easycap *peasycap;
605
606 JOT(4, "\n");
607 if (NULL == pss) {
608         SAY("ERROR:  pss is NULL\n");
609         return -EFAULT;
610 }
611 psnd_pcm = pss->pcm;
612 if (NULL == psnd_pcm) {
613         SAY("ERROR:  psnd_pcm is NULL\n");
614         return -EFAULT;
615 }
616 psnd_card = psnd_pcm->card;
617 if (NULL == psnd_card) {
618         SAY("ERROR:  psnd_card is NULL\n");
619         return -EFAULT;
620 }
621
622 peasycap = psnd_card->private_data;
623 if (NULL == peasycap) {
624         SAY("ERROR:  peasycap is NULL\n");
625         return -EFAULT;
626 }
627 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
628         SAY("ERROR: bad peasycap\n");
629         return -EFAULT;
630 }
631 if (peasycap->psnd_card != psnd_card) {
632         SAM("ERROR: bad peasycap->psnd_card\n");
633         return -EFAULT;
634 }
635 if (NULL != peasycap->psubstream) {
636         SAM("ERROR: bad peasycap->psubstream\n");
637         return -EFAULT;
638 }
639 pss->private_data = peasycap;
640 peasycap->psubstream = pss;
641 pss->runtime->hw = peasycap->alsa_hardware;
642 pss->runtime->private_data = peasycap;
643 pss->private_data = peasycap;
644
645 if (0 != easycap_sound_setup(peasycap)) {
646         JOM(4, "ending unsuccessfully\n");
647         return -EFAULT;
648 }
649 JOM(4, "ending successfully\n");
650 return 0;
651 }
652 /*****************************************************************************/
653 int
654 easycap_alsa_close(struct snd_pcm_substream *pss)
655 {
656 struct easycap *peasycap;
657
658 JOT(4, "\n");
659 if (NULL == pss) {
660         SAY("ERROR:  pss is NULL\n");
661         return -EFAULT;
662 }
663 peasycap = snd_pcm_substream_chip(pss);
664 if (NULL == peasycap) {
665         SAY("ERROR:  peasycap is NULL\n");
666         return -EFAULT;
667 }
668 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
669         SAY("ERROR: bad peasycap\n");
670         return -EFAULT;
671 }
672 pss->private_data = NULL;
673 peasycap->psubstream = (struct snd_pcm_substream *)NULL;
674 JOT(4, "ending successfully\n");
675 return 0;
676 }
677 /*****************************************************************************/
678 int
679 easycap_alsa_hw_params(struct snd_pcm_substream *pss,
680                                                 struct snd_pcm_hw_params *phw)
681 {
682 int rc;
683
684 JOT(4, "%i\n", (params_buffer_bytes(phw)));
685 if (NULL == pss) {
686         SAY("ERROR:  pss is NULL\n");
687         return -EFAULT;
688 }
689 rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
690 if (0 != rc)
691         return rc;
692 return 0;
693 }
694 /*****************************************************************************/
695 int
696 easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
697 {
698 struct snd_pcm_runtime *prt;
699 JOT(4, "\n");
700
701 if (NULL == pss) {
702         SAY("ERROR:  pss is NULL\n");
703         return -EFAULT;
704 }
705 prt = pss->runtime;
706 if (NULL == prt) {
707         SAY("ERROR: substream.runtime is NULL\n");
708         return -EFAULT;
709 }
710 if (prt->dma_area) {
711         if (prt->dma_bytes > sz)
712                 return 0;
713         vfree(prt->dma_area);
714 }
715 prt->dma_area = vmalloc(sz);
716 if (NULL == prt->dma_area)
717         return -ENOMEM;
718 prt->dma_bytes = sz;
719 return 0;
720 }
721 /*****************************************************************************/
722 int
723 easycap_alsa_hw_free(struct snd_pcm_substream *pss)
724 {
725 struct snd_pcm_runtime *prt;
726 JOT(4, "\n");
727
728 if (NULL == pss) {
729         SAY("ERROR:  pss is NULL\n");
730         return -EFAULT;
731 }
732 prt = pss->runtime;
733 if (NULL == prt) {
734         SAY("ERROR: substream.runtime is NULL\n");
735         return -EFAULT;
736 }
737 if (NULL != prt->dma_area) {
738         JOT(8, "0x%08lX=prt->dma_area\n", (unsigned long int)prt->dma_area);
739         vfree(prt->dma_area);
740         prt->dma_area = NULL;
741 } else
742         JOT(8, "dma_area already freed\n");
743 return 0;
744 }
745 /*****************************************************************************/
746 int
747 easycap_alsa_prepare(struct snd_pcm_substream *pss)
748 {
749 struct easycap *peasycap;
750 struct snd_pcm_runtime *prt;
751
752 JOT(4, "\n");
753 if (NULL == pss) {
754         SAY("ERROR:  pss is NULL\n");
755         return -EFAULT;
756 }
757 prt = pss->runtime;
758 peasycap = snd_pcm_substream_chip(pss);
759 if (NULL == peasycap) {
760         SAY("ERROR:  peasycap is NULL\n");
761         return -EFAULT;
762 }
763 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
764         SAY("ERROR: bad peasycap\n");
765         return -EFAULT;
766 }
767
768 JOM(16, "ALSA decides %8i Hz=rate\n", (int)pss->runtime->rate);
769 JOM(16, "ALSA decides %8i   =period_size\n", (int)pss->runtime->period_size);
770 JOM(16, "ALSA decides %8i   =periods\n", (int)pss->runtime->periods);
771 JOM(16, "ALSA decides %8i   =buffer_size\n", (int)pss->runtime->buffer_size);
772 JOM(16, "ALSA decides %8i   =dma_bytes\n", (int)pss->runtime->dma_bytes);
773 JOM(16, "ALSA decides %8i   =boundary\n", (int)pss->runtime->boundary);
774 JOM(16, "ALSA decides %8i   =period_step\n", (int)pss->runtime->period_step);
775 JOM(16, "ALSA decides %8i   =sample_bits\n", (int)pss->runtime->sample_bits);
776 JOM(16, "ALSA decides %8i   =frame_bits\n", (int)pss->runtime->frame_bits);
777 JOM(16, "ALSA decides %8i   =min_align\n", (int)pss->runtime->min_align);
778 JOM(12, "ALSA decides %8i   =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
779 JOM(12, "ALSA decides %8i   =hw_ptr_interrupt\n",
780                                         (int)pss->runtime->hw_ptr_interrupt);
781 if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
782         SAY("MISTAKE:  unexpected ALSA parameters\n");
783         return -ENOENT;
784 }
785 return 0;
786 }
787 /*****************************************************************************/
788 int
789 easycap_alsa_ack(struct snd_pcm_substream *pss)
790 {
791 return 0;
792 }
793 /*****************************************************************************/
794 int
795 easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
796 {
797 struct easycap *peasycap;
798 int retval;
799
800 JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
801                                                 SNDRV_PCM_TRIGGER_STOP);
802 if (NULL == pss) {
803         SAY("ERROR:  pss is NULL\n");
804         return -EFAULT;
805 }
806 peasycap = snd_pcm_substream_chip(pss);
807 if (NULL == peasycap) {
808         SAY("ERROR:  peasycap is NULL\n");
809         return -EFAULT;
810 }
811 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
812         SAY("ERROR: bad peasycap\n");
813         return -EFAULT;
814 }
815
816 switch (cmd) {
817 case SNDRV_PCM_TRIGGER_START: {
818         peasycap->audio_idle = 0;
819         break;
820 }
821 case SNDRV_PCM_TRIGGER_STOP: {
822         peasycap->audio_idle = 1;
823         break;
824 }
825 default:
826         retval = -EINVAL;
827 }
828 return 0;
829 }
830 /*****************************************************************************/
831 snd_pcm_uframes_t
832 easycap_alsa_pointer(struct snd_pcm_substream *pss)
833 {
834 struct easycap *peasycap;
835 snd_pcm_uframes_t offset;
836
837 JOT(16, "\n");
838 if (NULL == pss) {
839         SAY("ERROR:  pss is NULL\n");
840         return -EFAULT;
841 }
842 peasycap = snd_pcm_substream_chip(pss);
843 if (NULL == peasycap) {
844         SAY("ERROR:  peasycap is NULL\n");
845         return -EFAULT;
846 }
847 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
848         SAY("ERROR: bad peasycap\n");
849         return -EFAULT;
850 }
851 if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
852         JOM(8, "returning -EIO because  "
853                         "%i=audio_idle  %i=audio_eof\n",
854                         peasycap->audio_idle, peasycap->audio_eof);
855         return -EIO;
856 }
857 /*---------------------------------------------------------------------------*/
858 if (0 > peasycap->dma_read) {
859         JOM(8, "returning -EBUSY\n");
860         return -EBUSY;
861 }
862 offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
863 JOM(8, "ALSA decides %8i   =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
864 JOM(8, "ALSA decides %8i   =hw_ptr_interrupt\n",
865                                         (int)pss->runtime->hw_ptr_interrupt);
866 JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n",
867                         (int)offset, peasycap->dma_read, peasycap->dma_next);
868 return offset;
869 }
870 /*****************************************************************************/
871 struct page *
872 easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
873 {
874 return vmalloc_to_page(pss->runtime->dma_area + offset);
875 }
876 /*****************************************************************************/
877
878 #else /*!EASYCAP_NEEDS_ALSA*/
879
880 /*****************************************************************************/
881 /****************************                       **************************/
882 /****************************   Open Sound System   **************************/
883 /****************************                       **************************/
884 /*****************************************************************************/
885 /*--------------------------------------------------------------------------*/
886 /*
887  *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
888  */
889 /*--------------------------------------------------------------------------*/
890 const struct file_operations easyoss_fops = {
891         .owner          = THIS_MODULE,
892         .open           = easyoss_open,
893         .release        = easyoss_release,
894 #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
895         .unlocked_ioctl = easyoss_ioctl_noinode,
896 #else
897         .ioctl          = easyoss_ioctl,
898 #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
899         .read           = easyoss_read,
900         .llseek         = no_llseek,
901 };
902 struct usb_class_driver easyoss_class = {
903 .name = "usb/easyoss%d",
904 .fops = &easyoss_fops,
905 .minor_base = USB_SKEL_MINOR_BASE,
906 };
907 /*****************************************************************************/
908 /*---------------------------------------------------------------------------*/
909 /*
910  *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
911  *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
912  *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
913  */
914 /*---------------------------------------------------------------------------*/
915 void
916 easyoss_complete(struct urb *purb)
917 {
918 struct easycap *peasycap;
919 struct data_buffer *paudio_buffer;
920 __u8 *p1, *p2;
921 __s16 s16;
922 int i, j, more, much, leap, rc;
923 #if defined(UPSAMPLE)
924 int k;
925 __s16 oldaudio, newaudio, delta;
926 #endif /*UPSAMPLE*/
927
928 JOT(16, "\n");
929
930 if (NULL == purb) {
931         SAY("ERROR: purb is NULL\n");
932         return;
933 }
934 peasycap = purb->context;
935 if (NULL == peasycap) {
936         SAY("ERROR: peasycap is NULL\n");
937         return;
938 }
939 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
940         SAY("ERROR: bad peasycap\n");
941         return;
942 }
943 much = 0;
944 if (peasycap->audio_idle) {
945         JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
946                         peasycap->audio_idle, peasycap->audio_isoc_streaming);
947         if (peasycap->audio_isoc_streaming) {
948                 rc = usb_submit_urb(purb, GFP_ATOMIC);
949                 if (0 != rc) {
950                         if (-ENODEV != rc && -ENOENT != rc) {
951                                 SAM("ERROR: while %i=audio_idle, "
952                                         "usb_submit_urb() failed with rc:\n",
953                                                         peasycap->audio_idle);
954                         }
955                         switch (rc) {
956                         case -ENODEV:
957                         case -ENOENT:
958                                 break;
959                         case -ENOMEM: {
960                                 SAM("-ENOMEM\n");
961                                 break;
962                         }
963                         case -ENXIO: {
964                                 SAM("-ENXIO\n");
965                                 break;
966                         }
967                         case -EINVAL: {
968                                 SAM("-EINVAL\n");
969                                 break;
970                         }
971                         case -EAGAIN: {
972                                 SAM("-EAGAIN\n");
973                                 break;
974                         }
975                         case -EFBIG: {
976                                 SAM("-EFBIG\n");
977                                 break;
978                         }
979                         case -EPIPE: {
980                                 SAM("-EPIPE\n");
981                                 break;
982                         }
983                         case -EMSGSIZE: {
984                                 SAM("-EMSGSIZE\n");
985                                 break;
986                         }
987                         case -ENOSPC: {
988                                 SAM("-ENOSPC\n");
989                                 break;
990                         }
991                         case -EPERM: {
992                                 SAM("-EPERM\n");
993                                 break;
994                         }
995                         default: {
996                                 SAM("unknown error: %i\n", rc);
997                                 break;
998                         }
999                         }
1000                 }
1001         }
1002 return;
1003 }
1004 /*---------------------------------------------------------------------------*/
1005 if (purb->status) {
1006         if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
1007                 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
1008                 return;
1009         }
1010         SAM("ERROR: non-zero urb status:\n");
1011         switch (purb->status) {
1012         case -EINPROGRESS: {
1013                 SAM("-EINPROGRESS\n");
1014                 break;
1015         }
1016         case -ENOSR: {
1017                 SAM("-ENOSR\n");
1018                 break;
1019         }
1020         case -EPIPE: {
1021                 SAM("-EPIPE\n");
1022                 break;
1023         }
1024         case -EOVERFLOW: {
1025                 SAM("-EOVERFLOW\n");
1026                 break;
1027         }
1028         case -EPROTO: {
1029                 SAM("-EPROTO\n");
1030                 break;
1031         }
1032         case -EILSEQ: {
1033                 SAM("-EILSEQ\n");
1034                 break;
1035         }
1036         case -ETIMEDOUT: {
1037                 SAM("-ETIMEDOUT\n");
1038                 break;
1039         }
1040         case -EMSGSIZE: {
1041                 SAM("-EMSGSIZE\n");
1042                 break;
1043         }
1044         case -EOPNOTSUPP: {
1045                 SAM("-EOPNOTSUPP\n");
1046                 break;
1047         }
1048         case -EPFNOSUPPORT: {
1049                 SAM("-EPFNOSUPPORT\n");
1050                 break;
1051         }
1052         case -EAFNOSUPPORT: {
1053                 SAM("-EAFNOSUPPORT\n");
1054                 break;
1055         }
1056         case -EADDRINUSE: {
1057                 SAM("-EADDRINUSE\n");
1058                 break;
1059         }
1060         case -EADDRNOTAVAIL: {
1061                 SAM("-EADDRNOTAVAIL\n");
1062                 break;
1063         }
1064         case -ENOBUFS: {
1065                 SAM("-ENOBUFS\n");
1066                 break;
1067         }
1068         case -EISCONN: {
1069                 SAM("-EISCONN\n");
1070                 break;
1071         }
1072         case -ENOTCONN: {
1073                 SAM("-ENOTCONN\n");
1074                 break;
1075         }
1076         case -ESHUTDOWN: {
1077                 SAM("-ESHUTDOWN\n");
1078                 break;
1079         }
1080         case -ENOENT: {
1081                 SAM("-ENOENT\n");
1082                 break;
1083         }
1084         case -ECONNRESET: {
1085                 SAM("-ECONNRESET\n");
1086                 break;
1087         }
1088         case -ENOSPC: {
1089                 SAM("ENOSPC\n");
1090                 break;
1091         }
1092         case -EPERM: {
1093                 SAM("-EPERM\n");
1094                 break;
1095         }
1096         default: {
1097                 SAM("unknown error: %i\n", purb->status);
1098                 break;
1099         }
1100         }
1101         goto resubmit;
1102 }
1103 /*---------------------------------------------------------------------------*/
1104 /*
1105  *  PROCEED HERE WHEN NO ERROR
1106  */
1107 /*---------------------------------------------------------------------------*/
1108 #if defined(UPSAMPLE)
1109 oldaudio = peasycap->oldaudio;
1110 #endif /*UPSAMPLE*/
1111
1112 for (i = 0;  i < purb->number_of_packets; i++) {
1113         switch (purb->iso_frame_desc[i].status) {
1114         case  0: {
1115                 break;
1116         }
1117         case -ENODEV: {
1118                 SAM("-ENODEV\n");
1119                 break;
1120         }
1121         case -ENOENT: {
1122                 SAM("-ENOENT\n");
1123                 break;
1124         }
1125         case -EINPROGRESS: {
1126                 SAM("-EINPROGRESS\n");
1127                 break;
1128         }
1129         case -EPROTO: {
1130                 SAM("-EPROTO\n");
1131                 break;
1132         }
1133         case -EILSEQ: {
1134                 SAM("-EILSEQ\n");
1135                 break;
1136         }
1137         case -ETIME: {
1138                 SAM("-ETIME\n");
1139                 break;
1140         }
1141         case -ETIMEDOUT: {
1142                 SAM("-ETIMEDOUT\n");
1143                 break;
1144         }
1145         case -EPIPE: {
1146                 SAM("-EPIPE\n");
1147                 break;
1148         }
1149         case -ECOMM: {
1150                 SAM("-ECOMM\n");
1151                 break;
1152         }
1153         case -ENOSR: {
1154                 SAM("-ENOSR\n");
1155                 break;
1156         }
1157         case -EOVERFLOW: {
1158                 SAM("-EOVERFLOW\n");
1159                 break;
1160         }
1161         case -EREMOTEIO: {
1162                 SAM("-EREMOTEIO\n");
1163                 break;
1164         }
1165         case -EXDEV: {
1166                 SAM("-EXDEV\n");
1167                 break;
1168         }
1169         case -EINVAL: {
1170                 SAM("-EINVAL\n");
1171                 break;
1172         }
1173         case -ECONNRESET: {
1174                 SAM("-ECONNRESET\n");
1175                 break;
1176         }
1177         case -ENOSPC: {
1178                 SAM("-ENOSPC\n");
1179                 break;
1180         }
1181         case -ESHUTDOWN: {
1182                 SAM("-ESHUTDOWN\n");
1183                 break;
1184         }
1185         case -EPERM: {
1186                 SAM("-EPERM\n");
1187                 break;
1188         }
1189         default: {
1190                 SAM("unknown error: %i\n", purb->iso_frame_desc[i].status);
1191                 break;
1192         }
1193         }
1194         if (!purb->iso_frame_desc[i].status) {
1195                 more = purb->iso_frame_desc[i].actual_length;
1196
1197 #if defined(TESTTONE)
1198                 if (!more)
1199                         more = purb->iso_frame_desc[i].length;
1200 #endif
1201
1202                 if (!more)
1203                         peasycap->audio_mt++;
1204                 else {
1205                         if (peasycap->audio_mt) {
1206                                 JOM(12, "%4i empty audio urb frames\n",
1207                                                         peasycap->audio_mt);
1208                                 peasycap->audio_mt = 0;
1209                         }
1210
1211                         p1 = (__u8 *)(purb->transfer_buffer +
1212                                         purb->iso_frame_desc[i].offset);
1213
1214                         leap = 0;
1215                         p1 += leap;
1216                         more -= leap;
1217 /*---------------------------------------------------------------------------*/
1218 /*
1219  *  COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
1220  *  CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
1221  */
1222 /*---------------------------------------------------------------------------*/
1223                         while (more) {
1224                                 if (0 > more) {
1225                                         SAM("MISTAKE: more is negative\n");
1226                                         return;
1227                                 }
1228                                 if (peasycap->audio_buffer_page_many <=
1229                                                         peasycap->audio_fill) {
1230                                         SAM("ERROR: bad "
1231                                                 "peasycap->audio_fill\n");
1232                                         return;
1233                                 }
1234
1235                                 paudio_buffer = &peasycap->audio_buffer
1236                                                         [peasycap->audio_fill];
1237                                 if (PAGE_SIZE < (paudio_buffer->pto -
1238                                                 paudio_buffer->pgo)) {
1239                                         SAM("ERROR: bad paudio_buffer->pto\n");
1240                                         return;
1241                                 }
1242                                 if (PAGE_SIZE == (paudio_buffer->pto -
1243                                                         paudio_buffer->pgo)) {
1244
1245 #if defined(TESTTONE)
1246                                         easyoss_testtone(peasycap,
1247                                                         peasycap->audio_fill);
1248 #endif /*TESTTONE*/
1249
1250                                         paudio_buffer->pto =
1251                                                         paudio_buffer->pgo;
1252                                         (peasycap->audio_fill)++;
1253                                         if (peasycap->
1254                                                 audio_buffer_page_many <=
1255                                                         peasycap->audio_fill)
1256                                                 peasycap->audio_fill = 0;
1257
1258                                         JOM(8, "bumped peasycap->"
1259                                                         "audio_fill to %i\n",
1260                                                         peasycap->audio_fill);
1261
1262                                         paudio_buffer = &peasycap->
1263                                                         audio_buffer
1264                                                         [peasycap->audio_fill];
1265                                         paudio_buffer->pto =
1266                                                         paudio_buffer->pgo;
1267
1268                                         if (!(peasycap->audio_fill %
1269                                                 peasycap->
1270                                                 audio_pages_per_fragment)) {
1271                                                 JOM(12, "wakeup call on wq_"
1272                                                 "audio, %i=frag reading  %i"
1273                                                 "=fragment fill\n",
1274                                                 (peasycap->audio_read /
1275                                                 peasycap->
1276                                                 audio_pages_per_fragment),
1277                                                 (peasycap->audio_fill /
1278                                                 peasycap->
1279                                                 audio_pages_per_fragment));
1280                                                 wake_up_interruptible
1281                                                 (&(peasycap->wq_audio));
1282                                         }
1283                                 }
1284
1285                                 much = PAGE_SIZE - (int)(paudio_buffer->pto -
1286                                                          paudio_buffer->pgo);
1287
1288                                 if (false == peasycap->microphone) {
1289                                         if (much > more)
1290                                                 much = more;
1291
1292                                         memcpy(paudio_buffer->pto, p1, much);
1293                                         p1 += much;
1294                                         more -= much;
1295                                 } else {
1296 #if defined(UPSAMPLE)
1297                                         if (much % 16)
1298                                                 JOM(8, "MISTAKE? much"
1299                                                 " is not divisible by 16\n");
1300                                         if (much > (16 *
1301                                                         more))
1302                                                 much = 16 *
1303                                                         more;
1304                                         p2 = (__u8 *)paudio_buffer->pto;
1305
1306                                         for (j = 0;  j < (much/16);  j++) {
1307                                                 newaudio =  ((int) *p1) - 128;
1308                                                 newaudio = 128 *
1309                                                                 newaudio;
1310
1311                                                 delta = (newaudio - oldaudio)
1312                                                                         / 4;
1313                                                 s16 = oldaudio + delta;
1314
1315                                                 for (k = 0;  k < 4;  k++) {
1316                                                         *p2 = (0x00FF & s16);
1317                                                         *(p2 + 1) = (0xFF00 &
1318                                                                 s16) >> 8;
1319                                                         p2 += 2;
1320                                                         *p2 = (0x00FF & s16);
1321                                                         *(p2 + 1) = (0xFF00 &
1322                                                                 s16) >> 8;
1323                                                         p2 += 2;
1324
1325                                                         s16 += delta;
1326                                                 }
1327                                                 p1++;
1328                                                 more--;
1329                                                 oldaudio = s16;
1330                                         }
1331 #else /*!UPSAMPLE*/
1332                                         if (much > (2 * more))
1333                                                 much = 2 * more;
1334                                         p2 = (__u8 *)paudio_buffer->pto;
1335
1336                                         for (j = 0;  j < (much / 2);  j++) {
1337                                                 s16 =  ((int) *p1) - 128;
1338                                                 s16 = 128 *
1339                                                                 s16;
1340                                                 *p2 = (0x00FF & s16);
1341                                                 *(p2 + 1) = (0xFF00 & s16) >>
1342                                                                         8;
1343                                                 p1++;  p2 += 2;
1344                                                 more--;
1345                                         }
1346 #endif /*UPSAMPLE*/
1347                                 }
1348                                 (paudio_buffer->pto) += much;
1349                         }
1350                 }
1351         } else {
1352                 JOM(12, "discarding audio samples because "
1353                         "%i=purb->iso_frame_desc[i].status\n",
1354                                 purb->iso_frame_desc[i].status);
1355         }
1356
1357 #if defined(UPSAMPLE)
1358 peasycap->oldaudio = oldaudio;
1359 #endif /*UPSAMPLE*/
1360
1361 }
1362 /*---------------------------------------------------------------------------*/
1363 /*
1364  *  RESUBMIT THIS URB
1365  */
1366 /*---------------------------------------------------------------------------*/
1367 resubmit:
1368 if (peasycap->audio_isoc_streaming) {
1369         rc = usb_submit_urb(purb, GFP_ATOMIC);
1370         if (0 != rc) {
1371                 if (-ENODEV != rc && -ENOENT != rc) {
1372                         SAM("ERROR: while %i=audio_idle, "
1373                                 "usb_submit_urb() failed "
1374                                 "with rc:\n", peasycap->audio_idle);
1375                 }
1376                 switch (rc) {
1377                 case -ENODEV:
1378                 case -ENOENT:
1379                         break;
1380                 case -ENOMEM: {
1381                         SAM("-ENOMEM\n");
1382                         break;
1383                 }
1384                 case -ENXIO: {
1385                         SAM("-ENXIO\n");
1386                         break;
1387                 }
1388                 case -EINVAL: {
1389                         SAM("-EINVAL\n");
1390                         break;
1391                 }
1392                 case -EAGAIN: {
1393                         SAM("-EAGAIN\n");
1394                         break;
1395                 }
1396                 case -EFBIG: {
1397                         SAM("-EFBIG\n");
1398                         break;
1399                 }
1400                 case -EPIPE: {
1401                         SAM("-EPIPE\n");
1402                         break;
1403                 }
1404                 case -EMSGSIZE: {
1405                         SAM("-EMSGSIZE\n");
1406                         break;
1407                 }
1408                 case -ENOSPC: {
1409                         SAM("-ENOSPC\n");
1410                         break;
1411                 }
1412                 case -EPERM: {
1413                         SAM("-EPERM\n");
1414                         break;
1415                 }
1416                 default: {
1417                         SAM("unknown error: %i\n", rc);
1418                         break;
1419                 }
1420                 }
1421         }
1422 }
1423 return;
1424 }
1425 /*****************************************************************************/
1426 /*---------------------------------------------------------------------------*/
1427 /*
1428  *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
1429  *  STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
1430  *  HAVE AN IOCTL INTERFACE.
1431  */
1432 /*---------------------------------------------------------------------------*/
1433 int
1434 easyoss_open(struct inode *inode, struct file *file)
1435 {
1436 struct usb_interface *pusb_interface;
1437 struct easycap *peasycap;
1438 int subminor;
1439 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
1440 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
1441 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
1442 struct v4l2_device *pv4l2_device;
1443 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
1444 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
1445 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
1446
1447 JOT(4, "begins\n");
1448
1449 subminor = iminor(inode);
1450
1451 pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
1452 if (NULL == pusb_interface) {
1453         SAY("ERROR: pusb_interface is NULL\n");
1454         SAY("ending unsuccessfully\n");
1455         return -1;
1456 }
1457 peasycap = usb_get_intfdata(pusb_interface);
1458 if (NULL == peasycap) {
1459         SAY("ERROR: peasycap is NULL\n");
1460         SAY("ending unsuccessfully\n");
1461         return -1;
1462 }
1463 /*---------------------------------------------------------------------------*/
1464 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
1465 #
1466 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
1467 #else
1468 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
1469 /*---------------------------------------------------------------------------*/
1470 /*
1471  *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
1472  *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
1473  *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
1474  *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
1475 */
1476 /*---------------------------------------------------------------------------*/
1477 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1478         pv4l2_device = usb_get_intfdata(pusb_interface);
1479         if ((struct v4l2_device *)NULL == pv4l2_device) {
1480                 SAY("ERROR: pv4l2_device is NULL\n");
1481                 return -EFAULT;
1482         }
1483         peasycap = (struct easycap *)
1484                 container_of(pv4l2_device, struct easycap, v4l2_device);
1485 }
1486 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
1487 #
1488 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
1489 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
1490 /*---------------------------------------------------------------------------*/
1491 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1492         SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1493         return -EFAULT;
1494 }
1495 /*---------------------------------------------------------------------------*/
1496
1497 file->private_data = peasycap;
1498
1499 if (0 != easycap_sound_setup(peasycap)) {
1500         ;
1501         ;
1502 }
1503 return 0;
1504 }
1505 /*****************************************************************************/
1506 int
1507 easyoss_release(struct inode *inode, struct file *file)
1508 {
1509 struct easycap *peasycap;
1510
1511 JOT(4, "begins\n");
1512
1513 peasycap = file->private_data;
1514 if (NULL == peasycap) {
1515         SAY("ERROR:  peasycap is NULL.\n");
1516         return -EFAULT;
1517 }
1518 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1519         SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1520         return -EFAULT;
1521 }
1522 if (0 != kill_audio_urbs(peasycap)) {
1523         SAM("ERROR: kill_audio_urbs() failed\n");
1524         return -EFAULT;
1525 }
1526 JOM(4, "ending successfully\n");
1527 return 0;
1528 }
1529 /*****************************************************************************/
1530 ssize_t
1531 easyoss_read(struct file *file, char __user *puserspacebuffer,
1532                                                 size_t kount, loff_t *poff)
1533 {
1534 struct timeval timeval;
1535 long long int above, below, mean;
1536 struct signed_div_result sdr;
1537 unsigned char *p0;
1538 long int kount1, more, rc, l0, lm;
1539 int fragment, kd;
1540 struct easycap *peasycap;
1541 struct data_buffer *pdata_buffer;
1542 size_t szret;
1543
1544 /*---------------------------------------------------------------------------*/
1545 /*
1546  *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
1547  *
1548  ******************************************************************************
1549  *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
1550  *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
1551  ******************************************************************************
1552  */
1553 /*---------------------------------------------------------------------------*/
1554
1555 JOT(8, "%5i=kount  %5i=*poff\n", (int)kount, (int)(*poff));
1556
1557 if (NULL == file) {
1558         SAY("ERROR:  file is NULL\n");
1559         return -ERESTARTSYS;
1560 }
1561 peasycap = file->private_data;
1562 if (NULL == peasycap) {
1563         SAY("ERROR in easyoss_read(): peasycap is NULL\n");
1564         return -EFAULT;
1565 }
1566 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1567         SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1568         return -EFAULT;
1569 }
1570 if (NULL == peasycap->pusb_device) {
1571         SAY("ERROR: peasycap->pusb_device is NULL\n");
1572         return -EFAULT;
1573 }
1574 kd = isdongle(peasycap);
1575 if (0 <= kd && DONGLE_MANY > kd) {
1576         if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
1577                 SAY("ERROR: "
1578                 "cannot lock easycapdc60_dongle[%i].mutex_audio\n", kd);
1579                 return -ERESTARTSYS;
1580         }
1581         JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
1582 /*---------------------------------------------------------------------------*/
1583 /*
1584  *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
1585  *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1586  *  IF NECESSARY, BAIL OUT.
1587 */
1588 /*---------------------------------------------------------------------------*/
1589         if (kd != isdongle(peasycap))
1590                 return -ERESTARTSYS;
1591         if (NULL == file) {
1592                 SAY("ERROR:  file is NULL\n");
1593                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1594                 return -ERESTARTSYS;
1595         }
1596         peasycap = file->private_data;
1597         if (NULL == peasycap) {
1598                 SAY("ERROR:  peasycap is NULL\n");
1599                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1600                 return -ERESTARTSYS;
1601         }
1602         if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1603                 SAY("ERROR: bad peasycap: 0x%08lX\n",
1604                                                 (unsigned long int) peasycap);
1605                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1606                 return -ERESTARTSYS;
1607         }
1608         if (NULL == peasycap->pusb_device) {
1609                 SAM("ERROR: peasycap->pusb_device is NULL\n");
1610                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1611                 return -ERESTARTSYS;
1612         }
1613 } else {
1614 /*---------------------------------------------------------------------------*/
1615 /*
1616  *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1617  *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
1618 */
1619 /*---------------------------------------------------------------------------*/
1620         return -ERESTARTSYS;
1621 }
1622 /*---------------------------------------------------------------------------*/
1623 if (file->f_flags & O_NONBLOCK)
1624         JOT(16, "NONBLOCK  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
1625 else
1626         JOT(8, "BLOCKING  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
1627
1628 if ((0 > peasycap->audio_read) ||
1629                 (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
1630         SAM("ERROR: peasycap->audio_read out of range\n");
1631         mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1632         return -EFAULT;
1633 }
1634 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
1635 if ((struct data_buffer *)NULL == pdata_buffer) {
1636         SAM("ERROR: pdata_buffer is NULL\n");
1637         mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1638         return -EFAULT;
1639 }
1640 JOM(12, "before wait, %i=frag read  %i=frag fill\n",
1641                 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
1642                 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
1643 fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
1644 while ((fragment == (peasycap->audio_fill /
1645                                 peasycap->audio_pages_per_fragment)) ||
1646                 (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
1647         if (file->f_flags & O_NONBLOCK) {
1648                 JOM(16, "returning -EAGAIN as instructed\n");
1649                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1650                 return -EAGAIN;
1651         }
1652         rc = wait_event_interruptible(peasycap->wq_audio,
1653                 (peasycap->audio_idle  || peasycap->audio_eof   ||
1654                 ((fragment != (peasycap->audio_fill /
1655                                 peasycap->audio_pages_per_fragment)) &&
1656                 (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
1657         if (0 != rc) {
1658                 SAM("aborted by signal\n");
1659                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1660                 return -ERESTARTSYS;
1661         }
1662         if (peasycap->audio_eof) {
1663                 JOM(8, "returning 0 because  %i=audio_eof\n",
1664                                                         peasycap->audio_eof);
1665                 kill_audio_urbs(peasycap);
1666                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1667                 return 0;
1668         }
1669         if (peasycap->audio_idle) {
1670                 JOM(16, "returning 0 because  %i=audio_idle\n",
1671                                                         peasycap->audio_idle);
1672                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1673                 return 0;
1674         }
1675         if (!peasycap->audio_isoc_streaming) {
1676                 JOM(16, "returning 0 because audio urbs not streaming\n");
1677                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1678                 return 0;
1679         }
1680 }
1681 JOM(12, "after  wait, %i=frag read  %i=frag fill\n",
1682                 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
1683                 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
1684 szret = (size_t)0;
1685 fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
1686 while (fragment == (peasycap->audio_read /
1687                                 peasycap->audio_pages_per_fragment)) {
1688         if (NULL == pdata_buffer->pgo) {
1689                 SAM("ERROR: pdata_buffer->pgo is NULL\n");
1690                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1691                 return -EFAULT;
1692         }
1693         if (NULL == pdata_buffer->pto) {
1694                 SAM("ERROR: pdata_buffer->pto is NULL\n");
1695                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1696                 return -EFAULT;
1697         }
1698         kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
1699         if (0 > kount1) {
1700                 SAM("MISTAKE: kount1 is negative\n");
1701                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1702                 return -ERESTARTSYS;
1703         }
1704         if (!kount1) {
1705                 (peasycap->audio_read)++;
1706                 if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
1707                         peasycap->audio_read = 0;
1708                 JOM(12, "bumped peasycap->audio_read to %i\n",
1709                                                 peasycap->audio_read);
1710
1711                 if (fragment != (peasycap->audio_read /
1712                                         peasycap->audio_pages_per_fragment))
1713                         break;
1714
1715                 if ((0 > peasycap->audio_read) ||
1716                         (peasycap->audio_buffer_page_many <=
1717                                         peasycap->audio_read)) {
1718                         SAM("ERROR: peasycap->audio_read out of range\n");
1719                         mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1720                         return -EFAULT;
1721                 }
1722                 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
1723                 if ((struct data_buffer *)NULL == pdata_buffer) {
1724                         SAM("ERROR: pdata_buffer is NULL\n");
1725                         mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1726                         return -EFAULT;
1727                 }
1728                 if (NULL == pdata_buffer->pgo) {
1729                         SAM("ERROR: pdata_buffer->pgo is NULL\n");
1730                         mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1731                         return -EFAULT;
1732                 }
1733                 if (NULL == pdata_buffer->pto) {
1734                         SAM("ERROR: pdata_buffer->pto is NULL\n");
1735                         mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1736                         return -EFAULT;
1737                 }
1738                 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
1739         }
1740         JOM(12, "ready  to send %li bytes\n", (long int) kount1);
1741         JOM(12, "still  to send %li bytes\n", (long int) kount);
1742         more = kount1;
1743         if (more > kount)
1744                 more = kount;
1745         JOM(12, "agreed to send %li bytes from page %i\n",
1746                                                 more, peasycap->audio_read);
1747         if (!more)
1748                 break;
1749
1750 /*---------------------------------------------------------------------------*/
1751 /*
1752  *  ACCUMULATE DYNAMIC-RANGE INFORMATION
1753  */
1754 /*---------------------------------------------------------------------------*/
1755         p0 = (unsigned char *)pdata_buffer->pgo;  l0 = 0;  lm = more/2;
1756         while (l0 < lm) {
1757                 SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau,
1758                                 &peasycap->audio_square);  l0++;  p0 += 2;
1759         }
1760 /*---------------------------------------------------------------------------*/
1761         rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
1762         if (0 != rc) {
1763                 SAM("ERROR: copy_to_user() returned %li\n", rc);
1764                 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1765                 return -EFAULT;
1766         }
1767         *poff += (loff_t)more;
1768         szret += (size_t)more;
1769         pdata_buffer->pto += more;
1770         puserspacebuffer += more;
1771         kount -= (size_t)more;
1772 }
1773 JOM(12, "after  read, %i=frag read  %i=frag fill\n",
1774                 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
1775                 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
1776 if (kount < 0) {
1777         SAM("MISTAKE:  %li=kount  %li=szret\n",
1778                                         (long int)kount, (long int)szret);
1779 }
1780 /*---------------------------------------------------------------------------*/
1781 /*
1782  *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
1783  */
1784 /*---------------------------------------------------------------------------*/
1785 if (peasycap->audio_sample) {
1786         below = peasycap->audio_sample;
1787         above = peasycap->audio_square;
1788         sdr = signed_div(above, below);
1789         above = sdr.quotient;
1790         mean = peasycap->audio_niveau;
1791         sdr = signed_div(mean, peasycap->audio_sample);
1792
1793         JOM(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n",
1794                                 sdr.quotient, above, peasycap->audio_sample);
1795
1796         sdr = signed_div(above, 32768);
1797         JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
1798 }
1799 /*---------------------------------------------------------------------------*/
1800 /*
1801  *  UPDATE THE AUDIO CLOCK
1802  */
1803 /*---------------------------------------------------------------------------*/
1804 do_gettimeofday(&timeval);
1805 if (!peasycap->timeval1.tv_sec) {
1806         peasycap->audio_bytes = 0;
1807         peasycap->timeval3 = timeval;
1808         peasycap->timeval1 = peasycap->timeval3;
1809         sdr.quotient = 192000;
1810 } else {
1811         peasycap->audio_bytes += (long long int) szret;
1812         below = ((long long int)(1000000)) *
1813                 ((long long int)(timeval.tv_sec  -
1814                                                 peasycap->timeval3.tv_sec)) +
1815                 (long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
1816         above = 1000000 * ((long long int) peasycap->audio_bytes);
1817
1818         if (below)
1819                 sdr = signed_div(above, below);
1820         else
1821                 sdr.quotient = 192000;
1822 }
1823 JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
1824 peasycap->dnbydt = sdr.quotient;
1825
1826 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
1827 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
1828 JOM(8, "returning %li\n", (long int)szret);
1829 return szret;
1830 }
1831 /*****************************************************************************/
1832
1833 #endif /*!EASYCAP_NEEDS_ALSA*/
1834
1835 /*****************************************************************************/
1836 /*****************************************************************************/
1837 /*****************************************************************************/
1838 /*****************************************************************************/
1839 /*****************************************************************************/
1840 /*****************************************************************************/
1841 /*---------------------------------------------------------------------------*/
1842 /*
1843  *  COMMON AUDIO INITIALIZATION
1844  */
1845 /*---------------------------------------------------------------------------*/
1846 int
1847 easycap_sound_setup(struct easycap *peasycap)
1848 {
1849 int rc;
1850
1851 JOM(4, "starting initialization\n");
1852
1853 if (NULL == peasycap) {
1854         SAY("ERROR:  peasycap is NULL.\n");
1855         return -EFAULT;
1856 }
1857 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1858         SAM("ERROR: peasycap->pusb_device is NULL\n");
1859         return -ENODEV;
1860 }
1861 JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
1862
1863 rc = audio_setup(peasycap);
1864 JOM(8, "audio_setup() returned %i\n", rc);
1865
1866 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1867         SAM("ERROR: peasycap->pusb_device has become NULL\n");
1868         return -ENODEV;
1869 }
1870 /*---------------------------------------------------------------------------*/
1871 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1872         SAM("ERROR: peasycap->pusb_device has become NULL\n");
1873         return -ENODEV;
1874 }
1875 rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
1876                                         peasycap->audio_altsetting_on);
1877 JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
1878                                         peasycap->audio_altsetting_on, rc);
1879
1880 rc = wakeup_device(peasycap->pusb_device);
1881 JOM(8, "wakeup_device() returned %i\n", rc);
1882
1883 peasycap->audio_eof = 0;
1884 peasycap->audio_idle = 0;
1885
1886 peasycap->timeval1.tv_sec  = 0;
1887 peasycap->timeval1.tv_usec = 0;
1888
1889 submit_audio_urbs(peasycap);
1890
1891 JOM(4, "finished initialization\n");
1892 return 0;
1893 }
1894 /*****************************************************************************/
1895 /*---------------------------------------------------------------------------*/
1896 /*
1897  *  SUBMIT ALL AUDIO URBS.
1898  */
1899 /*---------------------------------------------------------------------------*/
1900 int
1901 submit_audio_urbs(struct easycap *peasycap)
1902 {
1903 struct data_urb *pdata_urb;
1904 struct urb *purb;
1905 struct list_head *plist_head;
1906 int j, isbad, nospc, m, rc;
1907 int isbuf;
1908
1909 if (NULL == peasycap) {
1910         SAY("ERROR: peasycap is NULL\n");
1911         return -EFAULT;
1912 }
1913 if ((struct list_head *)NULL == peasycap->purb_audio_head) {
1914         SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
1915         return -EFAULT;
1916 }
1917 if ((struct usb_device *)NULL == peasycap->pusb_device) {
1918         SAM("ERROR: peasycap->pusb_device is NULL\n");
1919         return -EFAULT;
1920 }
1921 if (!peasycap->audio_isoc_streaming) {
1922         JOM(4, "initial submission of all audio urbs\n");
1923         rc = usb_set_interface(peasycap->pusb_device,
1924                                         peasycap->audio_interface,
1925                                         peasycap->audio_altsetting_on);
1926         JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
1927                                         peasycap->audio_interface,
1928                                         peasycap->audio_altsetting_on, rc);
1929
1930         isbad = 0;  nospc = 0;  m = 0;
1931         list_for_each(plist_head, (peasycap->purb_audio_head)) {
1932                 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
1933                 if (NULL != pdata_urb) {
1934                         purb = pdata_urb->purb;
1935                         if (NULL != purb) {
1936                                 isbuf = pdata_urb->isbuf;
1937
1938                                 purb->interval = 1;
1939                                 purb->dev = peasycap->pusb_device;
1940                                 purb->pipe =
1941                                         usb_rcvisocpipe(peasycap->pusb_device,
1942                                         peasycap->audio_endpointnumber);
1943                                 purb->transfer_flags = URB_ISO_ASAP;
1944                                 purb->transfer_buffer =
1945                                         peasycap->audio_isoc_buffer[isbuf].pgo;
1946                                 purb->transfer_buffer_length =
1947                                         peasycap->audio_isoc_buffer_size;
1948 #if defined(EASYCAP_NEEDS_ALSA)
1949                                 purb->complete = easycap_alsa_complete;
1950 #else
1951                                 purb->complete = easyoss_complete;
1952 #endif /*EASYCAP_NEEDS_ALSA*/
1953                                 purb->context = peasycap;
1954                                 purb->start_frame = 0;
1955                                 purb->number_of_packets =
1956                                         peasycap->audio_isoc_framesperdesc;
1957                                 for (j = 0;  j < peasycap->
1958                                                 audio_isoc_framesperdesc;
1959                                                                         j++) {
1960                                         purb->iso_frame_desc[j].offset = j *
1961                                                 peasycap->
1962                                                 audio_isoc_maxframesize;
1963                                         purb->iso_frame_desc[j].length =
1964                                                 peasycap->
1965                                                 audio_isoc_maxframesize;
1966                                 }
1967
1968                                 rc = usb_submit_urb(purb, GFP_KERNEL);
1969                                 if (0 != rc) {
1970                                         isbad++;
1971                                         SAM("ERROR: usb_submit_urb() failed"
1972                                                         " for urb with rc:\n");
1973                                         switch (rc) {
1974                                         case -ENODEV: {
1975                                                 SAM("-ENODEV\n");
1976                                                 break;
1977                                         }
1978                                         case -ENOENT: {
1979                                                 SAM("-ENOENT\n");
1980                                                 break;
1981                                         }
1982                                         case -ENOMEM: {
1983                                                 SAM("-ENOMEM\n");
1984                                                 break;
1985                                         }
1986                                         case -ENXIO: {
1987                                                 SAM("-ENXIO\n");
1988                                                 break;
1989                                         }
1990                                         case -EINVAL: {
1991                                                 SAM("-EINVAL\n");
1992                                                 break;
1993                                         }
1994                                         case -EAGAIN: {
1995                                                 SAM("-EAGAIN\n");
1996                                                 break;
1997                                         }
1998                                         case -EFBIG: {
1999                                                 SAM("-EFBIG\n");
2000                                                 break;
2001                                         }
2002                                         case -EPIPE: {
2003                                                 SAM("-EPIPE\n");
2004                                                 break;
2005                                         }
2006                                         case -EMSGSIZE: {
2007                                                 SAM("-EMSGSIZE\n");
2008                                                 break;
2009                                         }
2010                                         case -ENOSPC: {
2011                                                 nospc++;
2012                                                 break;
2013                                         }
2014                                         case -EPERM: {
2015                                                 SAM("-EPERM\n");
2016                                                 break;
2017                                         }
2018                                         default: {
2019                                                 SAM("unknown error: %i\n", rc);
2020                                                 break;
2021                                         }
2022                                         }
2023                                 } else {
2024                                          m++;
2025                                 }
2026                         } else {
2027                                 isbad++;
2028                         }
2029                 } else {
2030                         isbad++;
2031                 }
2032         }
2033         if (nospc) {
2034                 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
2035                 SAM(".....  possibly inadequate USB bandwidth\n");
2036                 peasycap->audio_eof = 1;
2037         }
2038         if (isbad) {
2039                 JOM(4, "attempting cleanup instead of submitting\n");
2040                 list_for_each(plist_head, (peasycap->purb_audio_head)) {
2041                         pdata_urb = list_entry(plist_head, struct data_urb,
2042                                                                 list_head);
2043                         if (NULL != pdata_urb) {
2044                                 purb = pdata_urb->purb;
2045                                 if (NULL != purb)
2046                                         usb_kill_urb(purb);
2047                         }
2048                 }
2049                 peasycap->audio_isoc_streaming = 0;
2050         } else {
2051                 peasycap->audio_isoc_streaming = m;
2052                 JOM(4, "submitted %i audio urbs\n", m);
2053         }
2054 } else
2055         JOM(4, "already streaming audio urbs\n");
2056
2057 return 0;
2058 }
2059 /*****************************************************************************/
2060 /*---------------------------------------------------------------------------*/
2061 /*
2062  *  KILL ALL AUDIO URBS.
2063  */
2064 /*---------------------------------------------------------------------------*/
2065 int
2066 kill_audio_urbs(struct easycap *peasycap)
2067 {
2068 int m;
2069 struct list_head *plist_head;
2070 struct data_urb *pdata_urb;
2071
2072 if (NULL == peasycap) {
2073         SAY("ERROR: peasycap is NULL\n");
2074         return -EFAULT;
2075 }
2076 if (peasycap->audio_isoc_streaming) {
2077         if ((struct list_head *)NULL != peasycap->purb_audio_head) {
2078                 peasycap->audio_isoc_streaming = 0;
2079                 JOM(4, "killing audio urbs\n");
2080                 m = 0;
2081                 list_for_each(plist_head, (peasycap->purb_audio_head)) {
2082                         pdata_urb = list_entry(plist_head, struct data_urb,
2083                                                                 list_head);
2084                         if ((struct data_urb *)NULL != pdata_urb) {
2085                                 if ((struct urb *)NULL != pdata_urb->purb) {
2086                                         usb_kill_urb(pdata_urb->purb);
2087                                         m++;
2088                                 }
2089                         }
2090                 }
2091                 JOM(4, "%i audio urbs killed\n", m);
2092         } else {
2093                 SAM("ERROR: peasycap->purb_audio_head is NULL\n");
2094                 return -EFAULT;
2095         }
2096 } else {
2097         JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n",
2098                                         peasycap->audio_isoc_streaming);
2099 }
2100 return 0;
2101 }
2102 /*****************************************************************************/