1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31#include "easycap.h"
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51void
52easyoss_complete(struct urb *purb)
53{
54 struct easycap *peasycap;
55 struct data_buffer *paudio_buffer;
56 u8 *p1, *p2;
57 s16 tmp;
58 int i, j, more, much, leap, rc;
59#ifdef UPSAMPLE
60 int k;
61 s16 oldaudio, newaudio, delta;
62#endif
63
64 JOT(16, "\n");
65
66 if (!purb) {
67 SAY("ERROR: purb is NULL\n");
68 return;
69 }
70 peasycap = purb->context;
71 if (!peasycap) {
72 SAY("ERROR: peasycap is NULL\n");
73 return;
74 }
75 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
76 SAY("ERROR: bad peasycap\n");
77 return;
78 }
79 much = 0;
80 if (peasycap->audio_idle) {
81 JOM(16, "%i=audio_idle %i=audio_isoc_streaming\n",
82 peasycap->audio_idle, peasycap->audio_isoc_streaming);
83 if (peasycap->audio_isoc_streaming) {
84 rc = usb_submit_urb(purb, GFP_ATOMIC);
85 if (rc) {
86 if (-ENODEV != rc && -ENOENT != rc) {
87 SAM("ERROR: while %i=audio_idle, "
88 "usb_submit_urb() failed with rc: -%s: %d\n",
89 peasycap->audio_idle,
90 strerror(rc), rc);
91 }
92 }
93 }
94 return;
95 }
96
97 if (purb->status) {
98 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
99 JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
100 return;
101 }
102 SAM("ERROR: non-zero urb status: -%s: %d\n",
103 strerror(purb->status), purb->status);
104 goto resubmit;
105 }
106
107
108
109
110
111#ifdef UPSAMPLE
112 oldaudio = peasycap->oldaudio;
113#endif
114
115 for (i = 0; i < purb->number_of_packets; i++) {
116 if (!purb->iso_frame_desc[i].status) {
117
118 SAM("-%s\n", strerror(purb->iso_frame_desc[i].status));
119
120 more = purb->iso_frame_desc[i].actual_length;
121
122 if (!more)
123 peasycap->audio_mt++;
124 else {
125 if (peasycap->audio_mt) {
126 JOM(12, "%4i empty audio urb frames\n",
127 peasycap->audio_mt);
128 peasycap->audio_mt = 0;
129 }
130
131 p1 = (u8 *)(purb->transfer_buffer + purb->iso_frame_desc[i].offset);
132
133 leap = 0;
134 p1 += leap;
135 more -= leap;
136
137
138
139
140
141
142 while (more) {
143 if (0 > more) {
144 SAM("MISTAKE: more is negative\n");
145 return;
146 }
147 if (peasycap->audio_buffer_page_many <= peasycap->audio_fill) {
148 SAM("ERROR: bad peasycap->audio_fill\n");
149 return;
150 }
151
152 paudio_buffer = &peasycap->audio_buffer[peasycap->audio_fill];
153 if (PAGE_SIZE < (paudio_buffer->pto - paudio_buffer->pgo)) {
154 SAM("ERROR: bad paudio_buffer->pto\n");
155 return;
156 }
157 if (PAGE_SIZE == (paudio_buffer->pto - paudio_buffer->pgo)) {
158
159 paudio_buffer->pto = paudio_buffer->pgo;
160 (peasycap->audio_fill)++;
161 if (peasycap->audio_buffer_page_many <= peasycap->audio_fill)
162 peasycap->audio_fill = 0;
163
164 JOM(8, "bumped peasycap->"
165 "audio_fill to %i\n",
166 peasycap->audio_fill);
167
168 paudio_buffer = &peasycap->audio_buffer[peasycap->audio_fill];
169 paudio_buffer->pto = paudio_buffer->pgo;
170
171 if (!(peasycap->audio_fill % peasycap->audio_pages_per_fragment)) {
172 JOM(12, "wakeup call on wq_audio, %i=frag reading %i=fragment fill\n",
173 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
174 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
175 wake_up_interruptible(&(peasycap->wq_audio));
176 }
177 }
178
179 much = PAGE_SIZE - (int)(paudio_buffer->pto - paudio_buffer->pgo);
180
181 if (!peasycap->microphone) {
182 if (much > more)
183 much = more;
184
185 memcpy(paudio_buffer->pto, p1, much);
186 p1 += much;
187 more -= much;
188 } else {
189#ifdef UPSAMPLE
190 if (much % 16)
191 JOM(8, "MISTAKE? much"
192 " is not divisible by 16\n");
193 if (much > (16 * more))
194 much = 16 * more;
195 p2 = (u8 *)paudio_buffer->pto;
196
197 for (j = 0; j < (much/16); j++) {
198 newaudio = ((int) *p1) - 128;
199 newaudio = 128 * newaudio;
200
201 delta = (newaudio - oldaudio) / 4;
202 tmp = oldaudio + delta;
203
204 for (k = 0; k < 4; k++) {
205 *p2 = (0x00FF & tmp);
206 *(p2 + 1) = (0xFF00 & tmp) >> 8;
207 p2 += 2;
208 *p2 = (0x00FF & tmp);
209 *(p2 + 1) = (0xFF00 & tmp) >> 8;
210 p2 += 2;
211
212 tmp += delta;
213 }
214 p1++;
215 more--;
216 oldaudio = tmp;
217 }
218#else
219 if (much > (2 * more))
220 much = 2 * more;
221 p2 = (u8 *)paudio_buffer->pto;
222
223 for (j = 0; j < (much / 2); j++) {
224 tmp = ((int) *p1) - 128;
225 tmp = 128 * tmp;
226 *p2 = (0x00FF & tmp);
227 *(p2 + 1) = (0xFF00 & tmp) >> 8;
228 p1++;
229 p2 += 2;
230 more--;
231 }
232#endif
233 }
234 (paudio_buffer->pto) += much;
235 }
236 }
237 } else {
238 JOM(12, "discarding audio samples because "
239 "%i=purb->iso_frame_desc[i].status\n",
240 purb->iso_frame_desc[i].status);
241 }
242
243#ifdef UPSAMPLE
244 peasycap->oldaudio = oldaudio;
245#endif
246
247 }
248
249
250
251
252
253resubmit:
254 if (peasycap->audio_isoc_streaming) {
255 rc = usb_submit_urb(purb, GFP_ATOMIC);
256 if (rc) {
257 if (-ENODEV != rc && -ENOENT != rc) {
258 SAM("ERROR: while %i=audio_idle, "
259 "usb_submit_urb() failed "
260 "with rc: -%s: %d\n", peasycap->audio_idle,
261 strerror(rc), rc);
262 }
263 }
264 }
265 return;
266}
267
268
269
270
271
272
273
274
275static int easyoss_open(struct inode *inode, struct file *file)
276{
277 struct usb_interface *pusb_interface;
278 struct easycap *peasycap;
279 int subminor;
280 struct v4l2_device *pv4l2_device;
281
282 JOT(4, "begins\n");
283
284 subminor = iminor(inode);
285
286 pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
287 if (!pusb_interface) {
288 SAY("ERROR: pusb_interface is NULL\n");
289 SAY("ending unsuccessfully\n");
290 return -1;
291 }
292 peasycap = usb_get_intfdata(pusb_interface);
293 if (!peasycap) {
294 SAY("ERROR: peasycap is NULL\n");
295 SAY("ending unsuccessfully\n");
296 return -1;
297 }
298
299
300
301
302
303
304
305
306 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
307 pv4l2_device = usb_get_intfdata(pusb_interface);
308 if (!pv4l2_device) {
309 SAY("ERROR: pv4l2_device is NULL\n");
310 return -EFAULT;
311 }
312 peasycap = container_of(pv4l2_device,
313 struct easycap, v4l2_device);
314 }
315
316 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
317 SAY("ERROR: bad peasycap: %p\n", peasycap);
318 return -EFAULT;
319 }
320
321
322 file->private_data = peasycap;
323
324 if (0 != easycap_sound_setup(peasycap)) {
325 ;
326 ;
327 }
328 return 0;
329}
330
331static int easyoss_release(struct inode *inode, struct file *file)
332{
333 struct easycap *peasycap;
334
335 JOT(4, "begins\n");
336
337 peasycap = file->private_data;
338 if (!peasycap) {
339 SAY("ERROR: peasycap is NULL.\n");
340 return -EFAULT;
341 }
342 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
343 SAY("ERROR: bad peasycap: %p\n", peasycap);
344 return -EFAULT;
345 }
346 if (0 != kill_audio_urbs(peasycap)) {
347 SAM("ERROR: kill_audio_urbs() failed\n");
348 return -EFAULT;
349 }
350 JOM(4, "ending successfully\n");
351 return 0;
352}
353
354static ssize_t easyoss_read(struct file *file, char __user *puserspacebuffer,
355 size_t kount, loff_t *poff)
356{
357 struct timeval timeval;
358 long long int above, below, mean;
359 struct signed_div_result sdr;
360 unsigned char *p0;
361 long int kount1, more, rc, l0, lm;
362 int fragment, kd;
363 struct easycap *peasycap;
364 struct data_buffer *pdata_buffer;
365 size_t szret;
366
367
368
369
370
371
372
373
374
375
376
377
378 JOT(8, "%5zd=kount %5lld=*poff\n", kount, *poff);
379
380 if (!file) {
381 SAY("ERROR: file is NULL\n");
382 return -ERESTARTSYS;
383 }
384 peasycap = file->private_data;
385 if (!peasycap) {
386 SAY("ERROR in easyoss_read(): peasycap is NULL\n");
387 return -EFAULT;
388 }
389 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
390 SAY("ERROR: bad peasycap: %p\n", peasycap);
391 return -EFAULT;
392 }
393 if (!peasycap->pusb_device) {
394 SAY("ERROR: peasycap->pusb_device is NULL\n");
395 return -EFAULT;
396 }
397 kd = isdongle(peasycap);
398 if (0 <= kd && DONGLE_MANY > kd) {
399 if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
400 SAY("ERROR: "
401 "cannot lock dongle[%i].mutex_audio\n", kd);
402 return -ERESTARTSYS;
403 }
404 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
405
406
407
408
409
410
411 if (kd != isdongle(peasycap))
412 return -ERESTARTSYS;
413 if (!file) {
414 SAY("ERROR: file is NULL\n");
415 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
416 return -ERESTARTSYS;
417 }
418 peasycap = file->private_data;
419 if (!peasycap) {
420 SAY("ERROR: peasycap is NULL\n");
421 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
422 return -ERESTARTSYS;
423 }
424 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
425 SAY("ERROR: bad peasycap: %p\n", peasycap);
426 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
427 return -ERESTARTSYS;
428 }
429 if (!peasycap->pusb_device) {
430 SAM("ERROR: peasycap->pusb_device is NULL\n");
431 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
432 return -ERESTARTSYS;
433 }
434 } else {
435
436
437
438
439
440
441 return -ERESTARTSYS;
442 }
443
444 JOT(16, "%sBLOCKING kount=%zd, *poff=%lld\n",
445 (file->f_flags & O_NONBLOCK) ? "NON" : "", kount, *poff);
446
447 if ((0 > peasycap->audio_read) ||
448 (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
449 SAM("ERROR: peasycap->audio_read out of range\n");
450 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
451 return -EFAULT;
452 }
453 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
454 if (!pdata_buffer) {
455 SAM("ERROR: pdata_buffer is NULL\n");
456 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
457 return -EFAULT;
458 }
459 JOM(12, "before wait, %i=frag read %i=frag fill\n",
460 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
461 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
462 fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
463 while ((fragment == (peasycap->audio_fill / peasycap->audio_pages_per_fragment)) ||
464 (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
465 if (file->f_flags & O_NONBLOCK) {
466 JOM(16, "returning -EAGAIN as instructed\n");
467 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
468 return -EAGAIN;
469 }
470 rc = wait_event_interruptible(peasycap->wq_audio,
471 (peasycap->audio_idle || peasycap->audio_eof ||
472 ((fragment !=
473 (peasycap->audio_fill / peasycap->audio_pages_per_fragment)) &&
474 (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
475 if (rc) {
476 SAM("aborted by signal\n");
477 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
478 return -ERESTARTSYS;
479 }
480 if (peasycap->audio_eof) {
481 JOM(8, "returning 0 because %i=audio_eof\n",
482 peasycap->audio_eof);
483 kill_audio_urbs(peasycap);
484 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
485 return 0;
486 }
487 if (peasycap->audio_idle) {
488 JOM(16, "returning 0 because %i=audio_idle\n",
489 peasycap->audio_idle);
490 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
491 return 0;
492 }
493 if (!peasycap->audio_isoc_streaming) {
494 JOM(16, "returning 0 because audio urbs not streaming\n");
495 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
496 return 0;
497 }
498 }
499 JOM(12, "after wait, %i=frag read %i=frag fill\n",
500 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
501 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
502 szret = (size_t)0;
503 fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
504 while (fragment == (peasycap->audio_read / peasycap->audio_pages_per_fragment)) {
505 if (!pdata_buffer->pgo) {
506 SAM("ERROR: pdata_buffer->pgo is NULL\n");
507 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
508 return -EFAULT;
509 }
510 if (!pdata_buffer->pto) {
511 SAM("ERROR: pdata_buffer->pto is NULL\n");
512 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
513 return -EFAULT;
514 }
515 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
516 if (0 > kount1) {
517 SAM("MISTAKE: kount1 is negative\n");
518 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
519 return -ERESTARTSYS;
520 }
521 if (!kount1) {
522 peasycap->audio_read++;
523 if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
524 peasycap->audio_read = 0;
525 JOM(12, "bumped peasycap->audio_read to %i\n",
526 peasycap->audio_read);
527
528 if (fragment != (peasycap->audio_read / peasycap->audio_pages_per_fragment))
529 break;
530
531 if ((0 > peasycap->audio_read) ||
532 (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
533 SAM("ERROR: peasycap->audio_read out of range\n");
534 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
535 return -EFAULT;
536 }
537 pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
538 if (!pdata_buffer) {
539 SAM("ERROR: pdata_buffer is NULL\n");
540 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
541 return -EFAULT;
542 }
543 if (!pdata_buffer->pgo) {
544 SAM("ERROR: pdata_buffer->pgo is NULL\n");
545 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
546 return -EFAULT;
547 }
548 if (!pdata_buffer->pto) {
549 SAM("ERROR: pdata_buffer->pto is NULL\n");
550 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
551 return -EFAULT;
552 }
553 kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
554 }
555 JOM(12, "ready to send %zd bytes\n", kount1);
556 JOM(12, "still to send %li bytes\n", (long int) kount);
557 more = kount1;
558 if (more > kount)
559 more = kount;
560 JOM(12, "agreed to send %li bytes from page %i\n",
561 more, peasycap->audio_read);
562 if (!more)
563 break;
564
565
566
567
568 p0 = (unsigned char *)pdata_buffer->pgo;
569 l0 = 0;
570 lm = more/2;
571 while (l0 < lm) {
572 SUMMER(p0, &peasycap->audio_sample,
573 &peasycap->audio_niveau,
574 &peasycap->audio_square);
575 l0++;
576 p0 += 2;
577 }
578
579 rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
580 if (rc) {
581 SAM("ERROR: copy_to_user() returned %li\n", rc);
582 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
583 return -EFAULT;
584 }
585 *poff += (loff_t)more;
586 szret += (size_t)more;
587 pdata_buffer->pto += more;
588 puserspacebuffer += more;
589 kount -= (size_t)more;
590 }
591 JOM(12, "after read, %i=frag read %i=frag fill\n",
592 (peasycap->audio_read / peasycap->audio_pages_per_fragment),
593 (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
594 if (kount < 0) {
595 SAM("MISTAKE: %li=kount %li=szret\n",
596 (long int)kount, (long int)szret);
597 }
598
599
600
601
602
603 if (peasycap->audio_sample) {
604 below = peasycap->audio_sample;
605 above = peasycap->audio_square;
606 sdr = signed_div(above, below);
607 above = sdr.quotient;
608 mean = peasycap->audio_niveau;
609 sdr = signed_div(mean, peasycap->audio_sample);
610
611 JOM(8, "%8lli=mean %8lli=meansquare after %lli samples, =>\n",
612 sdr.quotient, above, peasycap->audio_sample);
613
614 sdr = signed_div(above, 32768);
615 JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
616 }
617
618
619
620
621
622 do_gettimeofday(&timeval);
623 if (!peasycap->timeval1.tv_sec) {
624 peasycap->audio_bytes = 0;
625 peasycap->timeval3 = timeval;
626 peasycap->timeval1 = peasycap->timeval3;
627 sdr.quotient = 192000;
628 } else {
629 peasycap->audio_bytes += (long long int) szret;
630 below = ((long long int)(1000000)) *
631 ((long long int)(timeval.tv_sec - peasycap->timeval3.tv_sec)) +
632 (long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
633 above = 1000000 * ((long long int) peasycap->audio_bytes);
634
635 if (below)
636 sdr = signed_div(above, below);
637 else
638 sdr.quotient = 192000;
639 }
640 JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
641 peasycap->dnbydt = sdr.quotient;
642
643 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
644 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
645 JOM(8, "returning %li\n", (long int)szret);
646 return szret;
647
648}
649
650static long easyoss_unlocked_ioctl(struct file *file,
651 unsigned int cmd, unsigned long arg)
652{
653 struct easycap *peasycap;
654 struct usb_device *p;
655 int kd;
656
657 if (!file) {
658 SAY("ERROR: file is NULL\n");
659 return -ERESTARTSYS;
660 }
661 peasycap = file->private_data;
662 if (!peasycap) {
663 SAY("ERROR: peasycap is NULL.\n");
664 return -EFAULT;
665 }
666 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
667 SAY("ERROR: bad peasycap\n");
668 return -EFAULT;
669 }
670 p = peasycap->pusb_device;
671 if (!p) {
672 SAM("ERROR: peasycap->pusb_device is NULL\n");
673 return -EFAULT;
674 }
675 kd = isdongle(peasycap);
676 if (0 <= kd && DONGLE_MANY > kd) {
677 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
678 SAY("ERROR: cannot lock "
679 "easycapdc60_dongle[%i].mutex_audio\n", kd);
680 return -ERESTARTSYS;
681 }
682 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
683
684
685
686
687
688
689 if (kd != isdongle(peasycap))
690 return -ERESTARTSYS;
691 if (!file) {
692 SAY("ERROR: file is NULL\n");
693 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
694 return -ERESTARTSYS;
695 }
696 peasycap = file->private_data;
697 if (!peasycap) {
698 SAY("ERROR: peasycap is NULL\n");
699 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
700 return -ERESTARTSYS;
701 }
702 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
703 SAY("ERROR: bad peasycap\n");
704 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
705 return -EFAULT;
706 }
707 p = peasycap->pusb_device;
708 if (!peasycap->pusb_device) {
709 SAM("ERROR: peasycap->pusb_device is NULL\n");
710 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
711 return -ERESTARTSYS;
712 }
713 } else {
714
715
716
717
718
719
720 return -ERESTARTSYS;
721 }
722
723 switch (cmd) {
724 case SNDCTL_DSP_GETCAPS: {
725 int caps;
726 JOM(8, "SNDCTL_DSP_GETCAPS\n");
727
728#ifdef UPSAMPLE
729 if (peasycap->microphone)
730 caps = 0x04400000;
731 else
732 caps = 0x04400000;
733#else
734 if (peasycap->microphone)
735 caps = 0x02400000;
736 else
737 caps = 0x04400000;
738#endif
739
740 if (copy_to_user((void __user *)arg, &caps, sizeof(int))) {
741 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
742 return -EFAULT;
743 }
744 break;
745 }
746 case SNDCTL_DSP_GETFMTS: {
747 int incoming;
748 JOM(8, "SNDCTL_DSP_GETFMTS\n");
749
750#ifdef UPSAMPLE
751 if (peasycap->microphone)
752 incoming = AFMT_S16_LE;
753 else
754 incoming = AFMT_S16_LE;
755#else
756 if (peasycap->microphone)
757 incoming = AFMT_S16_LE;
758 else
759 incoming = AFMT_S16_LE;
760#endif
761
762 if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
763 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
764 return -EFAULT;
765 }
766 break;
767 }
768 case SNDCTL_DSP_SETFMT: {
769 int incoming, outgoing;
770 JOM(8, "SNDCTL_DSP_SETFMT\n");
771 if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
772 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
773 return -EFAULT;
774 }
775 JOM(8, "........... %i=incoming\n", incoming);
776
777#ifdef UPSAMPLE
778 if (peasycap->microphone)
779 outgoing = AFMT_S16_LE;
780 else
781 outgoing = AFMT_S16_LE;
782#else
783 if (peasycap->microphone)
784 outgoing = AFMT_S16_LE;
785 else
786 outgoing = AFMT_S16_LE;
787#endif
788
789 if (incoming != outgoing) {
790 JOM(8, "........... %i=outgoing\n", outgoing);
791 JOM(8, " cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
792 JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8);
793 if (copy_to_user((void __user *)arg, &outgoing, sizeof(int))) {
794 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
795 return -EFAULT;
796 }
797 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
798 return -EINVAL ;
799 }
800 break;
801 }
802 case SNDCTL_DSP_STEREO: {
803 int incoming;
804 JOM(8, "SNDCTL_DSP_STEREO\n");
805 if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
806 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
807 return -EFAULT;
808 }
809 JOM(8, "........... %i=incoming\n", incoming);
810
811#ifdef UPSAMPLE
812 if (peasycap->microphone)
813 incoming = 1;
814 else
815 incoming = 1;
816#else
817 if (peasycap->microphone)
818 incoming = 0;
819 else
820 incoming = 1;
821#endif
822
823 if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
824 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
825 return -EFAULT;
826 }
827 break;
828 }
829 case SNDCTL_DSP_SPEED: {
830 int incoming;
831 JOM(8, "SNDCTL_DSP_SPEED\n");
832 if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
833 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
834 return -EFAULT;
835 }
836 JOM(8, "........... %i=incoming\n", incoming);
837
838#ifdef UPSAMPLE
839 if (peasycap->microphone)
840 incoming = 32000;
841 else
842 incoming = 48000;
843#else
844 if (peasycap->microphone)
845 incoming = 8000;
846 else
847 incoming = 48000;
848#endif
849
850 if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
851 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
852 return -EFAULT;
853 }
854 break;
855 }
856 case SNDCTL_DSP_GETTRIGGER: {
857 int incoming;
858 JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
859 if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
860 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
861 return -EFAULT;
862 }
863 JOM(8, "........... %i=incoming\n", incoming);
864
865 incoming = PCM_ENABLE_INPUT;
866 if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
867 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
868 return -EFAULT;
869 }
870 break;
871 }
872 case SNDCTL_DSP_SETTRIGGER: {
873 int incoming;
874 JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
875 if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
876 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
877 return -EFAULT;
878 }
879 JOM(8, "........... %i=incoming\n", incoming);
880 JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT "
881 "0x%x=PCM_ENABLE_OUTPUT\n",
882 PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
883 ;
884 ;
885 ;
886 ;
887 break;
888 }
889 case SNDCTL_DSP_GETBLKSIZE: {
890 int incoming;
891 JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
892 if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
893 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
894 return -EFAULT;
895 }
896 JOM(8, "........... %i=incoming\n", incoming);
897 incoming = peasycap->audio_bytes_per_fragment;
898 if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
899 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
900 return -EFAULT;
901 }
902 break;
903 }
904 case SNDCTL_DSP_GETISPACE: {
905 struct audio_buf_info audio_buf_info;
906
907 JOM(8, "SNDCTL_DSP_GETISPACE\n");
908
909 audio_buf_info.bytes = peasycap->audio_bytes_per_fragment;
910 audio_buf_info.fragments = 1;
911 audio_buf_info.fragsize = 0;
912 audio_buf_info.fragstotal = 0;
913
914 if (copy_to_user((void __user *)arg, &audio_buf_info, sizeof(int))) {
915 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
916 return -EFAULT;
917 }
918 break;
919 }
920 case 0x00005401:
921 case 0x00005402:
922 case 0x00005403:
923 case 0x00005404:
924 case 0x00005405:
925 case 0x00005406: {
926 JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
927 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
928 return -ENOIOCTLCMD;
929 }
930 default: {
931 JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
932 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
933 return -ENOIOCTLCMD;
934 }
935 }
936 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
937 return 0;
938}
939
940
941static const struct file_operations easyoss_fops = {
942 .owner = THIS_MODULE,
943 .open = easyoss_open,
944 .release = easyoss_release,
945 .unlocked_ioctl = easyoss_unlocked_ioctl,
946 .read = easyoss_read,
947 .llseek = no_llseek,
948};
949struct usb_class_driver easyoss_class = {
950 .name = "usb/easyoss%d",
951 .fops = &easyoss_fops,
952 .minor_base = USB_SKEL_MINOR_BASE,
953};
954
955