• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/easycap/
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_debug.h"
33#include "easycap_sound.h"
34
35/*****************************************************************************/
36/*---------------------------------------------------------------------------*/
37/*
38 *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
39 *  PROVIDED peasycap->audio_idle IS ZER0.  REGARDLESS OF THIS BEING TRUE,
40 *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
41 */
42/*---------------------------------------------------------------------------*/
43void
44easysnd_complete(struct urb *purb)
45{
46static int mt;
47struct easycap *peasycap;
48struct data_buffer *paudio_buffer;
49char errbuf[16];
50__u8 *p1, *p2;
51__s16 s16;
52int i, j, more, much, leap, rc;
53#if defined(UPSAMPLE)
54int k;
55__s16 oldaudio, newaudio, delta;
56#endif /*UPSAMPLE*/
57
58JOT(16, "\n");
59
60if (NULL == purb) {
61	SAY("ERROR: purb is NULL\n");
62	return;
63}
64peasycap = purb->context;
65if (NULL == peasycap) {
66	SAY("ERROR: peasycap is NULL\n");
67	return;
68}
69much = 0;
70
71
72if (peasycap->audio_idle) {
73	JOT(16, "%i=audio_idle  %i=audio_isoc_streaming\n", \
74			peasycap->audio_idle, peasycap->audio_isoc_streaming);
75	if (peasycap->audio_isoc_streaming) {
76		rc = usb_submit_urb(purb, GFP_ATOMIC);
77		if (0 != rc) {
78			SAY("ERROR: while %i=audio_idle, " \
79					"usb_submit_urb() failed with rc:\n", \
80							peasycap->audio_idle);
81			switch (rc) {
82			case -ENOMEM: {
83				SAY("ENOMEM\n");    break;
84			}
85			case -ENODEV: {
86				SAY("ENODEV\n");    break;
87			}
88			case -ENXIO: {
89				SAY("ENXIO\n");     break;
90			}
91			case -EINVAL: {
92				SAY("EINVAL\n");    break;
93			}
94			case -EAGAIN: {
95				SAY("EAGAIN\n");    break;
96			}
97			case -EFBIG: {
98				SAY("EFBIG\n");     break;
99			}
100			case -EPIPE: {
101				SAY("EPIPE\n");     break;
102			}
103			case -EMSGSIZE: {
104				SAY("EMSGSIZE\n");  break;
105			}
106			case -ENOSPC: {
107				SAY("ENOSPC\n");  break;
108			}
109			default: {
110				SAY("0x%08X\n", rc); break;
111			}
112			}
113		}
114	}
115return;
116}
117/*---------------------------------------------------------------------------*/
118if (purb->status) {
119	if (-ESHUTDOWN == purb->status) {
120		JOT(16, "immediate return because -ESHUTDOWN=purb->status\n");
121		return;
122	}
123	SAY("ERROR: non-zero urb status:\n");
124	switch (purb->status) {
125	case -EINPROGRESS: {
126		SAY("-EINPROGRESS\n"); break;
127	}
128	case -ENOSR: {
129		SAY("-ENOSR\n"); break;
130	}
131	case -EPIPE: {
132		SAY("-EPIPE\n"); break;
133	}
134	case -EOVERFLOW: {
135		SAY("-EOVERFLOW\n"); break;
136	}
137	case -EPROTO: {
138		SAY("-EPROTO\n"); break;
139	}
140	case -EILSEQ: {
141		SAY("-EILSEQ\n"); break;
142	}
143	case -ETIMEDOUT: {
144		SAY("-ETIMEDOUT\n"); break;
145	}
146	case -EMSGSIZE: {
147		SAY("-EMSGSIZE\n"); break;
148	}
149	case -EOPNOTSUPP: {
150		SAY("-EOPNOTSUPP\n"); break;
151	}
152	case -EPFNOSUPPORT: {
153		SAY("-EPFNOSUPPORT\n"); break;
154	}
155	case -EAFNOSUPPORT: {
156		SAY("-EAFNOSUPPORT\n"); break;
157	}
158	case -EADDRINUSE: {
159		SAY("-EADDRINUSE\n"); break;
160	}
161	case -EADDRNOTAVAIL: {
162		SAY("-EADDRNOTAVAIL\n"); break;
163	}
164	case -ENOBUFS: {
165		SAY("-ENOBUFS\n"); break;
166	}
167	case -EISCONN: {
168		SAY("-EISCONN\n"); break;
169	}
170	case -ENOTCONN: {
171		SAY("-ENOTCONN\n"); break;
172	}
173	case -ESHUTDOWN: {
174		SAY("-ESHUTDOWN\n"); break;
175	}
176	case -ENOENT: {
177		SAY("-ENOENT\n"); break;
178	}
179	case -ECONNRESET: {
180		SAY("-ECONNRESET\n"); break;
181	}
182	case -ENOSPC: {
183		SAY("ENOSPC\n");  break;
184	}
185	default: {
186		SAY("unknown error code 0x%08X\n", purb->status); break;
187	}
188	}
189/*---------------------------------------------------------------------------*/
190/*
191 *  RESUBMIT THIS URB AFTER AN ERROR
192 *
193 *  (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH)
194 */
195/*---------------------------------------------------------------------------*/
196	if (peasycap->audio_isoc_streaming) {
197		rc = usb_submit_urb(purb, GFP_ATOMIC);
198		if (0 != rc) {
199			SAY("ERROR: while %i=audio_idle, usb_submit_urb() "
200				"failed with rc:\n", peasycap->audio_idle);
201			switch (rc) {
202			case -ENOMEM: {
203				SAY("ENOMEM\n");    break;
204			}
205			case -ENODEV: {
206				SAY("ENODEV\n");    break;
207			}
208			case -ENXIO: {
209				SAY("ENXIO\n");     break;
210			}
211			case -EINVAL: {
212				SAY("EINVAL\n");    break;
213			}
214			case -EAGAIN: {
215				SAY("EAGAIN\n");    break;
216			}
217			case -EFBIG: {
218				SAY("EFBIG\n");     break;
219			}
220			case -EPIPE: {
221				SAY("EPIPE\n");     break;
222			}
223			case -EMSGSIZE: {
224				SAY("EMSGSIZE\n");  break;
225			}
226			default: {
227				SAY("0x%08X\n", rc); break;
228			}
229			}
230		}
231	}
232	return;
233}
234/*---------------------------------------------------------------------------*/
235/*
236 *  PROCEED HERE WHEN NO ERROR
237 */
238/*---------------------------------------------------------------------------*/
239#if defined(UPSAMPLE)
240oldaudio = peasycap->oldaudio;
241#endif /*UPSAMPLE*/
242
243for (i = 0;  i < purb->number_of_packets; i++) {
244	switch (purb->iso_frame_desc[i].status) {
245	case  0: {
246		strcpy(&errbuf[0], "OK"); break;
247	}
248	case -ENOENT: {
249		strcpy(&errbuf[0], "-ENOENT"); break;
250	}
251	case -EINPROGRESS: {
252		strcpy(&errbuf[0], "-EINPROGRESS"); break;
253	}
254	case -EPROTO: {
255		strcpy(&errbuf[0], "-EPROTO"); break;
256	}
257	case -EILSEQ: {
258		strcpy(&errbuf[0], "-EILSEQ"); break;
259	}
260	case -ETIME: {
261		strcpy(&errbuf[0], "-ETIME"); break;
262	}
263	case -ETIMEDOUT: {
264		strcpy(&errbuf[0], "-ETIMEDOUT"); break;
265	}
266	case -EPIPE: {
267		strcpy(&errbuf[0], "-EPIPE"); break;
268	}
269	case -ECOMM: {
270		strcpy(&errbuf[0], "-ECOMM"); break;
271	}
272	case -ENOSR: {
273		strcpy(&errbuf[0], "-ENOSR"); break;
274	}
275	case -EOVERFLOW: {
276		strcpy(&errbuf[0], "-EOVERFLOW"); break;
277	}
278	case -EREMOTEIO: {
279		strcpy(&errbuf[0], "-EREMOTEIO"); break;
280	}
281	case -ENODEV: {
282		strcpy(&errbuf[0], "-ENODEV"); break;
283	}
284	case -EXDEV: {
285		strcpy(&errbuf[0], "-EXDEV"); break;
286	}
287	case -EINVAL: {
288		strcpy(&errbuf[0], "-EINVAL"); break;
289	}
290	case -ECONNRESET: {
291		strcpy(&errbuf[0], "-ECONNRESET"); break;
292	}
293	case -ENOSPC: {
294		strcpy(&errbuf[0], "-ENOSPC"); break;
295	}
296	case -ESHUTDOWN: {
297		strcpy(&errbuf[0], "-ESHUTDOWN"); break;
298	}
299	default: {
300		strcpy(&errbuf[0], "UNKNOWN"); break;
301	}
302	}
303	if ((!purb->iso_frame_desc[i].status) && 0) {
304		JOT(16, "frame[%2i]: %i=status{=%16s}  "  \
305						"%5i=actual  "  \
306						"%5i=length  "  \
307						"%3i=offset\n", \
308				i, purb->iso_frame_desc[i].status, &errbuf[0],
309				purb->iso_frame_desc[i].actual_length,
310				purb->iso_frame_desc[i].length,
311				purb->iso_frame_desc[i].offset);
312	}
313	if (!purb->iso_frame_desc[i].status) {
314		more = purb->iso_frame_desc[i].actual_length;
315
316#if defined(TESTTONE)
317		if (!more)
318			more = purb->iso_frame_desc[i].length;
319#endif
320
321		if (!more)
322			mt++;
323		else {
324			if (mt) {
325				JOT(16, "%4i empty audio urb frames\n", mt);
326				mt = 0;
327			}
328
329			p1 = (__u8 *)(purb->transfer_buffer + \
330					purb->iso_frame_desc[i].offset);
331
332			leap = 0;
333			p1 += leap;
334			more -= leap;
335/*---------------------------------------------------------------------------*/
336/*
337 *  COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
338 *  CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
339 */
340/*---------------------------------------------------------------------------*/
341			while (more) {
342				if (0 > more) {
343					SAY("easysnd_complete: MISTAKE: " \
344							"more is negative\n");
345					return;
346				}
347				if (peasycap->audio_buffer_page_many <= \
348							peasycap->audio_fill) {
349					SAY("ERROR: bad " \
350						"peasycap->audio_fill\n");
351					return;
352				}
353
354				paudio_buffer = &peasycap->audio_buffer\
355							[peasycap->audio_fill];
356				if (PAGE_SIZE < (paudio_buffer->pto - \
357						paudio_buffer->pgo)) {
358					SAY("ERROR: bad paudio_buffer->pto\n");
359					return;
360				}
361				if (PAGE_SIZE == (paudio_buffer->pto - \
362							paudio_buffer->pgo)) {
363
364#if defined(TESTTONE)
365					easysnd_testtone(peasycap, \
366							peasycap->audio_fill);
367#endif /*TESTTONE*/
368
369					paudio_buffer->pto = \
370							paudio_buffer->pgo;
371					(peasycap->audio_fill)++;
372					if (peasycap->\
373						audio_buffer_page_many <= \
374							peasycap->audio_fill)
375						peasycap->audio_fill = 0;
376
377					JOT(12, "bumped peasycap->" \
378							"audio_fill to %i\n", \
379							peasycap->audio_fill);
380
381					paudio_buffer = &peasycap->\
382							audio_buffer\
383							[peasycap->audio_fill];
384					paudio_buffer->pto = \
385							paudio_buffer->pgo;
386
387					if (!(peasycap->audio_fill % \
388						peasycap->\
389						audio_pages_per_fragment)) {
390						JOT(12, "wakeup call on wq_" \
391						"audio, %i=frag reading  %i" \
392						"=fragment fill\n", \
393						(peasycap->audio_read / \
394						peasycap->\
395						audio_pages_per_fragment), \
396						(peasycap->audio_fill / \
397						peasycap->\
398						audio_pages_per_fragment));
399						wake_up_interruptible\
400						(&(peasycap->wq_audio));
401					}
402				}
403
404				much = PAGE_SIZE - (int)(paudio_buffer->pto -\
405							 paudio_buffer->pgo);
406
407				if (false == peasycap->microphone) {
408					if (much > more)
409						much = more;
410
411					memcpy(paudio_buffer->pto, p1, much);
412					p1 += much;
413					more -= much;
414				} else {
415#if defined(UPSAMPLE)
416					if (much % 16)
417						JOT(8, "MISTAKE? much" \
418						" is not divisible by 16\n");
419					if (much > (16 * \
420							more))
421						much = 16 * \
422							more;
423					p2 = (__u8 *)paudio_buffer->pto;
424
425					for (j = 0;  j < (much/16);  j++) {
426						newaudio =  ((int) *p1) - 128;
427						newaudio = 128 * \
428								newaudio;
429
430						delta = (newaudio - oldaudio) \
431									/ 4;
432						s16 = oldaudio + delta;
433
434						for (k = 0;  k < 4;  k++) {
435							*p2 = (0x00FF & s16);
436							*(p2 + 1) = (0xFF00 & \
437								s16) >> 8;
438							p2 += 2;
439							*p2 = (0x00FF & s16);
440							*(p2 + 1) = (0xFF00 & \
441								s16) >> 8;
442							p2 += 2;
443
444							s16 += delta;
445						}
446						p1++;
447						more--;
448						oldaudio = s16;
449					}
450#else
451					if (much > (2 * more))
452						much = 2 * more;
453					p2 = (__u8 *)paudio_buffer->pto;
454
455					for (j = 0;  j < (much / 2);  j++) {
456						s16 =  ((int) *p1) - 128;
457						s16 = 128 * \
458								s16;
459						*p2 = (0x00FF & s16);
460						*(p2 + 1) = (0xFF00 & s16) >> \
461									8;
462						p1++;  p2 += 2;
463						more--;
464					}
465#endif /*UPSAMPLE*/
466				}
467				(paudio_buffer->pto) += much;
468			}
469		}
470	} else {
471		JOT(12, "discarding audio samples because " \
472			"%i=purb->iso_frame_desc[i].status\n", \
473				purb->iso_frame_desc[i].status);
474	}
475
476#if defined(UPSAMPLE)
477peasycap->oldaudio = oldaudio;
478#endif /*UPSAMPLE*/
479
480}
481/*---------------------------------------------------------------------------*/
482/*
483 *  RESUBMIT THIS URB AFTER NO ERROR
484 */
485/*---------------------------------------------------------------------------*/
486if (peasycap->audio_isoc_streaming) {
487	rc = usb_submit_urb(purb, GFP_ATOMIC);
488	if (0 != rc) {
489		SAY("ERROR: while %i=audio_idle, usb_submit_urb() failed " \
490					"with rc:\n", peasycap->audio_idle);
491		switch (rc) {
492		case -ENOMEM: {
493			SAY("ENOMEM\n");    break;
494		}
495		case -ENODEV: {
496			SAY("ENODEV\n");    break;
497		}
498		case -ENXIO: {
499			SAY("ENXIO\n");     break;
500		}
501		case -EINVAL: {
502			SAY("EINVAL\n");    break;
503		}
504		case -EAGAIN: {
505			SAY("EAGAIN\n");    break;
506		}
507		case -EFBIG: {
508			SAY("EFBIG\n");     break;
509		}
510		case -EPIPE: {
511			SAY("EPIPE\n");     break;
512		}
513		case -EMSGSIZE: {
514			SAY("EMSGSIZE\n");  break;
515		}
516		case -ENOSPC: {
517			SAY("ENOSPC\n");  break;
518		}
519		default: {
520			SAY("0x%08X\n", rc); break;
521		}
522		}
523	}
524}
525return;
526}
527/*****************************************************************************/
528/*---------------------------------------------------------------------------*/
529/*
530 *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
531 *  STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
532 *  HAVE AN IOCTL INTERFACE.  THE VIDEO URBS, BY CONTRAST, MUST BE SUBMITTED
533 *  MUCH LATER: SEE COMMENTS IN FILE easycap_main.c.
534 */
535/*---------------------------------------------------------------------------*/
536int
537easysnd_open(struct inode *inode, struct file *file)
538{
539struct usb_interface *pusb_interface;
540struct easycap *peasycap;
541int subminor, rc;
542
543JOT(4, "begins.\n");
544
545subminor = iminor(inode);
546
547pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
548if (NULL == pusb_interface) {
549	SAY("ERROR: pusb_interface is NULL\n");
550	SAY("ending unsuccessfully\n");
551	return -1;
552}
553peasycap = usb_get_intfdata(pusb_interface);
554if (NULL == peasycap) {
555	SAY("ERROR: peasycap is NULL\n");
556	SAY("ending unsuccessfully\n");
557	return -1;
558}
559
560file->private_data = peasycap;
561
562/*---------------------------------------------------------------------------*/
563/*
564 *  INITIALIZATION.
565 */
566/*---------------------------------------------------------------------------*/
567JOT(4, "starting initialization\n");
568
569if ((struct usb_device *)NULL == peasycap->pusb_device) {
570	SAY("ERROR: peasycap->pusb_device is NULL\n");
571	return -EFAULT;
572} else {
573	JOT(16, "0x%08lX=peasycap->pusb_device\n", \
574					(long int)peasycap->pusb_device);
575}
576
577rc = audio_setup(peasycap);
578if (0 <= rc)
579	JOT(8, "audio_setup() returned %i\n", rc);
580else
581	JOT(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc);
582
583if ((struct usb_device *)NULL == peasycap->pusb_device) {
584	SAY("ERROR: peasycap->pusb_device has become NULL\n");
585	return -EFAULT;
586}
587rc = adjust_volume(peasycap, -8192);
588if (0 != rc) {
589	SAY("ERROR: adjust_volume(default) returned %i\n", rc);
590	return -EFAULT;
591}
592/*---------------------------------------------------------------------------*/
593if ((struct usb_device *)NULL == peasycap->pusb_device) {
594	SAY("ERROR: peasycap->pusb_device has become NULL\n");
595	return -EFAULT;
596}
597rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
598					peasycap->audio_altsetting_on);
599JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
600					peasycap->audio_altsetting_on, rc);
601
602if ((struct usb_device *)NULL == peasycap->pusb_device) {
603	SAY("ERROR: peasycap->pusb_device has become NULL\n");
604	return -EFAULT;
605}
606rc = wakeup_device(peasycap->pusb_device);
607if (0 == rc)
608	JOT(8, "wakeup_device() returned %i\n", rc);
609else
610	JOT(8, "easysnd open(): ERROR: wakeup_device() returned %i\n", rc);
611
612if ((struct usb_device *)NULL == peasycap->pusb_device) {
613	SAY("ERROR: peasycap->pusb_device has become NULL\n");
614	return -EFAULT;
615}
616submit_audio_urbs(peasycap);
617peasycap->audio_idle = 0;
618
619peasycap->timeval1.tv_sec  = 0;
620peasycap->timeval1.tv_usec = 0;
621
622JOT(4, "finished initialization\n");
623return 0;
624}
625/*****************************************************************************/
626int
627easysnd_release(struct inode *inode, struct file *file)
628{
629struct easycap *peasycap;
630
631JOT(4, "begins\n");
632
633peasycap = file->private_data;
634if (NULL == peasycap) {
635	SAY("ERROR:  peasycap is NULL.\n");
636	return -EFAULT;
637}
638if (0 != kill_audio_urbs(peasycap)) {
639	SAY("ERROR: kill_audio_urbs() failed\n");
640	return -EFAULT;
641}
642JOT(4, "ending successfully\n");
643return 0;
644}
645/*****************************************************************************/
646ssize_t
647easysnd_read(struct file *file, char __user *puserspacebuffer, \
648						size_t kount, loff_t *poff)
649{
650struct timeval timeval;
651static struct timeval timeval1;
652static long long int audio_bytes, above, below, mean;
653struct signed_div_result sdr;
654unsigned char *p0;
655long int kount1, more, rc, l0, lm;
656int fragment;
657struct easycap *peasycap;
658struct data_buffer *pdata_buffer;
659size_t szret;
660
661/*---------------------------------------------------------------------------*/
662/*
663 *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
664 *
665 ******************************************************************************
666 *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
667 *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
668 ******************************************************************************
669 */
670/*---------------------------------------------------------------------------*/
671
672JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
673
674peasycap = (struct easycap *)(file->private_data);
675if (NULL == peasycap) {
676	SAY("ERROR in easysnd_read(): peasycap is NULL\n");
677	return -EFAULT;
678}
679/*---------------------------------------------------------------------------*/
680if ((0 > peasycap->audio_read) || \
681		(peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
682	SAY("ERROR: peasycap->audio_read out of range\n");
683	return -EFAULT;
684}
685pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
686if ((struct data_buffer *)NULL == pdata_buffer) {
687	SAY("ERROR: pdata_buffer is NULL\n");
688	return -EFAULT;
689}
690JOT(12, "before wait, %i=frag read  %i=frag fill\n", \
691		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
692		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
693fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
694while ((fragment == (peasycap->audio_fill / \
695				peasycap->audio_pages_per_fragment)) || \
696		(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
697	if (file->f_flags & O_NONBLOCK) {
698		JOT(16, "returning -EAGAIN as instructed\n");
699		return -EAGAIN;
700	}
701	rc = wait_event_interruptible(peasycap->wq_audio, \
702		(peasycap->audio_idle  || peasycap->audio_eof   || \
703		((fragment != (peasycap->audio_fill / \
704				peasycap->audio_pages_per_fragment)) && \
705		(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
706	if (0 != rc) {
707		SAY("aborted by signal\n");
708		return -ERESTARTSYS;
709	}
710	if (peasycap->audio_eof) {
711		JOT(8, "returning 0 because  %i=audio_eof\n", \
712							peasycap->audio_eof);
713		kill_audio_urbs(peasycap);
714		msleep(500);
715		return 0;
716	}
717	if (peasycap->audio_idle) {
718		JOT(16, "returning 0 because  %i=audio_idle\n", \
719							peasycap->audio_idle);
720		return 0;
721	}
722	if (!peasycap->audio_isoc_streaming) {
723		JOT(16, "returning 0 because audio urbs not streaming\n");
724		return 0;
725	}
726}
727JOT(12, "after  wait, %i=frag read  %i=frag fill\n", \
728		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
729		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
730szret = (size_t)0;
731while (fragment == (peasycap->audio_read / \
732				peasycap->audio_pages_per_fragment)) {
733	if (NULL == pdata_buffer->pgo) {
734		SAY("ERROR: pdata_buffer->pgo is NULL\n");
735		return -EFAULT;
736	}
737	if (NULL == pdata_buffer->pto) {
738		SAY("ERROR: pdata_buffer->pto is NULL\n");
739		return -EFAULT;
740	}
741	kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
742	if (0 > kount1) {
743		SAY("easysnd_read: MISTAKE: kount1 is negative\n");
744		return -ERESTARTSYS;
745	}
746	if (!kount1) {
747		(peasycap->audio_read)++;
748		if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
749			peasycap->audio_read = 0;
750		JOT(12, "bumped peasycap->audio_read to %i\n", \
751						peasycap->audio_read);
752
753		if (fragment != (peasycap->audio_read / \
754					peasycap->audio_pages_per_fragment))
755			break;
756
757		if ((0 > peasycap->audio_read) || \
758			(peasycap->audio_buffer_page_many <= \
759					peasycap->audio_read)) {
760			SAY("ERROR: peasycap->audio_read out of range\n");
761			return -EFAULT;
762		}
763		pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
764		if ((struct data_buffer *)NULL == pdata_buffer) {
765			SAY("ERROR: pdata_buffer is NULL\n");
766			return -EFAULT;
767		}
768		if (NULL == pdata_buffer->pgo) {
769			SAY("ERROR: pdata_buffer->pgo is NULL\n");
770			return -EFAULT;
771		}
772		if (NULL == pdata_buffer->pto) {
773			SAY("ERROR: pdata_buffer->pto is NULL\n");
774			return -EFAULT;
775		}
776		kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
777	}
778	JOT(12, "ready  to send %li bytes\n", (long int) kount1);
779	JOT(12, "still  to send %li bytes\n", (long int) kount);
780	more = kount1;
781	if (more > kount)
782		more = kount;
783	JOT(12, "agreed to send %li bytes from page %i\n", \
784						more, peasycap->audio_read);
785	if (!more)
786		break;
787
788/*---------------------------------------------------------------------------*/
789/*
790 *  ACCUMULATE DYNAMIC-RANGE INFORMATION
791 */
792/*---------------------------------------------------------------------------*/
793	p0 = (unsigned char *)pdata_buffer->pgo;  l0 = 0;  lm = more/2;
794	while (l0 < lm) {
795		SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau, \
796				&peasycap->audio_square);  l0++;  p0 += 2;
797	}
798/*---------------------------------------------------------------------------*/
799	rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
800	if (0 != rc) {
801		SAY("ERROR: copy_to_user() returned %li\n", rc);
802		return -EFAULT;
803	}
804	*poff += (loff_t)more;
805	szret += (size_t)more;
806	pdata_buffer->pto += more;
807	puserspacebuffer += more;
808	kount -= (size_t)more;
809}
810JOT(12, "after  read, %i=frag read  %i=frag fill\n", \
811		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
812		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
813if (kount < 0) {
814	SAY("MISTAKE:  %li=kount  %li=szret\n", \
815					(long int)kount, (long int)szret);
816}
817/*---------------------------------------------------------------------------*/
818/*
819 *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
820 */
821/*---------------------------------------------------------------------------*/
822if (peasycap->audio_sample) {
823	below = peasycap->audio_sample;
824	above = peasycap->audio_square;
825	sdr = signed_div(above, below);
826	above = sdr.quotient;
827	mean = peasycap->audio_niveau;
828	sdr = signed_div(mean, peasycap->audio_sample);
829
830	JOT(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n", \
831				sdr.quotient, above, peasycap->audio_sample);
832
833	sdr = signed_div(above, 32768);
834	JOT(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
835}
836/*---------------------------------------------------------------------------*/
837/*
838 *  UPDATE THE AUDIO CLOCK
839 */
840/*---------------------------------------------------------------------------*/
841do_gettimeofday(&timeval);
842if (!peasycap->timeval1.tv_sec) {
843	audio_bytes = 0;
844	timeval1 = timeval;
845
846	if (mutex_lock_interruptible(&(peasycap->mutex_timeval1)))
847		return -ERESTARTSYS;
848	peasycap->timeval1 = timeval1;
849	mutex_unlock(&(peasycap->mutex_timeval1));
850	sdr.quotient = 192000;
851} else {
852	audio_bytes += (long long int) szret;
853	below = ((long long int)(1000000)) * \
854		((long long int)(timeval.tv_sec  - timeval1.tv_sec)) + \
855		(long long int)(timeval.tv_usec - timeval1.tv_usec);
856	above = 1000000 * ((long long int) audio_bytes);
857
858	if (below)
859		sdr = signed_div(above, below);
860	else
861		sdr.quotient = 192000;
862}
863JOT(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
864if (mutex_lock_interruptible(&(peasycap->mutex_timeval1)))
865	return -ERESTARTSYS;
866peasycap->dnbydt = sdr.quotient;
867mutex_unlock(&(peasycap->mutex_timeval1));
868
869JOT(8, "returning %li\n", (long int)szret);
870return szret;
871}
872/*****************************************************************************/
873/*---------------------------------------------------------------------------*/
874/*
875 *  SUBMIT ALL AUDIO URBS.
876 */
877/*---------------------------------------------------------------------------*/
878int
879submit_audio_urbs(struct easycap *peasycap)
880{
881struct data_urb *pdata_urb;
882struct urb *purb;
883struct list_head *plist_head;
884int j, isbad, m, rc;
885int isbuf;
886
887if ((struct list_head *)NULL == peasycap->purb_audio_head) {
888	SAY("ERROR: peasycap->urb_audio_head uninitialized\n");
889	return -EFAULT;
890}
891if ((struct usb_device *)NULL == peasycap->pusb_device) {
892	SAY("ERROR: peasycap->pusb_device is NULL\n");
893	return -EFAULT;
894}
895if (!peasycap->audio_isoc_streaming) {
896	JOT(4, "initial submission of all audio urbs\n");
897	rc = usb_set_interface(peasycap->pusb_device,
898					peasycap->audio_interface, \
899					peasycap->audio_altsetting_on);
900	JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", \
901					peasycap->audio_interface, \
902					peasycap->audio_altsetting_on, rc);
903
904	isbad = 0;  m = 0;
905	list_for_each(plist_head, (peasycap->purb_audio_head)) {
906		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
907		if (NULL != pdata_urb) {
908			purb = pdata_urb->purb;
909			if (NULL != purb) {
910				isbuf = pdata_urb->isbuf;
911
912				purb->interval = 1;
913				purb->dev = peasycap->pusb_device;
914				purb->pipe = \
915					usb_rcvisocpipe(peasycap->pusb_device,\
916					peasycap->audio_endpointnumber);
917				purb->transfer_flags = URB_ISO_ASAP;
918				purb->transfer_buffer = \
919					peasycap->audio_isoc_buffer[isbuf].pgo;
920				purb->transfer_buffer_length = \
921					peasycap->audio_isoc_buffer_size;
922				purb->complete = easysnd_complete;
923				purb->context = peasycap;
924				purb->start_frame = 0;
925				purb->number_of_packets = \
926					peasycap->audio_isoc_framesperdesc;
927				for (j = 0;  j < peasycap->\
928						audio_isoc_framesperdesc; \
929									j++) {
930					purb->iso_frame_desc[j].offset = j * \
931						peasycap->\
932						audio_isoc_maxframesize;
933					purb->iso_frame_desc[j].length = \
934						peasycap->\
935						audio_isoc_maxframesize;
936				}
937
938				rc = usb_submit_urb(purb, GFP_KERNEL);
939				if (0 != rc) {
940					isbad++;
941					SAY("ERROR: usb_submit_urb() failed" \
942							" for urb with rc:\n");
943					switch (rc) {
944					case -ENOMEM: {
945						SAY("ENOMEM\n"); break;
946					}
947					case -ENODEV: {
948						SAY("ENODEV\n"); break;
949					}
950					case -ENXIO: {
951						SAY("ENXIO\n"); break;
952					}
953					case -EINVAL: {
954						SAY("EINVAL\n"); break;
955					}
956					case -EAGAIN: {
957						SAY("EAGAIN\n"); break;
958					}
959					case -EFBIG: {
960						SAY("EFBIG\n"); break;
961					}
962					case -EPIPE: {
963						SAY("EPIPE\n"); break;
964					}
965					case -EMSGSIZE: {
966						SAY("EMSGSIZE\n"); break;
967					}
968					case -ENOSPC: {
969						SAY("ENOSPC\n"); break;
970					}
971					default: {
972						SAY("unknown error code %i\n",\
973								 rc); break;
974					}
975					}
976				} else {
977					 m++;
978				}
979			} else {
980				isbad++;
981			}
982		} else {
983			isbad++;
984		}
985	}
986	if (isbad) {
987		JOT(4, "attempting cleanup instead of submitting\n");
988		list_for_each(plist_head, (peasycap->purb_audio_head)) {
989			pdata_urb = list_entry(plist_head, struct data_urb, \
990								list_head);
991			if (NULL != pdata_urb) {
992				purb = pdata_urb->purb;
993				if (NULL != purb)
994					usb_kill_urb(purb);
995			}
996		}
997		peasycap->audio_isoc_streaming = 0;
998	} else {
999		peasycap->audio_isoc_streaming = 1;
1000		JOT(4, "submitted %i audio urbs\n", m);
1001	}
1002} else
1003	JOT(4, "already streaming audio urbs\n");
1004
1005return 0;
1006}
1007/*****************************************************************************/
1008/*---------------------------------------------------------------------------*/
1009/*
1010 *  KILL ALL AUDIO URBS.
1011 */
1012/*---------------------------------------------------------------------------*/
1013int
1014kill_audio_urbs(struct easycap *peasycap)
1015{
1016int m;
1017struct list_head *plist_head;
1018struct data_urb *pdata_urb;
1019
1020if (peasycap->audio_isoc_streaming) {
1021	if ((struct list_head *)NULL != peasycap->purb_audio_head) {
1022		peasycap->audio_isoc_streaming = 0;
1023		JOT(4, "killing audio urbs\n");
1024		m = 0;
1025		list_for_each(plist_head, (peasycap->purb_audio_head)) {
1026			pdata_urb = list_entry(plist_head, struct data_urb,
1027								list_head);
1028			if ((struct data_urb *)NULL != pdata_urb) {
1029				if ((struct urb *)NULL != pdata_urb->purb) {
1030					usb_kill_urb(pdata_urb->purb);
1031					m++;
1032				}
1033			}
1034		}
1035		JOT(4, "%i audio urbs killed\n", m);
1036	} else {
1037		SAY("ERROR: peasycap->purb_audio_head is NULL\n");
1038		return -EFAULT;
1039	}
1040} else {
1041	JOT(8, "%i=audio_isoc_streaming, no audio urbs killed\n", \
1042					peasycap->audio_isoc_streaming);
1043}
1044return 0;
1045}
1046/*****************************************************************************/
1047