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