staging/easycap: easycap_probe : rename usb variables to common names
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / easycap / easycap_main.c
blob68b1f4fd1cd10efa4c3c72969c2b4bae30764012
1 /******************************************************************************
2 * *
3 * easycap_main.c *
4 * *
5 * Video driver for EasyCAP USB2.0 Video Capture Device DC60 *
6 * *
7 * *
8 ******************************************************************************/
9 /*
11 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
14 * This is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * The software is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this software; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 /*****************************************************************************/
31 #include "easycap.h"
32 #include <linux/usb/audio.h>
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
37 MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
38 MODULE_VERSION(EASYCAP_DRIVER_VERSION);
40 #ifdef CONFIG_EASYCAP_DEBUG
41 int easycap_debug;
42 module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
43 MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
44 #endif /* CONFIG_EASYCAP_DEBUG */
46 bool easycap_readback;
47 module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
48 MODULE_PARM_DESC(readback, "read back written registers: (default false)");
50 static int easycap_bars = 1;
51 module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
52 MODULE_PARM_DESC(bars,
53 "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
55 static int easycap_gain = 16;
56 module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
57 MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
59 static bool easycap_ntsc;
60 module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
61 MODULE_PARM_DESC(ntsc, "NTCS default encoding (default PAL)");
65 struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
66 static struct mutex mutex_dongle;
67 static void easycap_complete(struct urb *purb);
68 static int reset(struct easycap *peasycap);
70 const char *strerror(int err)
72 #define ERRNOSTR(_e) case _e: return # _e
73 switch (err) {
74 case 0: return "OK";
75 ERRNOSTR(ENOMEM);
76 ERRNOSTR(ENODEV);
77 ERRNOSTR(ENXIO);
78 ERRNOSTR(EINVAL);
79 ERRNOSTR(EAGAIN);
80 ERRNOSTR(EFBIG);
81 ERRNOSTR(EPIPE);
82 ERRNOSTR(EMSGSIZE);
83 ERRNOSTR(ENOSPC);
84 ERRNOSTR(EINPROGRESS);
85 ERRNOSTR(ENOSR);
86 ERRNOSTR(EOVERFLOW);
87 ERRNOSTR(EPROTO);
88 ERRNOSTR(EILSEQ);
89 ERRNOSTR(ETIMEDOUT);
90 ERRNOSTR(EOPNOTSUPP);
91 ERRNOSTR(EPFNOSUPPORT);
92 ERRNOSTR(EAFNOSUPPORT);
93 ERRNOSTR(EADDRINUSE);
94 ERRNOSTR(EADDRNOTAVAIL);
95 ERRNOSTR(ENOBUFS);
96 ERRNOSTR(EISCONN);
97 ERRNOSTR(ENOTCONN);
98 ERRNOSTR(ESHUTDOWN);
99 ERRNOSTR(ENOENT);
100 ERRNOSTR(ECONNRESET);
101 ERRNOSTR(ETIME);
102 ERRNOSTR(ECOMM);
103 ERRNOSTR(EREMOTEIO);
104 ERRNOSTR(EXDEV);
105 ERRNOSTR(EPERM);
106 default: return "unknown";
109 #undef ERRNOSTR
112 /*---------------------------------------------------------------------------*/
114 * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
116 * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
117 * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
118 * THIS IS THE CASE FOR OpenSUSE.
120 /*---------------------------------------------------------------------------*/
121 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
122 /****************************************************************************/
123 /*---------------------------------------------------------------------------*/
125 * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
127 /*---------------------------------------------------------------------------*/
128 int isdongle(struct easycap *peasycap)
130 int k;
131 if (!peasycap)
132 return -2;
133 for (k = 0; k < DONGLE_MANY; k++) {
134 if (easycapdc60_dongle[k].peasycap == peasycap) {
135 peasycap->isdongle = k;
136 return k;
139 return -1;
141 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
142 static int easycap_open(struct inode *inode, struct file *file)
144 struct video_device *pvideo_device;
145 struct easycap *peasycap;
146 int rc;
148 JOT(4, "\n");
149 SAY("==========OPEN=========\n");
151 pvideo_device = video_devdata(file);
152 if (!pvideo_device) {
153 SAY("ERROR: pvideo_device is NULL.\n");
154 return -EFAULT;
156 peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
157 if (!peasycap) {
158 SAY("ERROR: peasycap is NULL\n");
159 return -EFAULT;
161 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
162 SAY("ERROR: bad peasycap: %p\n", peasycap);
163 return -EFAULT;
165 if (!peasycap->pusb_device) {
166 SAM("ERROR: peasycap->pusb_device is NULL\n");
167 return -EFAULT;
168 } else {
169 JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
171 file->private_data = peasycap;
172 rc = wakeup_device(peasycap->pusb_device);
173 if (0 == rc)
174 JOM(8, "wakeup_device() OK\n");
175 else {
176 SAM("ERROR: wakeup_device() rc = %i\n", rc);
177 if (-ENODEV == rc)
178 SAM("ERROR: wakeup_device() returned -ENODEV\n");
179 else
180 SAM("ERROR: wakeup_device() rc = %i\n", rc);
181 return rc;
183 peasycap->input = 0;
184 rc = reset(peasycap);
185 if (rc) {
186 SAM("ERROR: reset() rc = %i\n", rc);
187 return -EFAULT;
189 return 0;
192 /*****************************************************************************/
193 /*---------------------------------------------------------------------------*/
195 * RESET THE HARDWARE TO ITS REFERENCE STATE.
197 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
198 * A BAD VIDEO FRAME SIZE.
200 /*---------------------------------------------------------------------------*/
201 static int reset(struct easycap *peasycap)
203 struct easycap_standard const *peasycap_standard;
204 int fmtidx, input, rate;
205 bool ntsc, other;
206 int rc;
208 if (!peasycap) {
209 SAY("ERROR: peasycap is NULL\n");
210 return -EFAULT;
212 input = peasycap->input;
214 /*---------------------------------------------------------------------------*/
216 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
217 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
218 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
219 * A SWITCH BETWEEN PAL AND NTSC.
221 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
222 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
224 /*---------------------------------------------------------------------------*/
225 other = false;
226 JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
228 rate = ready_saa(peasycap->pusb_device);
229 if (rate < 0) {
230 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
231 ntsc = !peasycap->ntsc;
232 JOM(8, "... trying %s ..\n", ntsc ? "NTSC" : "PAL");
233 rc = setup_stk(peasycap->pusb_device, ntsc);
234 if (rc) {
235 SAM("ERROR: setup_stk() rc = %i\n", rc);
236 return -EFAULT;
238 rc = setup_saa(peasycap->pusb_device, ntsc);
239 if (rc) {
240 SAM("ERROR: setup_saa() rc = %i\n", rc);
241 return -EFAULT;
244 rate = ready_saa(peasycap->pusb_device);
245 if (rate < 0) {
246 JOM(8, "not ready to capture after %i ms\n", PATIENCE);
247 JOM(8, "... saa register 0x1F has 0x%02X\n",
248 read_saa(peasycap->pusb_device, 0x1F));
249 ntsc = peasycap->ntsc;
250 } else {
251 JOM(8, "... success at second try: %i=rate\n", rate);
252 ntsc = (0 < (rate/2)) ? true : false ;
253 other = true;
255 } else {
256 JOM(8, "... success at first try: %i=rate\n", rate);
257 ntsc = (0 < rate/2) ? true : false ;
259 JOM(8, "ntsc=%d\n", ntsc);
260 /*---------------------------------------------------------------------------*/
262 rc = setup_stk(peasycap->pusb_device, ntsc);
263 if (rc) {
264 SAM("ERROR: setup_stk() rc = %i\n", rc);
265 return -EFAULT;
267 rc = setup_saa(peasycap->pusb_device, ntsc);
268 if (rc) {
269 SAM("ERROR: setup_saa() rc = %i\n", rc);
270 return -EFAULT;
273 memset(peasycap->merit, 0, sizeof(peasycap->merit));
275 peasycap->video_eof = 0;
276 peasycap->audio_eof = 0;
277 do_gettimeofday(&peasycap->timeval7);
278 /*---------------------------------------------------------------------------*/
280 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
282 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
284 /*---------------------------------------------------------------------------*/
285 peasycap->input = -8192;
286 peasycap->standard_offset = -8192;
287 fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
288 if (other) {
289 peasycap_standard = &easycap_standard[0];
290 while (0xFFFF != peasycap_standard->mask) {
291 if (fmtidx == peasycap_standard->v4l2_standard.index) {
292 peasycap->inputset[input].standard_offset =
293 peasycap_standard - easycap_standard;
294 break;
296 peasycap_standard++;
298 if (0xFFFF == peasycap_standard->mask) {
299 SAM("ERROR: standard not found\n");
300 return -EINVAL;
302 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
303 peasycap->inputset[input].standard_offset, input);
305 peasycap->format_offset = -8192;
306 peasycap->brightness = -8192;
307 peasycap->contrast = -8192;
308 peasycap->saturation = -8192;
309 peasycap->hue = -8192;
311 rc = newinput(peasycap, input);
313 if (rc) {
314 SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
315 return -EFAULT;
317 JOM(4, "restored input, standard and format\n");
319 JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
321 if (0 > peasycap->input) {
322 SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
323 return -ENOENT;
325 if (0 > peasycap->standard_offset) {
326 SAM("MISTAKE: %i=peasycap->standard_offset\n",
327 peasycap->standard_offset);
328 return -ENOENT;
330 if (0 > peasycap->format_offset) {
331 SAM("MISTAKE: %i=peasycap->format_offset\n",
332 peasycap->format_offset);
333 return -ENOENT;
335 if (0 > peasycap->brightness) {
336 SAM("MISTAKE: %i=peasycap->brightness\n",
337 peasycap->brightness);
338 return -ENOENT;
340 if (0 > peasycap->contrast) {
341 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
342 return -ENOENT;
344 if (0 > peasycap->saturation) {
345 SAM("MISTAKE: %i=peasycap->saturation\n",
346 peasycap->saturation);
347 return -ENOENT;
349 if (0 > peasycap->hue) {
350 SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
351 return -ENOENT;
353 return 0;
355 /*****************************************************************************/
356 /*---------------------------------------------------------------------------*/
358 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
359 * OTHERWISE:
360 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
361 * _read AND _fill POINTERS.
362 * SELECT THE NEW INPUT.
363 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
364 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
365 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
367 * NOTE:
368 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
369 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
371 /*---------------------------------------------------------------------------*/
373 newinput(struct easycap *peasycap, int input)
375 int rc, k, m, mood, off;
376 int inputnow, video_idlenow, audio_idlenow;
377 bool resubmit;
379 if (!peasycap) {
380 SAY("ERROR: peasycap is NULL\n");
381 return -EFAULT;
383 JOM(8, "%i=input sought\n", input);
385 if (0 > input && INPUT_MANY <= input)
386 return -ENOENT;
387 inputnow = peasycap->input;
388 if (input == inputnow)
389 return 0;
390 /*---------------------------------------------------------------------------*/
392 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
393 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
394 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
395 * ROUTINE.
397 /*---------------------------------------------------------------------------*/
398 video_idlenow = peasycap->video_idle;
399 audio_idlenow = peasycap->audio_idle;
401 peasycap->video_idle = 1;
402 peasycap->audio_idle = 1;
403 if (peasycap->video_isoc_streaming) {
404 resubmit = true;
405 kill_video_urbs(peasycap);
406 } else {
407 resubmit = false;
409 /*---------------------------------------------------------------------------*/
410 if (!peasycap->pusb_device) {
411 SAM("ERROR: peasycap->pusb_device is NULL\n");
412 return -ENODEV;
414 rc = usb_set_interface(peasycap->pusb_device,
415 peasycap->video_interface,
416 peasycap->video_altsetting_off);
417 if (rc) {
418 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
419 return -EFAULT;
421 rc = stop_100(peasycap->pusb_device);
422 if (rc) {
423 SAM("ERROR: stop_100() rc = %i\n", rc);
424 return -EFAULT;
426 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
427 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
428 memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
430 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
431 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
432 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
434 peasycap->field_page = 0;
435 peasycap->field_read = 0;
436 peasycap->field_fill = 0;
438 peasycap->frame_read = 0;
439 peasycap->frame_fill = 0;
440 for (k = 0; k < peasycap->input; k++) {
441 (peasycap->frame_fill)++;
442 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
443 peasycap->frame_fill = 0;
445 peasycap->input = input;
446 select_input(peasycap->pusb_device, peasycap->input, 9);
447 /*---------------------------------------------------------------------------*/
448 if (input == peasycap->inputset[input].input) {
449 off = peasycap->inputset[input].standard_offset;
450 if (off != peasycap->standard_offset) {
451 rc = adjust_standard(peasycap,
452 easycap_standard[off].v4l2_standard.id);
453 if (rc) {
454 SAM("ERROR: adjust_standard() rc = %i\n", rc);
455 return -EFAULT;
457 JOM(8, "%i=peasycap->standard_offset\n",
458 peasycap->standard_offset);
459 } else {
460 JOM(8, "%i=peasycap->standard_offset unchanged\n",
461 peasycap->standard_offset);
463 off = peasycap->inputset[input].format_offset;
464 if (off != peasycap->format_offset) {
465 struct v4l2_pix_format *pix =
466 &easycap_format[off].v4l2_format.fmt.pix;
467 rc = adjust_format(peasycap,
468 pix->width, pix->height,
469 pix->pixelformat, pix->field, false);
470 if (0 > rc) {
471 SAM("ERROR: adjust_format() rc = %i\n", rc);
472 return -EFAULT;
474 JOM(8, "%i=peasycap->format_offset\n",
475 peasycap->format_offset);
476 } else {
477 JOM(8, "%i=peasycap->format_offset unchanged\n",
478 peasycap->format_offset);
480 mood = peasycap->inputset[input].brightness;
481 if (mood != peasycap->brightness) {
482 rc = adjust_brightness(peasycap, mood);
483 if (rc) {
484 SAM("ERROR: adjust_brightness rc = %i\n", rc);
485 return -EFAULT;
487 JOM(8, "%i=peasycap->brightness\n",
488 peasycap->brightness);
490 mood = peasycap->inputset[input].contrast;
491 if (mood != peasycap->contrast) {
492 rc = adjust_contrast(peasycap, mood);
493 if (rc) {
494 SAM("ERROR: adjust_contrast rc = %i\n", rc);
495 return -EFAULT;
497 JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
499 mood = peasycap->inputset[input].saturation;
500 if (mood != peasycap->saturation) {
501 rc = adjust_saturation(peasycap, mood);
502 if (rc) {
503 SAM("ERROR: adjust_saturation rc = %i\n", rc);
504 return -EFAULT;
506 JOM(8, "%i=peasycap->saturation\n",
507 peasycap->saturation);
509 mood = peasycap->inputset[input].hue;
510 if (mood != peasycap->hue) {
511 rc = adjust_hue(peasycap, mood);
512 if (rc) {
513 SAM("ERROR: adjust_hue rc = %i\n", rc);
514 return -EFAULT;
516 JOM(8, "%i=peasycap->hue\n", peasycap->hue);
518 } else {
519 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
520 return -ENOENT;
522 /*---------------------------------------------------------------------------*/
523 if (!peasycap->pusb_device) {
524 SAM("ERROR: peasycap->pusb_device is NULL\n");
525 return -ENODEV;
527 rc = usb_set_interface(peasycap->pusb_device,
528 peasycap->video_interface,
529 peasycap->video_altsetting_on);
530 if (rc) {
531 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
532 return -EFAULT;
534 rc = start_100(peasycap->pusb_device);
535 if (rc) {
536 SAM("ERROR: start_100() rc = %i\n", rc);
537 return -EFAULT;
539 if (resubmit)
540 submit_video_urbs(peasycap);
542 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
543 peasycap->video_idle = video_idlenow;
544 peasycap->audio_idle = audio_idlenow;
545 peasycap->video_junk = 0;
547 return 0;
549 /*****************************************************************************/
550 int submit_video_urbs(struct easycap *peasycap)
552 struct data_urb *pdata_urb;
553 struct urb *purb;
554 struct list_head *plist_head;
555 int j, isbad, nospc, m, rc;
556 int isbuf;
558 if (!peasycap) {
559 SAY("ERROR: peasycap is NULL\n");
560 return -EFAULT;
563 if (!peasycap->purb_video_head) {
564 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
565 return -EFAULT;
567 if (!peasycap->pusb_device) {
568 SAY("ERROR: peasycap->pusb_device is NULL\n");
569 return -ENODEV;
571 if (!peasycap->video_isoc_streaming) {
572 JOM(4, "submission of all video urbs\n");
573 isbad = 0; nospc = 0; m = 0;
574 list_for_each(plist_head, (peasycap->purb_video_head)) {
575 pdata_urb = list_entry(plist_head,
576 struct data_urb, list_head);
577 if (pdata_urb && pdata_urb->purb) {
578 purb = pdata_urb->purb;
579 isbuf = pdata_urb->isbuf;
580 purb->interval = 1;
581 purb->dev = peasycap->pusb_device;
582 purb->pipe =
583 usb_rcvisocpipe(peasycap->pusb_device,
584 peasycap->video_endpointnumber);
585 purb->transfer_flags = URB_ISO_ASAP;
586 purb->transfer_buffer =
587 peasycap->video_isoc_buffer[isbuf].pgo;
588 purb->transfer_buffer_length =
589 peasycap->video_isoc_buffer_size;
590 purb->complete = easycap_complete;
591 purb->context = peasycap;
592 purb->start_frame = 0;
593 purb->number_of_packets =
594 peasycap->video_isoc_framesperdesc;
596 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
597 purb->iso_frame_desc[j]. offset =
598 j * peasycap->video_isoc_maxframesize;
599 purb->iso_frame_desc[j]. length =
600 peasycap->video_isoc_maxframesize;
603 rc = usb_submit_urb(purb, GFP_KERNEL);
604 if (rc) {
605 isbad++;
606 SAM("ERROR: usb_submit_urb() failed "
607 "for urb with rc:-%s\n",
608 strerror(rc));
609 if (rc == -ENOSPC)
610 nospc++;
611 } else {
612 m++;
614 } else {
615 isbad++;
618 if (nospc) {
619 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
620 SAM("..... possibly inadequate USB bandwidth\n");
621 peasycap->video_eof = 1;
624 if (isbad) {
625 JOM(4, "attempting cleanup instead of submitting\n");
626 list_for_each(plist_head, (peasycap->purb_video_head)) {
627 pdata_urb = list_entry(plist_head,
628 struct data_urb, list_head);
629 if (pdata_urb) {
630 purb = pdata_urb->purb;
631 if (purb)
632 usb_kill_urb(purb);
635 peasycap->video_isoc_streaming = 0;
636 } else {
637 peasycap->video_isoc_streaming = 1;
638 JOM(4, "submitted %i video urbs\n", m);
640 } else {
641 JOM(4, "already streaming video urbs\n");
643 return 0;
645 /*****************************************************************************/
646 int kill_video_urbs(struct easycap *peasycap)
648 int m;
649 struct list_head *plist_head;
650 struct data_urb *pdata_urb;
652 if (!peasycap) {
653 SAY("ERROR: peasycap is NULL\n");
654 return -EFAULT;
656 if (!peasycap->video_isoc_streaming) {
657 JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
658 peasycap->video_isoc_streaming);
659 return 0;
661 if (!peasycap->purb_video_head) {
662 SAM("ERROR: peasycap->purb_video_head is NULL\n");
663 return -EFAULT;
666 peasycap->video_isoc_streaming = 0;
667 JOM(4, "killing video urbs\n");
668 m = 0;
669 list_for_each(plist_head, (peasycap->purb_video_head)) {
670 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
671 if (pdata_urb && pdata_urb->purb) {
672 usb_kill_urb(pdata_urb->purb);
673 m++;
676 JOM(4, "%i video urbs killed\n", m);
678 return 0;
680 /****************************************************************************/
681 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
682 /*--------------------------------------------------------------------------*/
683 static int easycap_open_noinode(struct file *file)
685 return easycap_open(NULL, file);
688 static int videodev_release(struct video_device *pvideo_device)
690 struct easycap *peasycap;
692 peasycap = video_get_drvdata(pvideo_device);
693 if (!peasycap) {
694 SAY("ERROR: peasycap is NULL\n");
695 SAY("ending unsuccessfully\n");
696 return -EFAULT;
698 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
699 SAY("ERROR: bad peasycap: %p\n", peasycap);
700 return -EFAULT;
702 if (0 != kill_video_urbs(peasycap)) {
703 SAM("ERROR: kill_video_urbs() failed\n");
704 return -EFAULT;
706 JOM(4, "ending successfully\n");
707 return 0;
709 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
710 /*****************************************************************************/
711 /*--------------------------------------------------------------------------*/
713 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
714 * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
716 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
717 * peasycap->pusb_device IS NO LONGER VALID.
719 /*---------------------------------------------------------------------------*/
720 static void easycap_delete(struct kref *pkref)
722 struct easycap *peasycap;
723 struct data_urb *pdata_urb;
724 struct list_head *plist_head, *plist_next;
725 int k, m, gone, kd;
726 int allocation_video_urb;
727 int allocation_video_page;
728 int allocation_video_struct;
729 int allocation_audio_urb;
730 int allocation_audio_page;
731 int allocation_audio_struct;
732 int registered_video, registered_audio;
734 peasycap = container_of(pkref, struct easycap, kref);
735 if (!peasycap) {
736 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
737 return;
739 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
740 SAY("ERROR: bad peasycap: %p\n", peasycap);
741 return;
743 kd = isdongle(peasycap);
744 /*---------------------------------------------------------------------------*/
746 * FREE VIDEO.
748 /*---------------------------------------------------------------------------*/
749 if (peasycap->purb_video_head) {
750 JOM(4, "freeing video urbs\n");
751 m = 0;
752 list_for_each(plist_head, (peasycap->purb_video_head)) {
753 pdata_urb = list_entry(plist_head,
754 struct data_urb, list_head);
755 if (!pdata_urb) {
756 JOM(4, "ERROR: pdata_urb is NULL\n");
757 } else {
758 if (pdata_urb->purb) {
759 usb_free_urb(pdata_urb->purb);
760 pdata_urb->purb = NULL;
761 peasycap->allocation_video_urb -= 1;
762 m++;
767 JOM(4, "%i video urbs freed\n", m);
768 /*---------------------------------------------------------------------------*/
769 JOM(4, "freeing video data_urb structures.\n");
770 m = 0;
771 list_for_each_safe(plist_head, plist_next,
772 peasycap->purb_video_head) {
773 pdata_urb = list_entry(plist_head,
774 struct data_urb, list_head);
775 if (pdata_urb) {
776 peasycap->allocation_video_struct -=
777 sizeof(struct data_urb);
778 kfree(pdata_urb);
779 pdata_urb = NULL;
780 m++;
783 JOM(4, "%i video data_urb structures freed\n", m);
784 JOM(4, "setting peasycap->purb_video_head=NULL\n");
785 peasycap->purb_video_head = NULL;
787 /*---------------------------------------------------------------------------*/
788 JOM(4, "freeing video isoc buffers.\n");
789 m = 0;
790 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
791 if (peasycap->video_isoc_buffer[k].pgo) {
792 free_pages((unsigned long)
793 peasycap->video_isoc_buffer[k].pgo,
794 VIDEO_ISOC_ORDER);
795 peasycap->video_isoc_buffer[k].pgo = NULL;
796 peasycap->allocation_video_page -=
797 BIT(VIDEO_ISOC_ORDER);
798 m++;
801 JOM(4, "isoc video buffers freed: %i pages\n",
802 m * (0x01 << VIDEO_ISOC_ORDER));
803 /*---------------------------------------------------------------------------*/
804 JOM(4, "freeing video field buffers.\n");
805 gone = 0;
806 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
807 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
808 if (peasycap->field_buffer[k][m].pgo) {
809 free_page((unsigned long)
810 peasycap->field_buffer[k][m].pgo);
811 peasycap->field_buffer[k][m].pgo = NULL;
812 peasycap->allocation_video_page -= 1;
813 gone++;
817 JOM(4, "video field buffers freed: %i pages\n", gone);
818 /*---------------------------------------------------------------------------*/
819 JOM(4, "freeing video frame buffers.\n");
820 gone = 0;
821 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
822 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
823 if (peasycap->frame_buffer[k][m].pgo) {
824 free_page((unsigned long)
825 peasycap->frame_buffer[k][m].pgo);
826 peasycap->frame_buffer[k][m].pgo = NULL;
827 peasycap->allocation_video_page -= 1;
828 gone++;
832 JOM(4, "video frame buffers freed: %i pages\n", gone);
833 /*---------------------------------------------------------------------------*/
835 * FREE AUDIO.
837 /*---------------------------------------------------------------------------*/
838 if (peasycap->purb_audio_head) {
839 JOM(4, "freeing audio urbs\n");
840 m = 0;
841 list_for_each(plist_head, (peasycap->purb_audio_head)) {
842 pdata_urb = list_entry(plist_head,
843 struct data_urb, list_head);
844 if (!pdata_urb)
845 JOM(4, "ERROR: pdata_urb is NULL\n");
846 else {
847 if (pdata_urb->purb) {
848 usb_free_urb(pdata_urb->purb);
849 pdata_urb->purb = NULL;
850 peasycap->allocation_audio_urb -= 1;
851 m++;
855 JOM(4, "%i audio urbs freed\n", m);
856 /*---------------------------------------------------------------------------*/
857 JOM(4, "freeing audio data_urb structures.\n");
858 m = 0;
859 list_for_each_safe(plist_head, plist_next,
860 peasycap->purb_audio_head) {
861 pdata_urb = list_entry(plist_head,
862 struct data_urb, list_head);
863 if (pdata_urb) {
864 peasycap->allocation_audio_struct -=
865 sizeof(struct data_urb);
866 kfree(pdata_urb);
867 pdata_urb = NULL;
868 m++;
871 JOM(4, "%i audio data_urb structures freed\n", m);
872 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
873 peasycap->purb_audio_head = NULL;
875 /*---------------------------------------------------------------------------*/
876 JOM(4, "freeing audio isoc buffers.\n");
877 m = 0;
878 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
879 if (peasycap->audio_isoc_buffer[k].pgo) {
880 free_pages((unsigned long)
881 (peasycap->audio_isoc_buffer[k].pgo),
882 AUDIO_ISOC_ORDER);
883 peasycap->audio_isoc_buffer[k].pgo = NULL;
884 peasycap->allocation_audio_page -=
885 BIT(AUDIO_ISOC_ORDER);
886 m++;
889 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
890 m * (0x01 << AUDIO_ISOC_ORDER));
891 /*---------------------------------------------------------------------------*/
892 #ifdef CONFIG_EASYCAP_OSS
893 JOM(4, "freeing audio buffers.\n");
894 gone = 0;
895 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
896 if (peasycap->audio_buffer[k].pgo) {
897 free_page((unsigned long)peasycap->audio_buffer[k].pgo);
898 peasycap->audio_buffer[k].pgo = NULL;
899 peasycap->allocation_audio_page -= 1;
900 gone++;
903 JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
904 #endif /* CONFIG_EASYCAP_OSS */
905 /*---------------------------------------------------------------------------*/
906 JOM(4, "freeing easycap structure.\n");
907 allocation_video_urb = peasycap->allocation_video_urb;
908 allocation_video_page = peasycap->allocation_video_page;
909 allocation_video_struct = peasycap->allocation_video_struct;
910 registered_video = peasycap->registered_video;
911 allocation_audio_urb = peasycap->allocation_audio_urb;
912 allocation_audio_page = peasycap->allocation_audio_page;
913 allocation_audio_struct = peasycap->allocation_audio_struct;
914 registered_audio = peasycap->registered_audio;
916 kfree(peasycap);
918 if (0 <= kd && DONGLE_MANY > kd) {
919 if (mutex_lock_interruptible(&mutex_dongle)) {
920 SAY("ERROR: cannot down mutex_dongle\n");
921 } else {
922 JOM(4, "locked mutex_dongle\n");
923 easycapdc60_dongle[kd].peasycap = NULL;
924 mutex_unlock(&mutex_dongle);
925 JOM(4, "unlocked mutex_dongle\n");
926 JOT(4, " null-->dongle[%i].peasycap\n", kd);
927 allocation_video_struct -= sizeof(struct easycap);
929 } else {
930 SAY("ERROR: cannot purge dongle[].peasycap");
932 /*---------------------------------------------------------------------------*/
933 SAY("%8i=video urbs after all deletions\n", allocation_video_urb);
934 SAY("%8i=video pages after all deletions\n", allocation_video_page);
935 SAY("%8i=video structs after all deletions\n", allocation_video_struct);
936 SAY("%8i=video devices after all deletions\n", registered_video);
937 SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb);
938 SAY("%8i=audio pages after all deletions\n", allocation_audio_page);
939 SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
940 SAY("%8i=audio devices after all deletions\n", registered_audio);
942 JOT(4, "ending.\n");
943 return;
945 /*****************************************************************************/
946 static unsigned int easycap_poll(struct file *file, poll_table *wait)
948 struct easycap *peasycap;
949 int rc, kd;
951 JOT(8, "\n");
953 if (NULL == ((poll_table *)wait))
954 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
955 if (!file) {
956 SAY("ERROR: file pointer is NULL\n");
957 return -ERESTARTSYS;
959 peasycap = file->private_data;
960 if (!peasycap) {
961 SAY("ERROR: peasycap is NULL\n");
962 return -EFAULT;
964 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
965 SAY("ERROR: bad peasycap: %p\n", peasycap);
966 return -EFAULT;
968 if (!peasycap->pusb_device) {
969 SAY("ERROR: peasycap->pusb_device is NULL\n");
970 return -EFAULT;
972 /*---------------------------------------------------------------------------*/
973 kd = isdongle(peasycap);
974 if (0 <= kd && DONGLE_MANY > kd) {
975 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
976 SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
977 return -ERESTARTSYS;
979 JOM(4, "locked dongle[%i].mutex_video\n", kd);
981 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
982 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
983 * IF NECESSARY, BAIL OUT.
985 if (kd != isdongle(peasycap))
986 return -ERESTARTSYS;
987 if (!file) {
988 SAY("ERROR: file is NULL\n");
989 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
990 return -ERESTARTSYS;
992 peasycap = file->private_data;
993 if (!peasycap) {
994 SAY("ERROR: peasycap is NULL\n");
995 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
996 return -ERESTARTSYS;
998 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
999 SAY("ERROR: bad peasycap: %p\n", peasycap);
1000 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1001 return -ERESTARTSYS;
1003 if (!peasycap->pusb_device) {
1004 SAM("ERROR: peasycap->pusb_device is NULL\n");
1005 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1006 return -ERESTARTSYS;
1008 } else
1010 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
1011 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
1012 * HAVE FAILED. BAIL OUT.
1014 return -ERESTARTSYS;
1015 /*---------------------------------------------------------------------------*/
1016 rc = easycap_dqbuf(peasycap, 0);
1017 peasycap->polled = 1;
1018 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1019 if (0 == rc)
1020 return POLLIN | POLLRDNORM;
1021 else
1022 return POLLERR;
1024 /*****************************************************************************/
1025 /*---------------------------------------------------------------------------*/
1027 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
1029 /*---------------------------------------------------------------------------*/
1030 int easycap_dqbuf(struct easycap *peasycap, int mode)
1032 int input, ifield, miss, rc;
1035 if (!peasycap) {
1036 SAY("ERROR: peasycap is NULL\n");
1037 return -EFAULT;
1039 if (!peasycap->pusb_device) {
1040 SAY("ERROR: peasycap->pusb_device is NULL\n");
1041 return -EFAULT;
1043 ifield = 0;
1044 JOM(8, "%i=ifield\n", ifield);
1045 /*---------------------------------------------------------------------------*/
1047 * CHECK FOR LOST INPUT SIGNAL.
1049 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1050 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1051 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1052 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
1054 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
1055 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
1056 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1057 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1059 /*---------------------------------------------------------------------------*/
1060 input = peasycap->input;
1061 if (0 <= input && INPUT_MANY > input) {
1062 rc = read_saa(peasycap->pusb_device, 0x1F);
1063 if (0 <= rc) {
1064 if (rc & 0x40)
1065 peasycap->lost[input] += 1;
1066 else
1067 peasycap->lost[input] -= 2;
1069 if (0 > peasycap->lost[input])
1070 peasycap->lost[input] = 0;
1071 else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1072 peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1075 /*---------------------------------------------------------------------------*/
1077 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
1079 /*---------------------------------------------------------------------------*/
1080 miss = 0;
1081 while ((peasycap->field_read == peasycap->field_fill) ||
1082 (0 != (0xFF00 & peasycap->field_buffer
1083 [peasycap->field_read][0].kount)) ||
1084 (ifield != (0x00FF & peasycap->field_buffer
1085 [peasycap->field_read][0].kount))) {
1086 if (mode)
1087 return -EAGAIN;
1089 JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n",
1090 peasycap->field_read, peasycap->field_fill);
1092 if (0 != (wait_event_interruptible(peasycap->wq_video,
1093 (peasycap->video_idle || peasycap->video_eof ||
1094 ((peasycap->field_read != peasycap->field_fill) &&
1095 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1096 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1097 SAM("aborted by signal\n");
1098 return -EIO;
1100 if (peasycap->video_idle) {
1101 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1102 peasycap->video_idle);
1103 return -EAGAIN;
1105 if (peasycap->video_eof) {
1106 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1107 #if defined(PERSEVERE)
1108 if (1 == peasycap->status) {
1109 JOM(8, "persevering ...\n");
1110 peasycap->video_eof = 0;
1111 peasycap->audio_eof = 0;
1112 if (0 != reset(peasycap)) {
1113 JOM(8, " ... failed returning -EIO\n");
1114 peasycap->video_eof = 1;
1115 peasycap->audio_eof = 1;
1116 kill_video_urbs(peasycap);
1117 return -EIO;
1119 peasycap->status = 0;
1120 JOM(8, " ... OK returning -EAGAIN\n");
1121 return -EAGAIN;
1123 #endif /*PERSEVERE*/
1124 peasycap->video_eof = 1;
1125 peasycap->audio_eof = 1;
1126 kill_video_urbs(peasycap);
1127 JOM(8, "returning -EIO\n");
1128 return -EIO;
1130 miss++;
1132 JOM(8, "first awakening on wq_video after %i waits\n", miss);
1134 rc = field2frame(peasycap);
1135 if (rc)
1136 SAM("ERROR: field2frame() rc = %i\n", rc);
1137 /*---------------------------------------------------------------------------*/
1139 * WAIT FOR THE OTHER FIELD
1141 /*---------------------------------------------------------------------------*/
1142 if (ifield)
1143 ifield = 0;
1144 else
1145 ifield = 1;
1146 miss = 0;
1147 while ((peasycap->field_read == peasycap->field_fill) ||
1148 (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1149 (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1150 if (mode)
1151 return -EAGAIN;
1153 JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n",
1154 peasycap->field_read, peasycap->field_fill);
1155 if (0 != (wait_event_interruptible(peasycap->wq_video,
1156 (peasycap->video_idle || peasycap->video_eof ||
1157 ((peasycap->field_read != peasycap->field_fill) &&
1158 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1159 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1160 SAM("aborted by signal\n");
1161 return -EIO;
1163 if (peasycap->video_idle) {
1164 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1165 peasycap->video_idle);
1166 return -EAGAIN;
1168 if (peasycap->video_eof) {
1169 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1170 #if defined(PERSEVERE)
1171 if (1 == peasycap->status) {
1172 JOM(8, "persevering ...\n");
1173 peasycap->video_eof = 0;
1174 peasycap->audio_eof = 0;
1175 if (0 != reset(peasycap)) {
1176 JOM(8, " ... failed returning -EIO\n");
1177 peasycap->video_eof = 1;
1178 peasycap->audio_eof = 1;
1179 kill_video_urbs(peasycap);
1180 return -EIO;
1182 peasycap->status = 0;
1183 JOM(8, " ... OK ... returning -EAGAIN\n");
1184 return -EAGAIN;
1186 #endif /*PERSEVERE*/
1187 peasycap->video_eof = 1;
1188 peasycap->audio_eof = 1;
1189 kill_video_urbs(peasycap);
1190 JOM(8, "returning -EIO\n");
1191 return -EIO;
1193 miss++;
1195 JOM(8, "second awakening on wq_video after %i waits\n", miss);
1197 rc = field2frame(peasycap);
1198 if (rc)
1199 SAM("ERROR: field2frame() rc = %i\n", rc);
1200 /*---------------------------------------------------------------------------*/
1202 * WASTE THIS FRAME
1204 /*---------------------------------------------------------------------------*/
1205 if (peasycap->skip) {
1206 peasycap->skipped++;
1207 if (peasycap->skip != peasycap->skipped)
1208 return peasycap->skip - peasycap->skipped;
1209 else
1210 peasycap->skipped = 0;
1212 /*---------------------------------------------------------------------------*/
1213 peasycap->frame_read = peasycap->frame_fill;
1214 peasycap->queued[peasycap->frame_read] = 0;
1215 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
1217 peasycap->frame_fill++;
1218 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1219 peasycap->frame_fill = 0;
1221 if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1222 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1223 V4L2_FIELD_TOP;
1224 else
1225 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1226 V4L2_FIELD_BOTTOM;
1229 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
1230 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
1232 return 0;
1234 /*****************************************************************************/
1235 /*---------------------------------------------------------------------------*/
1237 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1238 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1240 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1241 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1243 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1244 * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1246 /*---------------------------------------------------------------------------*/
1248 field2frame(struct easycap *peasycap)
1250 struct timeval timeval;
1251 long long int above, below;
1252 u32 remainder;
1253 struct signed_div_result sdr;
1255 void *pex, *pad;
1256 int kex, kad, mex, mad, rex, rad, rad2;
1257 int c2, c3, w2, w3, cz, wz;
1258 int rc, bytesperpixel, multiplier;
1259 int much, more, over, rump, caches, input;
1260 u8 mask, margin;
1261 bool odd, isuy, decimatepixel, offerfields, badinput;
1263 if (!peasycap) {
1264 SAY("ERROR: peasycap is NULL\n");
1265 return -EFAULT;
1268 badinput = false;
1269 input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1271 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1272 "frame buffer %i\n",
1273 peasycap->field_buffer[peasycap->field_read][0].kount,
1274 peasycap->field_buffer[peasycap->field_read][0].input,
1275 peasycap->field_read, peasycap->frame_fill);
1276 JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1277 if (peasycap->offerfields)
1278 JOM(8, "===== offerfields\n");
1280 /*---------------------------------------------------------------------------*/
1282 * REJECT OR CLEAN BAD FIELDS
1284 /*---------------------------------------------------------------------------*/
1285 if (peasycap->field_read == peasycap->field_fill) {
1286 SAM("ERROR: on entry, still filling field buffer %i\n",
1287 peasycap->field_read);
1288 return 0;
1290 #ifdef EASYCAP_TESTCARD
1291 easycap_testcard(peasycap, peasycap->field_read);
1292 #else
1293 if (0 <= input && INPUT_MANY > input) {
1294 if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1295 easycap_testcard(peasycap, peasycap->field_read);
1297 #endif /*EASYCAP_TESTCARD*/
1298 /*---------------------------------------------------------------------------*/
1300 offerfields = peasycap->offerfields;
1301 bytesperpixel = peasycap->bytesperpixel;
1302 decimatepixel = peasycap->decimatepixel;
1304 if ((2 != bytesperpixel) &&
1305 (3 != bytesperpixel) &&
1306 (4 != bytesperpixel)) {
1307 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1308 return -EFAULT;
1310 if (decimatepixel)
1311 multiplier = 2;
1312 else
1313 multiplier = 1;
1315 w2 = 2 * multiplier * (peasycap->width);
1316 w3 = bytesperpixel * multiplier * (peasycap->width);
1317 wz = multiplier * (peasycap->height) *
1318 multiplier * (peasycap->width);
1320 kex = peasycap->field_read; mex = 0;
1321 kad = peasycap->frame_fill; mad = 0;
1323 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1324 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1325 odd = !!(peasycap->field_buffer[kex][0].kount);
1327 if (odd && (!decimatepixel)) {
1328 JOM(8, "initial skipping %4i bytes p.%4i\n",
1329 w3/multiplier, mad);
1330 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1332 isuy = true;
1333 mask = 0; rump = 0; caches = 0;
1335 cz = 0;
1336 while (cz < wz) {
1338 * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1339 * READ w2 BYTES FROM FIELD BUFFER,
1340 * WRITE w3 BYTES TO FRAME BUFFER
1342 if (!decimatepixel) {
1343 over = w2;
1344 do {
1345 much = over; more = 0;
1346 margin = 0; mask = 0x00;
1347 if (rex < much)
1348 much = rex;
1349 rump = 0;
1351 if (much % 2) {
1352 SAM("MISTAKE: much is odd\n");
1353 return -EFAULT;
1356 more = (bytesperpixel *
1357 much) / 2;
1358 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1359 if (1 < bytesperpixel) {
1360 if (rad * 2 < much * bytesperpixel) {
1362 * INJUDICIOUS ALTERATION OF
1363 * THIS STATEMENT BLOCK WILL
1364 * CAUSE BREAKAGE. BEWARE.
1366 rad2 = rad + bytesperpixel - 1;
1367 much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1368 rump = ((bytesperpixel * much) / 2) - rad;
1369 more = rad;
1371 mask = (u8)rump;
1372 margin = 0;
1373 if (much == rex) {
1374 mask |= 0x04;
1375 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1376 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1377 else
1378 mask |= 0x08;
1380 } else {
1381 SAM("MISTAKE: %i=bytesperpixel\n",
1382 bytesperpixel);
1383 return -EFAULT;
1385 if (rump)
1386 caches++;
1387 if (badinput) {
1388 JOM(8, "ERROR: 0x%02X=->field_buffer"
1389 "[%i][%i].input, "
1390 "0x%02X=(0x08|->input)\n",
1391 peasycap->field_buffer
1392 [kex][mex].input, kex, mex,
1393 (0x08|peasycap->input));
1395 rc = redaub(peasycap, pad, pex, much, more,
1396 mask, margin, isuy);
1397 if (0 > rc) {
1398 SAM("ERROR: redaub() failed\n");
1399 return -EFAULT;
1401 if (much % 4)
1402 isuy = !isuy;
1404 over -= much; cz += much;
1405 pex += much; rex -= much;
1406 if (!rex) {
1407 mex++;
1408 pex = peasycap->field_buffer[kex][mex].pgo;
1409 rex = PAGE_SIZE;
1410 if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1411 badinput = true;
1413 pad += more;
1414 rad -= more;
1415 if (!rad) {
1416 mad++;
1417 pad = peasycap->frame_buffer[kad][mad].pgo;
1418 rad = PAGE_SIZE;
1419 if (rump) {
1420 pad += rump;
1421 rad -= rump;
1424 } while (over);
1425 /*---------------------------------------------------------------------------*/
1427 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1428 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1430 /*---------------------------------------------------------------------------*/
1431 if (!odd || (cz != wz)) {
1432 over = w3;
1433 do {
1434 if (!rad) {
1435 mad++;
1436 pad = peasycap->frame_buffer
1437 [kad][mad].pgo;
1438 rad = PAGE_SIZE;
1440 more = over;
1441 if (rad < more)
1442 more = rad;
1443 over -= more;
1444 pad += more;
1445 rad -= more;
1446 } while (over);
1448 /*---------------------------------------------------------------------------*/
1450 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1451 * ONLY IF false==odd,
1452 * READ w2 BYTES FROM FIELD BUFFER,
1453 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1455 /*---------------------------------------------------------------------------*/
1456 } else if (!odd) {
1457 over = w2;
1458 do {
1459 much = over; more = 0; margin = 0; mask = 0x00;
1460 if (rex < much)
1461 much = rex;
1462 rump = 0;
1464 if (much % 2) {
1465 SAM("MISTAKE: much is odd\n");
1466 return -EFAULT;
1469 more = (bytesperpixel * much) / 4;
1470 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1471 if (1 < bytesperpixel) {
1472 if (rad * 4 < much * bytesperpixel) {
1474 * INJUDICIOUS ALTERATION OF
1475 * THIS STATEMENT BLOCK
1476 * WILL CAUSE BREAKAGE.
1477 * BEWARE.
1479 rad2 = rad + bytesperpixel - 1;
1480 much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1481 rump = ((bytesperpixel * much) / 4) - rad;
1482 more = rad;
1484 mask = (u8)rump;
1485 margin = 0;
1486 if (much == rex) {
1487 mask |= 0x04;
1488 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1489 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1490 else
1491 mask |= 0x08;
1493 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1494 } else {
1495 SAM("MISTAKE: %i=bytesperpixel\n",
1496 bytesperpixel);
1497 return -EFAULT;
1499 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1500 if (rump)
1501 caches++;
1503 if (badinput) {
1504 JOM(8, "ERROR: 0x%02X=->field_buffer"
1505 "[%i][%i].input, "
1506 "0x%02X=(0x08|->input)\n",
1507 peasycap->field_buffer
1508 [kex][mex].input, kex, mex,
1509 (0x08|peasycap->input));
1511 rc = redaub(peasycap, pad, pex, much, more,
1512 mask, margin, isuy);
1513 if (0 > rc) {
1514 SAM("ERROR: redaub() failed\n");
1515 return -EFAULT;
1517 over -= much; cz += much;
1518 pex += much; rex -= much;
1519 if (!rex) {
1520 mex++;
1521 pex = peasycap->field_buffer[kex][mex].pgo;
1522 rex = PAGE_SIZE;
1523 if (peasycap->field_buffer[kex][mex].input !=
1524 (0x08|peasycap->input))
1525 badinput = true;
1527 pad += more;
1528 rad -= more;
1529 if (!rad) {
1530 mad++;
1531 pad = peasycap->frame_buffer[kad][mad].pgo;
1532 rad = PAGE_SIZE;
1533 if (rump) {
1534 pad += rump;
1535 rad -= rump;
1538 } while (over);
1539 /*---------------------------------------------------------------------------*/
1541 * OTHERWISE JUST
1542 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1544 /*---------------------------------------------------------------------------*/
1545 } else {
1546 over = w2;
1547 do {
1548 if (!rex) {
1549 mex++;
1550 pex = peasycap->field_buffer[kex][mex].pgo;
1551 rex = PAGE_SIZE;
1552 if (peasycap->field_buffer[kex][mex].input !=
1553 (0x08|peasycap->input)) {
1554 JOM(8, "ERROR: 0x%02X=->field_buffer"
1555 "[%i][%i].input, "
1556 "0x%02X=(0x08|->input)\n",
1557 peasycap->field_buffer
1558 [kex][mex].input, kex, mex,
1559 (0x08|peasycap->input));
1560 badinput = true;
1563 much = over;
1564 if (rex < much)
1565 much = rex;
1566 over -= much;
1567 cz += much;
1568 pex += much;
1569 rex -= much;
1570 } while (over);
1573 /*---------------------------------------------------------------------------*/
1575 * SANITY CHECKS
1577 /*---------------------------------------------------------------------------*/
1578 c2 = (mex + 1)*PAGE_SIZE - rex;
1579 if (cz != c2)
1580 SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1581 c3 = (mad + 1)*PAGE_SIZE - rad;
1583 if (!decimatepixel) {
1584 if (bytesperpixel * cz != c3)
1585 SAM("ERROR: discrepancy %i in bytes written\n",
1586 c3 - (bytesperpixel * cz));
1587 } else {
1588 if (!odd) {
1589 if (bytesperpixel *
1590 cz != (4 * c3))
1591 SAM("ERROR: discrepancy %i in bytes written\n",
1592 (2*c3)-(bytesperpixel * cz));
1593 } else {
1594 if (0 != c3)
1595 SAM("ERROR: discrepancy %i "
1596 "in bytes written\n", c3);
1599 if (rump)
1600 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1602 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1603 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1605 if (odd)
1606 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1608 if (peasycap->field_read == peasycap->field_fill)
1609 SAM("WARNING: on exit, filling field buffer %i\n",
1610 peasycap->field_read);
1611 /*---------------------------------------------------------------------------*/
1613 * CALCULATE VIDEO STREAMING RATE
1615 /*---------------------------------------------------------------------------*/
1616 do_gettimeofday(&timeval);
1617 if (peasycap->timeval6.tv_sec) {
1618 below = ((long long int)(1000000)) *
1619 ((long long int)(timeval.tv_sec -
1620 peasycap->timeval6.tv_sec)) +
1621 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1622 above = (long long int)1000000;
1624 sdr = signed_div(above, below);
1625 above = sdr.quotient;
1626 remainder = (u32)sdr.remainder;
1628 JOM(8, "video streaming at %3lli.%03i fields per second\n",
1629 above, (remainder/1000));
1631 peasycap->timeval6 = timeval;
1633 if (caches)
1634 JOM(8, "%i=caches\n", caches);
1635 return 0;
1637 /*****************************************************************************/
1638 struct signed_div_result
1639 signed_div(long long int above, long long int below)
1641 struct signed_div_result sdr;
1643 if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) {
1644 sdr.remainder = (unsigned long long int) do_div(above, below);
1645 sdr.quotient = (long long int) above;
1646 } else {
1647 if (0 > above)
1648 above = -above;
1649 if (0 > below)
1650 below = -below;
1651 sdr.remainder = (unsigned long long int) do_div(above, below);
1652 sdr.quotient = -((long long int) above);
1654 return sdr;
1656 /*****************************************************************************/
1657 /*---------------------------------------------------------------------------*/
1659 * DECIMATION AND COLOURSPACE CONVERSION.
1661 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1662 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1663 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1664 * ALSO ENSURE THAT much IS EVEN.
1666 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1667 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1669 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1670 * 0x03 & mask = number of bytes to be written to cache instead of to
1671 * frame buffer
1672 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1673 * 0x08 & mask => do not set the chrominance for last pixel
1675 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1677 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1678 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1679 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1681 /*---------------------------------------------------------------------------*/
1683 redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1684 u8 mask, u8 margin, bool isuy)
1686 static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1687 u8 *pcache;
1688 u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1689 int bytesperpixel;
1690 bool byteswaporder, decimatepixel, last;
1691 int j, rump;
1692 s32 tmp;
1694 if (much % 2) {
1695 SAM("MISTAKE: much is odd\n");
1696 return -EFAULT;
1698 bytesperpixel = peasycap->bytesperpixel;
1699 byteswaporder = peasycap->byteswaporder;
1700 decimatepixel = peasycap->decimatepixel;
1702 /*---------------------------------------------------------------------------*/
1703 if (!bu[255]) {
1704 for (j = 0; j < 112; j++) {
1705 tmp = (0xFF00 & (453 * j)) >> 8;
1706 bu[j + 128] = tmp; bu[127 - j] = -tmp;
1707 tmp = (0xFF00 & (359 * j)) >> 8;
1708 rv[j + 128] = tmp; rv[127 - j] = -tmp;
1709 tmp = (0xFF00 & (88 * j)) >> 8;
1710 gu[j + 128] = tmp; gu[127 - j] = -tmp;
1711 tmp = (0xFF00 & (183 * j)) >> 8;
1712 gv[j + 128] = tmp; gv[127 - j] = -tmp;
1714 for (j = 0; j < 16; j++) {
1715 bu[j] = bu[16]; rv[j] = rv[16];
1716 gu[j] = gu[16]; gv[j] = gv[16];
1718 for (j = 240; j < 256; j++) {
1719 bu[j] = bu[239]; rv[j] = rv[239];
1720 gu[j] = gu[239]; gv[j] = gv[239];
1722 for (j = 16; j < 236; j++)
1723 ay[j] = j;
1724 for (j = 0; j < 16; j++)
1725 ay[j] = ay[16];
1726 for (j = 236; j < 256; j++)
1727 ay[j] = ay[235];
1728 JOM(8, "lookup tables are prepared\n");
1730 pcache = peasycap->pcache;
1731 if (!pcache)
1732 pcache = &peasycap->cache[0];
1733 /*---------------------------------------------------------------------------*/
1735 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1737 /*---------------------------------------------------------------------------*/
1738 if (!pcache) {
1739 SAM("MISTAKE: pcache is NULL\n");
1740 return -EFAULT;
1743 if (pcache != &peasycap->cache[0])
1744 JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1745 p2 = &peasycap->cache[0];
1746 p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1747 while (p2 < pcache) {
1748 *p3++ = *p2; p2++;
1750 pcache = &peasycap->cache[0];
1751 if (p3 != pad) {
1752 SAM("MISTAKE: pointer misalignment\n");
1753 return -EFAULT;
1755 /*---------------------------------------------------------------------------*/
1756 rump = (int)(0x03 & mask);
1757 u = 0; v = 0;
1758 p2 = (u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1759 p2++;
1761 if (isuy)
1762 u = *(p2 - 1);
1763 else
1764 v = *(p2 - 1);
1766 if (rump)
1767 JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1769 /*---------------------------------------------------------------------------*/
1770 switch (bytesperpixel) {
1771 case 2: {
1772 if (!decimatepixel) {
1773 memcpy(pad, pex, (size_t)much);
1774 if (!byteswaporder) {
1775 /* UYVY */
1776 return 0;
1777 } else {
1778 /* YUYV */
1779 p3 = (u8 *)pad; pz = p3 + much;
1780 while (pz > p3) {
1781 c = *p3;
1782 *p3 = *(p3 + 1);
1783 *(p3 + 1) = c;
1784 p3 += 2;
1786 return 0;
1788 } else {
1789 if (!byteswaporder) {
1790 /* UYVY DECIMATED */
1791 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1792 while (pz > p2) {
1793 *p3 = *p2;
1794 *(p3 + 1) = *(p2 + 1);
1795 *(p3 + 2) = *(p2 + 2);
1796 *(p3 + 3) = *(p2 + 3);
1797 p3 += 4; p2 += 8;
1799 return 0;
1800 } else {
1801 /* YUYV DECIMATED */
1802 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1803 while (pz > p2) {
1804 *p3 = *(p2 + 1);
1805 *(p3 + 1) = *p2;
1806 *(p3 + 2) = *(p2 + 3);
1807 *(p3 + 3) = *(p2 + 2);
1808 p3 += 4; p2 += 8;
1810 return 0;
1813 break;
1815 case 3:
1817 if (!decimatepixel) {
1818 if (!byteswaporder) {
1819 /* RGB */
1820 while (pz > p2) {
1821 if (pr <= (p3 + bytesperpixel))
1822 last = true;
1823 else
1824 last = false;
1825 y = *p2;
1826 if (last && (0x0C & mask)) {
1827 if (0x04 & mask) {
1828 if (isuy)
1829 v = margin;
1830 else
1831 u = margin;
1832 } else
1833 if (0x08 & mask)
1835 } else {
1836 if (isuy)
1837 v = *(p2 + 1);
1838 else
1839 u = *(p2 + 1);
1842 tmp = ay[(int)y] + rv[(int)v];
1843 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1844 0 : (u8)tmp);
1845 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1846 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1847 0 : (u8)tmp);
1848 tmp = ay[(int)y] + bu[(int)u];
1849 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1850 0 : (u8)tmp);
1852 if (last && rump) {
1853 pcache = &peasycap->cache[0];
1854 switch (bytesperpixel - rump) {
1855 case 1: {
1856 *p3 = r;
1857 *pcache++ = g;
1858 *pcache++ = b;
1859 break;
1861 case 2: {
1862 *p3 = r;
1863 *(p3 + 1) = g;
1864 *pcache++ = b;
1865 break;
1867 default: {
1868 SAM("MISTAKE: %i=rump\n",
1869 bytesperpixel - rump);
1870 return -EFAULT;
1873 } else {
1874 *p3 = r;
1875 *(p3 + 1) = g;
1876 *(p3 + 2) = b;
1878 p2 += 2;
1879 if (isuy)
1880 isuy = false;
1881 else
1882 isuy = true;
1883 p3 += bytesperpixel;
1885 return 0;
1886 } else {
1887 /* BGR */
1888 while (pz > p2) {
1889 if (pr <= (p3 + bytesperpixel))
1890 last = true;
1891 else
1892 last = false;
1893 y = *p2;
1894 if (last && (0x0C & mask)) {
1895 if (0x04 & mask) {
1896 if (isuy)
1897 v = margin;
1898 else
1899 u = margin;
1901 else
1902 if (0x08 & mask)
1904 } else {
1905 if (isuy)
1906 v = *(p2 + 1);
1907 else
1908 u = *(p2 + 1);
1911 tmp = ay[(int)y] + rv[(int)v];
1912 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1913 0 : (u8)tmp);
1914 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1915 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1916 0 : (u8)tmp);
1917 tmp = ay[(int)y] + bu[(int)u];
1918 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1919 0 : (u8)tmp);
1921 if (last && rump) {
1922 pcache = &peasycap->cache[0];
1923 switch (bytesperpixel - rump) {
1924 case 1: {
1925 *p3 = b;
1926 *pcache++ = g;
1927 *pcache++ = r;
1928 break;
1930 case 2: {
1931 *p3 = b;
1932 *(p3 + 1) = g;
1933 *pcache++ = r;
1934 break;
1936 default: {
1937 SAM("MISTAKE: %i=rump\n",
1938 bytesperpixel - rump);
1939 return -EFAULT;
1942 } else {
1943 *p3 = b;
1944 *(p3 + 1) = g;
1945 *(p3 + 2) = r;
1947 p2 += 2;
1948 if (isuy)
1949 isuy = false;
1950 else
1951 isuy = true;
1952 p3 += bytesperpixel;
1955 return 0;
1956 } else {
1957 if (!byteswaporder) {
1958 /* RGB DECIMATED */
1959 while (pz > p2) {
1960 if (pr <= (p3 + bytesperpixel))
1961 last = true;
1962 else
1963 last = false;
1964 y = *p2;
1965 if (last && (0x0C & mask)) {
1966 if (0x04 & mask) {
1967 if (isuy)
1968 v = margin;
1969 else
1970 u = margin;
1971 } else
1972 if (0x08 & mask)
1974 } else {
1975 if (isuy)
1976 v = *(p2 + 1);
1977 else
1978 u = *(p2 + 1);
1981 if (isuy) {
1982 tmp = ay[(int)y] + rv[(int)v];
1983 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1984 0 : (u8)tmp);
1985 tmp = ay[(int)y] - gu[(int)u] -
1986 gv[(int)v];
1987 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1988 0 : (u8)tmp);
1989 tmp = ay[(int)y] + bu[(int)u];
1990 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1991 0 : (u8)tmp);
1993 if (last && rump) {
1994 pcache = &peasycap->cache[0];
1995 switch (bytesperpixel - rump) {
1996 case 1: {
1997 *p3 = r;
1998 *pcache++ = g;
1999 *pcache++ = b;
2000 break;
2002 case 2: {
2003 *p3 = r;
2004 *(p3 + 1) = g;
2005 *pcache++ = b;
2006 break;
2008 default: {
2009 SAM("MISTAKE: "
2010 "%i=rump\n",
2011 bytesperpixel - rump);
2012 return -EFAULT;
2015 } else {
2016 *p3 = r;
2017 *(p3 + 1) = g;
2018 *(p3 + 2) = b;
2020 isuy = false;
2021 p3 += bytesperpixel;
2022 } else {
2023 isuy = true;
2025 p2 += 2;
2027 return 0;
2028 } else {
2029 /* BGR DECIMATED */
2030 while (pz > p2) {
2031 if (pr <= (p3 + bytesperpixel))
2032 last = true;
2033 else
2034 last = false;
2035 y = *p2;
2036 if (last && (0x0C & mask)) {
2037 if (0x04 & mask) {
2038 if (isuy)
2039 v = margin;
2040 else
2041 u = margin;
2042 } else
2043 if (0x08 & mask)
2045 } else {
2046 if (isuy)
2047 v = *(p2 + 1);
2048 else
2049 u = *(p2 + 1);
2052 if (isuy) {
2054 tmp = ay[(int)y] + rv[(int)v];
2055 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2056 0 : (u8)tmp);
2057 tmp = ay[(int)y] - gu[(int)u] -
2058 gv[(int)v];
2059 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2060 0 : (u8)tmp);
2061 tmp = ay[(int)y] + bu[(int)u];
2062 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2063 0 : (u8)tmp);
2065 if (last && rump) {
2066 pcache = &peasycap->cache[0];
2067 switch (bytesperpixel - rump) {
2068 case 1: {
2069 *p3 = b;
2070 *pcache++ = g;
2071 *pcache++ = r;
2072 break;
2074 case 2: {
2075 *p3 = b;
2076 *(p3 + 1) = g;
2077 *pcache++ = r;
2078 break;
2080 default: {
2081 SAM("MISTAKE: "
2082 "%i=rump\n",
2083 bytesperpixel - rump);
2084 return -EFAULT;
2087 } else {
2088 *p3 = b;
2089 *(p3 + 1) = g;
2090 *(p3 + 2) = r;
2092 isuy = false;
2093 p3 += bytesperpixel;
2095 else
2096 isuy = true;
2097 p2 += 2;
2099 return 0;
2102 break;
2104 case 4:
2106 if (!decimatepixel) {
2107 if (!byteswaporder) {
2108 /* RGBA */
2109 while (pz > p2) {
2110 if (pr <= (p3 + bytesperpixel))
2111 last = true;
2112 else
2113 last = false;
2114 y = *p2;
2115 if (last && (0x0C & mask)) {
2116 if (0x04 & mask) {
2117 if (isuy)
2118 v = margin;
2119 else
2120 u = margin;
2121 } else
2122 if (0x08 & mask)
2124 } else {
2125 if (isuy)
2126 v = *(p2 + 1);
2127 else
2128 u = *(p2 + 1);
2131 tmp = ay[(int)y] + rv[(int)v];
2132 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2133 0 : (u8)tmp);
2134 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2135 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2136 0 : (u8)tmp);
2137 tmp = ay[(int)y] + bu[(int)u];
2138 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2139 0 : (u8)tmp);
2141 if (last && rump) {
2142 pcache = &peasycap->cache[0];
2143 switch (bytesperpixel - rump) {
2144 case 1: {
2145 *p3 = r;
2146 *pcache++ = g;
2147 *pcache++ = b;
2148 *pcache++ = 0;
2149 break;
2151 case 2: {
2152 *p3 = r;
2153 *(p3 + 1) = g;
2154 *pcache++ = b;
2155 *pcache++ = 0;
2156 break;
2158 case 3: {
2159 *p3 = r;
2160 *(p3 + 1) = g;
2161 *(p3 + 2) = b;
2162 *pcache++ = 0;
2163 break;
2165 default: {
2166 SAM("MISTAKE: %i=rump\n",
2167 bytesperpixel - rump);
2168 return -EFAULT;
2171 } else {
2172 *p3 = r;
2173 *(p3 + 1) = g;
2174 *(p3 + 2) = b;
2175 *(p3 + 3) = 0;
2177 p2 += 2;
2178 if (isuy)
2179 isuy = false;
2180 else
2181 isuy = true;
2182 p3 += bytesperpixel;
2184 return 0;
2185 } else {
2187 * BGRA
2189 while (pz > p2) {
2190 if (pr <= (p3 + bytesperpixel))
2191 last = true;
2192 else
2193 last = false;
2194 y = *p2;
2195 if (last && (0x0C & mask)) {
2196 if (0x04 & mask) {
2197 if (isuy)
2198 v = margin;
2199 else
2200 u = margin;
2201 } else
2202 if (0x08 & mask)
2204 } else {
2205 if (isuy)
2206 v = *(p2 + 1);
2207 else
2208 u = *(p2 + 1);
2211 tmp = ay[(int)y] + rv[(int)v];
2212 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2213 0 : (u8)tmp);
2214 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2215 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2216 0 : (u8)tmp);
2217 tmp = ay[(int)y] + bu[(int)u];
2218 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2219 0 : (u8)tmp);
2221 if (last && rump) {
2222 pcache = &peasycap->cache[0];
2223 switch (bytesperpixel - rump) {
2224 case 1: {
2225 *p3 = b;
2226 *pcache++ = g;
2227 *pcache++ = r;
2228 *pcache++ = 0;
2229 break;
2231 case 2: {
2232 *p3 = b;
2233 *(p3 + 1) = g;
2234 *pcache++ = r;
2235 *pcache++ = 0;
2236 break;
2238 case 3: {
2239 *p3 = b;
2240 *(p3 + 1) = g;
2241 *(p3 + 2) = r;
2242 *pcache++ = 0;
2243 break;
2245 default:
2246 SAM("MISTAKE: %i=rump\n",
2247 bytesperpixel - rump);
2248 return -EFAULT;
2250 } else {
2251 *p3 = b;
2252 *(p3 + 1) = g;
2253 *(p3 + 2) = r;
2254 *(p3 + 3) = 0;
2256 p2 += 2;
2257 if (isuy)
2258 isuy = false;
2259 else
2260 isuy = true;
2261 p3 += bytesperpixel;
2264 return 0;
2265 } else {
2266 if (!byteswaporder) {
2268 * RGBA DECIMATED
2270 while (pz > p2) {
2271 if (pr <= (p3 + bytesperpixel))
2272 last = true;
2273 else
2274 last = false;
2275 y = *p2;
2276 if (last && (0x0C & mask)) {
2277 if (0x04 & mask) {
2278 if (isuy)
2279 v = margin;
2280 else
2281 u = margin;
2282 } else
2283 if (0x08 & mask)
2285 } else {
2286 if (isuy)
2287 v = *(p2 + 1);
2288 else
2289 u = *(p2 + 1);
2292 if (isuy) {
2294 tmp = ay[(int)y] + rv[(int)v];
2295 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2296 0 : (u8)tmp);
2297 tmp = ay[(int)y] - gu[(int)u] -
2298 gv[(int)v];
2299 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2300 0 : (u8)tmp);
2301 tmp = ay[(int)y] + bu[(int)u];
2302 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2303 0 : (u8)tmp);
2305 if (last && rump) {
2306 pcache = &peasycap->cache[0];
2307 switch (bytesperpixel - rump) {
2308 case 1: {
2309 *p3 = r;
2310 *pcache++ = g;
2311 *pcache++ = b;
2312 *pcache++ = 0;
2313 break;
2315 case 2: {
2316 *p3 = r;
2317 *(p3 + 1) = g;
2318 *pcache++ = b;
2319 *pcache++ = 0;
2320 break;
2322 case 3: {
2323 *p3 = r;
2324 *(p3 + 1) = g;
2325 *(p3 + 2) = b;
2326 *pcache++ = 0;
2327 break;
2329 default: {
2330 SAM("MISTAKE: "
2331 "%i=rump\n",
2332 bytesperpixel -
2333 rump);
2334 return -EFAULT;
2337 } else {
2338 *p3 = r;
2339 *(p3 + 1) = g;
2340 *(p3 + 2) = b;
2341 *(p3 + 3) = 0;
2343 isuy = false;
2344 p3 += bytesperpixel;
2345 } else
2346 isuy = true;
2347 p2 += 2;
2349 return 0;
2350 } else {
2352 * BGRA DECIMATED
2354 while (pz > p2) {
2355 if (pr <= (p3 + bytesperpixel))
2356 last = true;
2357 else
2358 last = false;
2359 y = *p2;
2360 if (last && (0x0C & mask)) {
2361 if (0x04 & mask) {
2362 if (isuy)
2363 v = margin;
2364 else
2365 u = margin;
2366 } else
2367 if (0x08 & mask)
2369 } else {
2370 if (isuy)
2371 v = *(p2 + 1);
2372 else
2373 u = *(p2 + 1);
2376 if (isuy) {
2377 tmp = ay[(int)y] + rv[(int)v];
2378 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2379 0 : (u8)tmp);
2380 tmp = ay[(int)y] - gu[(int)u] -
2381 gv[(int)v];
2382 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2383 0 : (u8)tmp);
2384 tmp = ay[(int)y] + bu[(int)u];
2385 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2386 0 : (u8)tmp);
2388 if (last && rump) {
2389 pcache = &peasycap->cache[0];
2390 switch (bytesperpixel - rump) {
2391 case 1: {
2392 *p3 = b;
2393 *pcache++ = g;
2394 *pcache++ = r;
2395 *pcache++ = 0;
2396 break;
2398 case 2: {
2399 *p3 = b;
2400 *(p3 + 1) = g;
2401 *pcache++ = r;
2402 *pcache++ = 0;
2403 break;
2405 case 3: {
2406 *p3 = b;
2407 *(p3 + 1) = g;
2408 *(p3 + 2) = r;
2409 *pcache++ = 0;
2410 break;
2412 default: {
2413 SAM("MISTAKE: "
2414 "%i=rump\n",
2415 bytesperpixel - rump);
2416 return -EFAULT;
2419 } else {
2420 *p3 = b;
2421 *(p3 + 1) = g;
2422 *(p3 + 2) = r;
2423 *(p3 + 3) = 0;
2425 isuy = false;
2426 p3 += bytesperpixel;
2427 } else
2428 isuy = true;
2429 p2 += 2;
2431 return 0;
2434 break;
2436 default: {
2437 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2438 return -EFAULT;
2441 return 0;
2443 /*****************************************************************************/
2445 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2447 /*****************************************************************************/
2448 static void easycap_vma_open(struct vm_area_struct *pvma)
2450 struct easycap *peasycap;
2452 peasycap = pvma->vm_private_data;
2453 if (!peasycap) {
2454 SAY("ERROR: peasycap is NULL\n");
2455 return;
2457 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2458 SAY("ERROR: bad peasycap: %p\n", peasycap);
2459 return;
2461 peasycap->vma_many++;
2462 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2463 return;
2465 /*****************************************************************************/
2466 static void easycap_vma_close(struct vm_area_struct *pvma)
2468 struct easycap *peasycap;
2470 peasycap = pvma->vm_private_data;
2471 if (!peasycap) {
2472 SAY("ERROR: peasycap is NULL\n");
2473 return;
2475 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2476 SAY("ERROR: bad peasycap: %p\n", peasycap);
2477 return;
2479 peasycap->vma_many--;
2480 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2481 return;
2483 /*****************************************************************************/
2484 static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2486 int k, m, retcode;
2487 void *pbuf;
2488 struct page *page;
2489 struct easycap *peasycap;
2491 retcode = VM_FAULT_NOPAGE;
2493 if (!pvma) {
2494 SAY("pvma is NULL\n");
2495 return retcode;
2497 if (!pvmf) {
2498 SAY("pvmf is NULL\n");
2499 return retcode;
2502 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2503 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2505 if (!m)
2506 JOT(4, "%4i=k, %4i=m\n", k, m);
2507 else
2508 JOT(16, "%4i=k, %4i=m\n", k, m);
2510 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2511 SAY("ERROR: buffer index %i out of range\n", k);
2512 return retcode;
2514 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2515 SAY("ERROR: page number %i out of range\n", m);
2516 return retcode;
2518 peasycap = pvma->vm_private_data;
2519 if (!peasycap) {
2520 SAY("ERROR: peasycap is NULL\n");
2521 return retcode;
2523 /*---------------------------------------------------------------------------*/
2524 pbuf = peasycap->frame_buffer[k][m].pgo;
2525 if (!pbuf) {
2526 SAM("ERROR: pbuf is NULL\n");
2527 return retcode;
2529 page = virt_to_page(pbuf);
2530 if (!page) {
2531 SAM("ERROR: page is NULL\n");
2532 return retcode;
2534 get_page(page);
2535 /*---------------------------------------------------------------------------*/
2536 if (!page) {
2537 SAM("ERROR: page is NULL after get_page(page)\n");
2538 } else {
2539 pvmf->page = page;
2540 retcode = VM_FAULT_MINOR;
2542 return retcode;
2545 static const struct vm_operations_struct easycap_vm_ops = {
2546 .open = easycap_vma_open,
2547 .close = easycap_vma_close,
2548 .fault = easycap_vma_fault,
2551 static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2553 JOT(8, "\n");
2555 pvma->vm_ops = &easycap_vm_ops;
2556 pvma->vm_flags |= VM_RESERVED;
2557 if (file)
2558 pvma->vm_private_data = file->private_data;
2559 easycap_vma_open(pvma);
2560 return 0;
2562 /*****************************************************************************/
2563 /*---------------------------------------------------------------------------*/
2565 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2566 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2567 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2569 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2571 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2572 * STORED IN THE TWO-BYTE STATUS PARAMETER
2573 * peasycap->field_buffer[peasycap->field_fill][0].kount
2574 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2576 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2577 * CHIP.
2579 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2580 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2581 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2582 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2583 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2584 * 0 != (kount & 0x0400) => RESERVED
2585 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2586 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2588 /*---------------------------------------------------------------------------*/
2589 static void easycap_complete(struct urb *purb)
2591 struct easycap *peasycap;
2592 struct data_buffer *pfield_buffer;
2593 char errbuf[16];
2594 int i, more, much, leap, rc, last;
2595 int videofieldamount;
2596 unsigned int override, bad;
2597 int framestatus, framelength, frameactual, frameoffset;
2598 u8 *pu;
2600 if (!purb) {
2601 SAY("ERROR: easycap_complete(): purb is NULL\n");
2602 return;
2604 peasycap = purb->context;
2605 if (!peasycap) {
2606 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2607 return;
2609 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2610 SAY("ERROR: bad peasycap: %p\n", peasycap);
2611 return;
2613 if (peasycap->video_eof)
2614 return;
2615 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2616 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2617 break;
2618 JOM(16, "%2i=urb\n", i);
2619 last = peasycap->video_isoc_sequence;
2620 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2621 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2622 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2623 last, i);
2625 peasycap->video_isoc_sequence = i;
2627 if (peasycap->video_idle) {
2628 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2629 peasycap->video_idle, peasycap->video_isoc_streaming);
2630 if (peasycap->video_isoc_streaming) {
2631 rc = usb_submit_urb(purb, GFP_ATOMIC);
2632 if (rc) {
2633 SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2634 if (-ENODEV != rc)
2635 SAM("ERROR: while %i=video_idle, "
2636 "usb_submit_urb() "
2637 "failed with rc:\n",
2638 peasycap->video_idle);
2641 return;
2643 override = 0;
2644 /*---------------------------------------------------------------------------*/
2645 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2646 SAM("ERROR: bad peasycap->field_fill\n");
2647 return;
2649 if (purb->status) {
2650 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2651 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2652 return;
2655 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2656 SAM("ERROR: bad urb status -%s: %d\n",
2657 strerror(purb->status), purb->status);
2658 /*---------------------------------------------------------------------------*/
2659 } else {
2660 for (i = 0; i < purb->number_of_packets; i++) {
2661 if (0 != purb->iso_frame_desc[i].status) {
2662 (peasycap->field_buffer
2663 [peasycap->field_fill][0].kount) |= 0x8000 ;
2664 /* FIXME: 1. missing '-' check boundaries */
2665 strcpy(&errbuf[0],
2666 strerror(purb->iso_frame_desc[i].status));
2668 framestatus = purb->iso_frame_desc[i].status;
2669 framelength = purb->iso_frame_desc[i].length;
2670 frameactual = purb->iso_frame_desc[i].actual_length;
2671 frameoffset = purb->iso_frame_desc[i].offset;
2673 JOM(16, "frame[%2i]:"
2674 "%4i=status "
2675 "%4i=actual "
2676 "%4i=length "
2677 "%5i=offset\n",
2678 i, framestatus, frameactual, framelength, frameoffset);
2679 if (!purb->iso_frame_desc[i].status) {
2680 more = purb->iso_frame_desc[i].actual_length;
2681 pfield_buffer = &peasycap->field_buffer
2682 [peasycap->field_fill][peasycap->field_page];
2683 videofieldamount = (peasycap->field_page *
2684 PAGE_SIZE) +
2685 (int)(pfield_buffer->pto - pfield_buffer->pgo);
2686 if (4 == more)
2687 peasycap->video_mt++;
2688 if (4 < more) {
2689 if (peasycap->video_mt) {
2690 JOM(8, "%4i empty video urb frames\n",
2691 peasycap->video_mt);
2692 peasycap->video_mt = 0;
2694 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2695 SAM("ERROR: bad peasycap->field_fill\n");
2696 return;
2698 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2699 peasycap->field_page) {
2700 SAM("ERROR: bad peasycap->field_page\n");
2701 return;
2703 pfield_buffer = &peasycap->field_buffer
2704 [peasycap->field_fill][peasycap->field_page];
2705 pu = (u8 *)(purb->transfer_buffer +
2706 purb->iso_frame_desc[i].offset);
2707 if (0x80 & *pu)
2708 leap = 8;
2709 else
2710 leap = 4;
2711 /*--------------------------------------------------------------------------*/
2713 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2714 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2715 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2717 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2718 * BYTE OF
2719 * peasycap->field_buffer[peasycap->field_fill][0].kount
2720 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2721 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
2722 * NOTHING IS OFFERED TO dqbuf().
2724 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2725 * RESTS WITH dqbuf().
2727 /*---------------------------------------------------------------------------*/
2728 if ((8 == more) || override) {
2729 if (videofieldamount >
2730 peasycap->videofieldamount) {
2731 if (2 == videofieldamount -
2732 peasycap->
2733 videofieldamount) {
2734 (peasycap->field_buffer
2735 [peasycap->field_fill]
2736 [0].kount) |= 0x0100;
2737 peasycap->video_junk += (1 +
2738 VIDEO_JUNK_TOLERATE);
2739 } else
2740 (peasycap->field_buffer
2741 [peasycap->field_fill]
2742 [0].kount) |= 0x4000;
2743 } else if (videofieldamount <
2744 peasycap->
2745 videofieldamount) {
2746 (peasycap->field_buffer
2747 [peasycap->field_fill]
2748 [0].kount) |= 0x2000;
2750 bad = 0xFF00 & peasycap->field_buffer
2751 [peasycap->field_fill]
2752 [0].kount;
2753 if (!bad) {
2754 (peasycap->video_junk)--;
2755 if (-VIDEO_JUNK_TOLERATE >
2756 peasycap->video_junk)
2757 peasycap->video_junk =
2758 -VIDEO_JUNK_TOLERATE;
2759 peasycap->field_read =
2760 (peasycap->
2761 field_fill)++;
2762 if (FIELD_BUFFER_MANY <=
2763 peasycap->
2764 field_fill)
2765 peasycap->
2766 field_fill = 0;
2767 peasycap->field_page = 0;
2768 pfield_buffer = &peasycap->
2769 field_buffer
2770 [peasycap->
2771 field_fill]
2772 [peasycap->
2773 field_page];
2774 pfield_buffer->pto =
2775 pfield_buffer->pgo;
2776 JOM(8, "bumped to: %i="
2777 "peasycap->"
2778 "field_fill %i="
2779 "parity\n",
2780 peasycap->field_fill,
2781 0x00FF &
2782 pfield_buffer->kount);
2783 JOM(8, "field buffer %i has "
2784 "%i bytes fit to be "
2785 "read\n",
2786 peasycap->field_read,
2787 videofieldamount);
2788 JOM(8, "wakeup call to "
2789 "wq_video, "
2790 "%i=field_read "
2791 "%i=field_fill "
2792 "%i=parity\n",
2793 peasycap->field_read,
2794 peasycap->field_fill,
2795 0x00FF & peasycap->
2796 field_buffer
2797 [peasycap->
2798 field_read][0].kount);
2799 wake_up_interruptible
2800 (&(peasycap->
2801 wq_video));
2802 do_gettimeofday
2803 (&peasycap->timeval7);
2804 } else {
2805 peasycap->video_junk++;
2806 if (bad & 0x0010)
2807 peasycap->video_junk +=
2808 (1 + VIDEO_JUNK_TOLERATE/2);
2809 JOM(8, "field buffer %i had %i "
2810 "bytes, now discarded: "
2811 "0x%04X\n",
2812 peasycap->field_fill,
2813 videofieldamount,
2814 (0xFF00 &
2815 peasycap->field_buffer
2816 [peasycap->field_fill][0].
2817 kount));
2818 (peasycap->field_fill)++;
2820 if (FIELD_BUFFER_MANY <=
2821 peasycap->field_fill)
2822 peasycap->field_fill = 0;
2823 peasycap->field_page = 0;
2824 pfield_buffer =
2825 &peasycap->field_buffer
2826 [peasycap->field_fill]
2827 [peasycap->field_page];
2828 pfield_buffer->pto =
2829 pfield_buffer->pgo;
2831 JOM(8, "bumped to: %i=peasycap->"
2832 "field_fill %i=parity\n",
2833 peasycap->field_fill,
2834 0x00FF & pfield_buffer->kount);
2836 if (8 == more) {
2837 JOM(8, "end-of-field: received "
2838 "parity byte 0x%02X\n",
2839 (0xFF & *pu));
2840 if (0x40 & *pu)
2841 pfield_buffer->kount = 0x0000;
2842 else
2843 pfield_buffer->kount = 0x0001;
2844 pfield_buffer->input = 0x08 |
2845 (0x07 & peasycap->input);
2846 JOM(8, "end-of-field: 0x%02X=kount\n",
2847 0xFF & pfield_buffer->kount);
2850 /*---------------------------------------------------------------------------*/
2852 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2854 /*---------------------------------------------------------------------------*/
2855 pu += leap;
2856 more -= leap;
2858 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2859 SAM("ERROR: bad peasycap->field_fill\n");
2860 return;
2862 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2863 SAM("ERROR: bad peasycap->field_page\n");
2864 return;
2866 pfield_buffer = &peasycap->field_buffer
2867 [peasycap->field_fill][peasycap->field_page];
2868 while (more) {
2869 pfield_buffer = &peasycap->field_buffer
2870 [peasycap->field_fill]
2871 [peasycap->field_page];
2872 if (PAGE_SIZE < (pfield_buffer->pto -
2873 pfield_buffer->pgo)) {
2874 SAM("ERROR: bad pfield_buffer->pto\n");
2875 return;
2877 if (PAGE_SIZE == (pfield_buffer->pto -
2878 pfield_buffer->pgo)) {
2879 (peasycap->field_page)++;
2880 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2881 peasycap->field_page) {
2882 JOM(16, "wrapping peasycap->"
2883 "field_page\n");
2884 peasycap->field_page = 0;
2886 pfield_buffer = &peasycap->
2887 field_buffer
2888 [peasycap->field_fill]
2889 [peasycap->field_page];
2890 pfield_buffer->pto = pfield_buffer->pgo;
2891 pfield_buffer->input = 0x08 |
2892 (0x07 & peasycap->input);
2893 if ((peasycap->field_buffer[peasycap->
2894 field_fill][0]).
2895 input !=
2896 pfield_buffer->input)
2897 (peasycap->field_buffer
2898 [peasycap->field_fill]
2899 [0]).kount |= 0x1000;
2902 much = PAGE_SIZE -
2903 (int)(pfield_buffer->pto -
2904 pfield_buffer->pgo);
2906 if (much > more)
2907 much = more;
2908 memcpy(pfield_buffer->pto, pu, much);
2909 pu += much;
2910 (pfield_buffer->pto) += much;
2911 more -= much;
2917 /*---------------------------------------------------------------------------*/
2919 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2921 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2922 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2924 /*---------------------------------------------------------------------------*/
2925 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2926 SAM("easycap driver shutting down on condition green\n");
2927 peasycap->status = 1;
2928 peasycap->video_eof = 1;
2929 peasycap->video_junk = 0;
2930 wake_up_interruptible(&peasycap->wq_video);
2931 #if !defined(PERSEVERE)
2932 peasycap->audio_eof = 1;
2933 wake_up_interruptible(&peasycap->wq_audio);
2934 #endif /*PERSEVERE*/
2935 return;
2937 if (peasycap->video_isoc_streaming) {
2938 rc = usb_submit_urb(purb, GFP_ATOMIC);
2939 if (rc) {
2940 SAM("%s: %d\n", strerror(rc), rc);
2941 if (-ENODEV != rc)
2942 SAM("ERROR: while %i=video_idle, "
2943 "usb_submit_urb() "
2944 "failed with rc:\n",
2945 peasycap->video_idle);
2948 return;
2950 static const struct file_operations easycap_fops = {
2951 .owner = THIS_MODULE,
2952 .open = easycap_open,
2953 .unlocked_ioctl = easycap_unlocked_ioctl,
2954 .poll = easycap_poll,
2955 .mmap = easycap_mmap,
2956 .llseek = no_llseek,
2958 static const struct usb_class_driver easycap_class = {
2959 .name = "usb/easycap%d",
2960 .fops = &easycap_fops,
2961 .minor_base = USB_SKEL_MINOR_BASE,
2963 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2964 static const struct v4l2_file_operations v4l2_fops = {
2965 .owner = THIS_MODULE,
2966 .open = easycap_open_noinode,
2967 .unlocked_ioctl = easycap_unlocked_ioctl,
2968 .poll = easycap_poll,
2969 .mmap = easycap_mmap,
2971 /*****************************************************************************/
2972 /*---------------------------------------------------------------------------*/
2974 * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
2975 * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
2977 /*---------------------------------------------------------------------------*/
2978 static int easycap_usb_probe(struct usb_interface *intf,
2979 const struct usb_device_id *id)
2981 struct usb_device *usbdev;
2982 struct usb_host_interface *alt;
2983 struct usb_endpoint_descriptor *ep;
2984 struct usb_interface_descriptor *interface;
2985 struct urb *purb;
2986 struct easycap *peasycap;
2987 int ndong;
2988 struct data_urb *pdata_urb;
2989 size_t wMaxPacketSize;
2990 int ISOCwMaxPacketSize;
2991 int BULKwMaxPacketSize;
2992 int INTwMaxPacketSize;
2993 int CTRLwMaxPacketSize;
2994 u8 bEndpointAddress;
2995 u8 ISOCbEndpointAddress;
2996 u8 INTbEndpointAddress;
2997 int isin, i, j, k, m, rc;
2998 u8 bInterfaceNumber;
2999 u8 bInterfaceClass;
3000 u8 bInterfaceSubClass;
3001 void *pbuf;
3002 int okalt[8], isokalt;
3003 int okepn[8];
3004 int okmps[8];
3005 int maxpacketsize;
3006 u16 mask;
3007 s32 value;
3008 struct easycap_format *peasycap_format;
3009 int fmtidx;
3010 struct inputset *inputset;
3011 struct v4l2_device *pv4l2_device;
3013 usbdev = interface_to_usbdev(intf);
3015 /*---------------------------------------------------------------------------*/
3016 alt = usb_altnum_to_altsetting(intf, 0);
3017 if (!alt) {
3018 SAY("ERROR: usb_host_interface not found\n");
3019 return -EFAULT;
3021 interface = &alt->desc;
3022 if (!interface) {
3023 SAY("ERROR: intf_descriptor is NULL\n");
3024 return -EFAULT;
3026 /*---------------------------------------------------------------------------*/
3028 * GET PROPERTIES OF PROBED INTERFACE
3030 /*---------------------------------------------------------------------------*/
3031 bInterfaceNumber = interface->bInterfaceNumber;
3032 bInterfaceClass = interface->bInterfaceClass;
3033 bInterfaceSubClass = interface->bInterfaceSubClass;
3035 JOT(4, "intf[%i]: num_altsetting=%i\n",
3036 bInterfaceNumber, intf->num_altsetting);
3037 JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
3038 bInterfaceNumber,
3039 (long int)(intf->cur_altsetting - intf->altsetting));
3040 JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
3041 bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
3042 /*---------------------------------------------------------------------------*/
3044 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
3045 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
3046 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
3047 * PHYSICALLY UNPLUGGED.
3049 * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
3050 * INTERFACES 1 AND 2 ARE PROBED.
3052 /*---------------------------------------------------------------------------*/
3053 if (0 == bInterfaceNumber) {
3054 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3055 if (!peasycap) {
3056 SAY("ERROR: Could not allocate peasycap\n");
3057 return -ENOMEM;
3059 /*---------------------------------------------------------------------------*/
3061 * PERFORM URGENT INTIALIZATIONS ...
3063 /*---------------------------------------------------------------------------*/
3064 peasycap->minor = -1;
3065 strcpy(&peasycap->telltale[0], TELLTALE);
3066 kref_init(&peasycap->kref);
3067 JOM(8, "intf[%i]: after kref_init(..._video) "
3068 "%i=peasycap->kref.refcount.counter\n",
3069 bInterfaceNumber, peasycap->kref.refcount.counter);
3071 /* module params */
3072 peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
3074 init_waitqueue_head(&peasycap->wq_video);
3075 init_waitqueue_head(&peasycap->wq_audio);
3076 init_waitqueue_head(&peasycap->wq_trigger);
3078 if (mutex_lock_interruptible(&mutex_dongle)) {
3079 SAY("ERROR: cannot down mutex_dongle\n");
3080 return -ERESTARTSYS;
3081 } else {
3082 /*---------------------------------------------------------------------------*/
3084 * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3085 * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3087 * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3088 * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3089 * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3091 /*---------------------------------------------------------------------------*/
3092 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3093 if ((!easycapdc60_dongle[ndong].peasycap) &&
3094 (!mutex_is_locked(&easycapdc60_dongle
3095 [ndong].mutex_video)) &&
3096 (!mutex_is_locked(&easycapdc60_dongle
3097 [ndong].mutex_audio))) {
3098 easycapdc60_dongle[ndong].peasycap = peasycap;
3099 peasycap->isdongle = ndong;
3100 JOM(8, "intf[%i]: peasycap-->easycap"
3101 "_dongle[%i].peasycap\n",
3102 bInterfaceNumber, ndong);
3103 break;
3106 if (DONGLE_MANY <= ndong) {
3107 SAM("ERROR: too many dongles\n");
3108 mutex_unlock(&mutex_dongle);
3109 return -ENOMEM;
3111 mutex_unlock(&mutex_dongle);
3113 peasycap->allocation_video_struct = sizeof(struct easycap);
3114 peasycap->allocation_video_page = 0;
3115 peasycap->allocation_video_urb = 0;
3116 peasycap->allocation_audio_struct = 0;
3117 peasycap->allocation_audio_page = 0;
3118 peasycap->allocation_audio_urb = 0;
3120 /*---------------------------------------------------------------------------*/
3122 * ... AND FURTHER INITIALIZE THE STRUCTURE
3124 /*---------------------------------------------------------------------------*/
3125 peasycap->pusb_device = usbdev;
3126 peasycap->pusb_interface = intf;
3128 peasycap->ilk = 0;
3129 peasycap->microphone = false;
3131 peasycap->video_interface = -1;
3132 peasycap->video_altsetting_on = -1;
3133 peasycap->video_altsetting_off = -1;
3134 peasycap->video_endpointnumber = -1;
3135 peasycap->video_isoc_maxframesize = -1;
3136 peasycap->video_isoc_buffer_size = -1;
3138 peasycap->audio_interface = -1;
3139 peasycap->audio_altsetting_on = -1;
3140 peasycap->audio_altsetting_off = -1;
3141 peasycap->audio_endpointnumber = -1;
3142 peasycap->audio_isoc_maxframesize = -1;
3143 peasycap->audio_isoc_buffer_size = -1;
3145 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3147 for (k = 0; k < INPUT_MANY; k++)
3148 peasycap->lost[k] = 0;
3149 peasycap->skip = 0;
3150 peasycap->skipped = 0;
3151 peasycap->offerfields = 0;
3152 /*---------------------------------------------------------------------------*/
3154 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3156 /*---------------------------------------------------------------------------*/
3157 rc = fillin_formats();
3158 if (0 > rc) {
3159 SAM("ERROR: fillin_formats() rc = %i\n", rc);
3160 return -EFAULT;
3162 JOM(4, "%i formats available\n", rc);
3163 /*---------------------------------------------------------------------------*/
3165 * ... AND POPULATE easycap.inputset[]
3167 /*---------------------------------------------------------------------------*/
3168 /* FIXME: maybe we just use memset 0 */
3169 inputset = peasycap->inputset;
3170 for (k = 0; k < INPUT_MANY; k++) {
3171 inputset[k].input_ok = 0;
3172 inputset[k].standard_offset_ok = 0;
3173 inputset[k].format_offset_ok = 0;
3174 inputset[k].brightness_ok = 0;
3175 inputset[k].contrast_ok = 0;
3176 inputset[k].saturation_ok = 0;
3177 inputset[k].hue_ok = 0;
3180 fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3181 m = 0;
3182 mask = 0;
3183 for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3184 if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3185 m++;
3186 for (k = 0; k < INPUT_MANY; k++)
3187 inputset[k].standard_offset = i;
3189 mask = easycap_standard[i].mask;
3193 if (1 != m) {
3194 SAM("ERROR: "
3195 "inputset->standard_offset unpopulated, %i=m\n", m);
3196 return -ENOENT;
3199 peasycap_format = &easycap_format[0];
3200 m = 0;
3201 for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3202 struct v4l2_pix_format *pix =
3203 &peasycap_format->v4l2_format.fmt.pix;
3204 if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3205 pix->field == V4L2_FIELD_NONE &&
3206 pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3207 pix->width == 640 && pix->height == 480) {
3208 m++;
3209 for (k = 0; k < INPUT_MANY; k++)
3210 inputset[k].format_offset = i;
3211 break;
3213 peasycap_format++;
3215 if (1 != m) {
3216 SAM("ERROR: inputset[]->format_offset unpopulated\n");
3217 return -ENOENT;
3220 m = 0;
3221 for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
3222 value = easycap_control[i].default_value;
3223 if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
3224 m++;
3225 for (k = 0; k < INPUT_MANY; k++)
3226 inputset[k].brightness = value;
3227 } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
3228 m++;
3229 for (k = 0; k < INPUT_MANY; k++)
3230 inputset[k].contrast = value;
3231 } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
3232 m++;
3233 for (k = 0; k < INPUT_MANY; k++)
3234 inputset[k].saturation = value;
3235 } else if (V4L2_CID_HUE == easycap_control[i].id) {
3236 m++;
3237 for (k = 0; k < INPUT_MANY; k++)
3238 inputset[k].hue = value;
3242 if (4 != m) {
3243 SAM("ERROR: inputset[]->brightness underpopulated\n");
3244 return -ENOENT;
3246 for (k = 0; k < INPUT_MANY; k++)
3247 inputset[k].input = k;
3248 JOM(4, "populated inputset[]\n");
3249 JOM(4, "finished initialization\n");
3250 } else {
3251 /*---------------------------------------------------------------------------*/
3253 * FIXME
3255 * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3256 * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3258 /*---------------------------------------------------------------------------*/
3259 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3260 if (usbdev == easycapdc60_dongle[ndong].peasycap->
3261 pusb_device) {
3262 peasycap = easycapdc60_dongle[ndong].peasycap;
3263 JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3264 bInterfaceNumber, ndong);
3265 break;
3268 if (DONGLE_MANY <= ndong) {
3269 SAY("ERROR: peasycap is unknown when probing interface %i\n",
3270 bInterfaceNumber);
3271 return -ENODEV;
3273 if (!peasycap) {
3274 SAY("ERROR: peasycap is NULL when probing interface %i\n",
3275 bInterfaceNumber);
3276 return -ENODEV;
3278 /*---------------------------------------------------------------------------*/
3280 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
3281 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
3282 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
3283 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
3285 /*---------------------------------------------------------------------------*/
3286 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
3287 pv4l2_device = usb_get_intfdata(intf);
3288 if (!pv4l2_device) {
3289 SAY("ERROR: pv4l2_device is NULL\n");
3290 return -ENODEV;
3292 peasycap = (struct easycap *)
3293 container_of(pv4l2_device, struct easycap, v4l2_device);
3296 /*---------------------------------------------------------------------------*/
3297 if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3298 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3299 if (-1 == peasycap->video_interface) {
3300 peasycap->video_interface = bInterfaceNumber;
3301 JOM(4, "setting peasycap->video_interface=%i\n",
3302 peasycap->video_interface);
3303 } else {
3304 if (peasycap->video_interface != bInterfaceNumber) {
3305 SAM("ERROR: attempting to reset "
3306 "peasycap->video_interface\n");
3307 SAM("...... continuing with "
3308 "%i=peasycap->video_interface\n",
3309 peasycap->video_interface);
3312 } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3313 (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
3314 if (-1 == peasycap->audio_interface) {
3315 peasycap->audio_interface = bInterfaceNumber;
3316 JOM(4, "setting peasycap->audio_interface=%i\n",
3317 peasycap->audio_interface);
3318 } else {
3319 if (peasycap->audio_interface != bInterfaceNumber) {
3320 SAM("ERROR: attempting to reset "
3321 "peasycap->audio_interface\n");
3322 SAM("...... continuing with "
3323 "%i=peasycap->audio_interface\n",
3324 peasycap->audio_interface);
3328 /*---------------------------------------------------------------------------*/
3330 * INVESTIGATE ALL ALTSETTINGS.
3331 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3333 /*---------------------------------------------------------------------------*/
3334 isokalt = 0;
3336 for (i = 0; i < intf->num_altsetting; i++) {
3337 alt = usb_altnum_to_altsetting(intf, i);
3338 if (!alt) {
3339 SAM("ERROR: alt is NULL\n");
3340 return -EFAULT;
3342 interface = &alt->desc;
3343 if (!interface) {
3344 SAM("ERROR: intf_descriptor is NULL\n");
3345 return -EFAULT;
3348 JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n",
3349 bInterfaceNumber, i, interface->bDescriptorType);
3350 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n",
3351 bInterfaceNumber, i, interface->bInterfaceNumber);
3352 JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n",
3353 bInterfaceNumber, i, interface->bAlternateSetting);
3354 JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n",
3355 bInterfaceNumber, i, interface->bNumEndpoints);
3356 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n",
3357 bInterfaceNumber, i, interface->bInterfaceClass);
3358 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n",
3359 bInterfaceNumber, i, interface->bInterfaceSubClass);
3360 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n",
3361 bInterfaceNumber, i, interface->bInterfaceProtocol);
3362 JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n",
3363 bInterfaceNumber, i, interface->iInterface);
3365 ISOCwMaxPacketSize = -1;
3366 BULKwMaxPacketSize = -1;
3367 INTwMaxPacketSize = -1;
3368 CTRLwMaxPacketSize = -1;
3369 ISOCbEndpointAddress = 0;
3370 INTbEndpointAddress = 0;
3372 if (0 == interface->bNumEndpoints)
3373 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3374 bInterfaceNumber, i);
3375 /*---------------------------------------------------------------------------*/
3376 for (j = 0; j < interface->bNumEndpoints; j++) {
3377 ep = &alt->endpoint[j].desc;
3378 if (!ep) {
3379 SAM("ERROR: ep is NULL.\n");
3380 SAM("...... skipping\n");
3381 continue;
3383 wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
3384 bEndpointAddress = ep->bEndpointAddress;
3386 JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n",
3387 bInterfaceNumber, i, j,
3388 ep->bEndpointAddress);
3389 JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n",
3390 bInterfaceNumber, i, j,
3391 ep->bmAttributes);
3392 JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n",
3393 bInterfaceNumber, i, j,
3394 ep->wMaxPacketSize);
3395 JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
3396 bInterfaceNumber, i, j,
3397 ep->bInterval);
3399 if (ep->bEndpointAddress & USB_DIR_IN) {
3400 JOM(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",
3401 bInterfaceNumber, i, j);
3402 isin = 1;
3403 } else {
3404 JOM(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",
3405 bInterfaceNumber, i, j);
3406 SAM("ERROR: OUT endpoint unexpected\n");
3407 SAM("...... continuing\n");
3408 isin = 0;
3410 if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
3411 USB_ENDPOINT_XFER_ISOC) {
3412 JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",
3413 bInterfaceNumber, i, j);
3414 if (isin) {
3415 switch (bInterfaceClass) {
3416 case USB_CLASS_VIDEO:
3417 case USB_CLASS_VENDOR_SPEC: {
3418 if (!peasycap) {
3419 SAM("MISTAKE: "
3420 "peasycap is NULL\n");
3421 return -EFAULT;
3423 if (ep->wMaxPacketSize) {
3424 if (8 > isokalt) {
3425 okalt[isokalt] = i;
3426 JOM(4,
3427 "%i=okalt[%i]\n",
3428 okalt[isokalt],
3429 isokalt);
3430 okepn[isokalt] =
3431 ep->
3432 bEndpointAddress &
3433 0x0F;
3434 JOM(4,
3435 "%i=okepn[%i]\n",
3436 okepn[isokalt],
3437 isokalt);
3438 okmps[isokalt] =
3439 le16_to_cpu(ep->
3440 wMaxPacketSize);
3441 JOM(4,
3442 "%i=okmps[%i]\n",
3443 okmps[isokalt],
3444 isokalt);
3445 isokalt++;
3447 } else {
3448 if (-1 == peasycap->
3449 video_altsetting_off) {
3450 peasycap->
3451 video_altsetting_off =
3453 JOM(4, "%i=video_"
3454 "altsetting_off "
3455 "<====\n",
3456 peasycap->
3457 video_altsetting_off);
3458 } else {
3459 SAM("ERROR: peasycap"
3460 "->video_altsetting_"
3461 "off already set\n");
3462 SAM("...... "
3463 "continuing with "
3464 "%i=peasycap->video_"
3465 "altsetting_off\n",
3466 peasycap->
3467 video_altsetting_off);
3470 break;
3472 case USB_CLASS_AUDIO: {
3473 if (bInterfaceSubClass !=
3474 USB_SUBCLASS_AUDIOSTREAMING)
3475 break;
3476 if (!peasycap) {
3477 SAM("MISTAKE: "
3478 "peasycap is NULL\n");
3479 return -EFAULT;
3481 if (ep->wMaxPacketSize) {
3482 if (8 > isokalt) {
3483 okalt[isokalt] = i ;
3484 JOM(4,
3485 "%i=okalt[%i]\n",
3486 okalt[isokalt],
3487 isokalt);
3488 okepn[isokalt] =
3489 ep->
3490 bEndpointAddress &
3491 0x0F;
3492 JOM(4,
3493 "%i=okepn[%i]\n",
3494 okepn[isokalt],
3495 isokalt);
3496 okmps[isokalt] =
3497 le16_to_cpu(ep->
3498 wMaxPacketSize);
3499 JOM(4,
3500 "%i=okmps[%i]\n",
3501 okmps[isokalt],
3502 isokalt);
3503 isokalt++;
3505 } else {
3506 if (-1 == peasycap->
3507 audio_altsetting_off) {
3508 peasycap->
3509 audio_altsetting_off =
3511 JOM(4, "%i=audio_"
3512 "altsetting_off "
3513 "<====\n",
3514 peasycap->
3515 audio_altsetting_off);
3516 } else {
3517 SAM("ERROR: peasycap"
3518 "->audio_altsetting_"
3519 "off already set\n");
3520 SAM("...... "
3521 "continuing with "
3522 "%i=peasycap->"
3523 "audio_altsetting_"
3524 "off\n",
3525 peasycap->
3526 audio_altsetting_off);
3529 break;
3531 default:
3532 break;
3535 } else if ((ep->bmAttributes &
3536 USB_ENDPOINT_XFERTYPE_MASK) ==
3537 USB_ENDPOINT_XFER_BULK) {
3538 JOM(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",
3539 bInterfaceNumber, i, j);
3540 } else if ((ep->bmAttributes &
3541 USB_ENDPOINT_XFERTYPE_MASK) ==
3542 USB_ENDPOINT_XFER_INT) {
3543 JOM(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",
3544 bInterfaceNumber, i, j);
3545 } else {
3546 JOM(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",
3547 bInterfaceNumber, i, j);
3549 if (0 == ep->wMaxPacketSize) {
3550 JOM(4, "intf[%i]alt[%i]end[%i] "
3551 "has zero packet size\n",
3552 bInterfaceNumber, i, j);
3556 /*---------------------------------------------------------------------------*/
3558 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
3560 /*---------------------------------------------------------------------------*/
3561 JOM(4, "initialization begins for interface %i\n",
3562 interface->bInterfaceNumber);
3563 switch (bInterfaceNumber) {
3564 /*---------------------------------------------------------------------------*/
3566 * INTERFACE 0 IS THE VIDEO INTERFACE
3568 /*---------------------------------------------------------------------------*/
3569 case 0: {
3570 if (!peasycap) {
3571 SAM("MISTAKE: peasycap is NULL\n");
3572 return -EFAULT;
3574 if (!isokalt) {
3575 SAM("ERROR: no viable video_altsetting_on\n");
3576 return -ENOENT;
3577 } else {
3578 peasycap->video_altsetting_on = okalt[isokalt - 1];
3579 JOM(4, "%i=video_altsetting_on <====\n",
3580 peasycap->video_altsetting_on);
3582 /*---------------------------------------------------------------------------*/
3584 * DECIDE THE VIDEO STREAMING PARAMETERS
3586 /*---------------------------------------------------------------------------*/
3587 peasycap->video_endpointnumber = okepn[isokalt - 1];
3588 JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
3589 maxpacketsize = okmps[isokalt - 1];
3591 peasycap->video_isoc_maxframesize =
3592 min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
3593 if (0 >= peasycap->video_isoc_maxframesize) {
3594 SAM("ERROR: bad video_isoc_maxframesize\n");
3595 SAM(" possibly because port is USB 1.1\n");
3596 return -ENOENT;
3598 JOM(4, "%i=video_isoc_maxframesize\n",
3599 peasycap->video_isoc_maxframesize);
3601 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3602 JOM(4, "%i=video_isoc_framesperdesc\n",
3603 peasycap->video_isoc_framesperdesc);
3604 if (0 >= peasycap->video_isoc_framesperdesc) {
3605 SAM("ERROR: bad video_isoc_framesperdesc\n");
3606 return -ENOENT;
3608 peasycap->video_isoc_buffer_size =
3609 peasycap->video_isoc_maxframesize *
3610 peasycap->video_isoc_framesperdesc;
3611 JOM(4, "%i=video_isoc_buffer_size\n",
3612 peasycap->video_isoc_buffer_size);
3613 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
3614 peasycap->video_isoc_buffer_size) {
3615 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
3616 return -EFAULT;
3618 /*---------------------------------------------------------------------------*/
3619 if (-1 == peasycap->video_interface) {
3620 SAM("MISTAKE: video_interface is unset\n");
3621 return -EFAULT;
3623 if (-1 == peasycap->video_altsetting_on) {
3624 SAM("MISTAKE: video_altsetting_on is unset\n");
3625 return -EFAULT;
3627 if (-1 == peasycap->video_altsetting_off) {
3628 SAM("MISTAKE: video_interface_off is unset\n");
3629 return -EFAULT;
3631 if (-1 == peasycap->video_endpointnumber) {
3632 SAM("MISTAKE: video_endpointnumber is unset\n");
3633 return -EFAULT;
3635 if (-1 == peasycap->video_isoc_maxframesize) {
3636 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
3637 return -EFAULT;
3639 if (-1 == peasycap->video_isoc_buffer_size) {
3640 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
3641 return -EFAULT;
3643 /*---------------------------------------------------------------------------*/
3645 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3647 /*---------------------------------------------------------------------------*/
3648 INIT_LIST_HEAD(&(peasycap->urb_video_head));
3649 peasycap->purb_video_head = &(peasycap->urb_video_head);
3650 /*---------------------------------------------------------------------------*/
3651 JOM(4, "allocating %i frame buffers of size %li\n",
3652 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
3653 JOM(4, ".... each scattered over %li pages\n",
3654 FRAME_BUFFER_SIZE/PAGE_SIZE);
3656 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
3657 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
3658 if (peasycap->frame_buffer[k][m].pgo)
3659 SAM("attempting to reallocate frame "
3660 " buffers\n");
3661 else {
3662 pbuf = (void *)__get_free_page(GFP_KERNEL);
3663 if (!pbuf) {
3664 SAM("ERROR: Could not allocate frame "
3665 "buffer %i page %i\n", k, m);
3666 return -ENOMEM;
3667 } else
3668 peasycap->allocation_video_page += 1;
3669 peasycap->frame_buffer[k][m].pgo = pbuf;
3671 peasycap->frame_buffer[k][m].pto =
3672 peasycap->frame_buffer[k][m].pgo;
3676 peasycap->frame_fill = 0;
3677 peasycap->frame_read = 0;
3678 JOM(4, "allocation of frame buffers done: %i pages\n", k *
3680 /*---------------------------------------------------------------------------*/
3681 JOM(4, "allocating %i field buffers of size %li\n",
3682 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
3683 JOM(4, ".... each scattered over %li pages\n",
3684 FIELD_BUFFER_SIZE/PAGE_SIZE);
3686 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
3687 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
3688 if (peasycap->field_buffer[k][m].pgo) {
3689 SAM("ERROR: attempting to reallocate "
3690 "field buffers\n");
3691 } else {
3692 pbuf = (void *) __get_free_page(GFP_KERNEL);
3693 if (!pbuf) {
3694 SAM("ERROR: Could not allocate field"
3695 " buffer %i page %i\n", k, m);
3696 return -ENOMEM;
3698 else
3699 peasycap->allocation_video_page += 1;
3700 peasycap->field_buffer[k][m].pgo = pbuf;
3702 peasycap->field_buffer[k][m].pto =
3703 peasycap->field_buffer[k][m].pgo;
3705 peasycap->field_buffer[k][0].kount = 0x0200;
3707 peasycap->field_fill = 0;
3708 peasycap->field_page = 0;
3709 peasycap->field_read = 0;
3710 JOM(4, "allocation of field buffers done: %i pages\n", k *
3712 /*---------------------------------------------------------------------------*/
3713 JOM(4, "allocating %i isoc video buffers of size %i\n",
3714 VIDEO_ISOC_BUFFER_MANY,
3715 peasycap->video_isoc_buffer_size);
3716 JOM(4, ".... each occupying contiguous memory pages\n");
3718 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3719 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3720 VIDEO_ISOC_ORDER);
3721 if (!pbuf) {
3722 SAM("ERROR: Could not allocate isoc video buffer "
3723 "%i\n", k);
3724 return -ENOMEM;
3725 } else
3726 peasycap->allocation_video_page +=
3727 BIT(VIDEO_ISOC_ORDER);
3729 peasycap->video_isoc_buffer[k].pgo = pbuf;
3730 peasycap->video_isoc_buffer[k].pto =
3731 pbuf + peasycap->video_isoc_buffer_size;
3732 peasycap->video_isoc_buffer[k].kount = k;
3734 JOM(4, "allocation of isoc video buffers done: %i pages\n",
3735 k * (0x01 << VIDEO_ISOC_ORDER));
3736 /*---------------------------------------------------------------------------*/
3738 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3740 /*---------------------------------------------------------------------------*/
3741 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3742 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
3743 peasycap->video_isoc_framesperdesc);
3744 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
3745 peasycap->video_isoc_maxframesize);
3746 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
3747 peasycap->video_isoc_buffer_size);
3749 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3750 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
3751 GFP_KERNEL);
3752 if (!purb) {
3753 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3754 "%i\n", k);
3755 return -ENOMEM;
3756 } else
3757 peasycap->allocation_video_urb += 1;
3758 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3759 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3760 if (!pdata_urb) {
3761 SAM("ERROR: Could not allocate struct data_urb.\n");
3762 return -ENOMEM;
3763 } else
3764 peasycap->allocation_video_struct +=
3765 sizeof(struct data_urb);
3767 pdata_urb->purb = purb;
3768 pdata_urb->isbuf = k;
3769 pdata_urb->length = 0;
3770 list_add_tail(&(pdata_urb->list_head),
3771 peasycap->purb_video_head);
3772 /*---------------------------------------------------------------------------*/
3774 * ... AND INITIALIZE THEM
3776 /*---------------------------------------------------------------------------*/
3777 if (!k) {
3778 JOM(4, "initializing video urbs thus:\n");
3779 JOM(4, " purb->interval = 1;\n");
3780 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3781 JOM(4, " purb->pipe = usb_rcvisocpipe"
3782 "(peasycap->pusb_device,%i);\n",
3783 peasycap->video_endpointnumber);
3784 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3785 JOM(4, " purb->transfer_buffer = peasycap->"
3786 "video_isoc_buffer[.].pgo;\n");
3787 JOM(4, " purb->transfer_buffer_length = %i;\n",
3788 peasycap->video_isoc_buffer_size);
3789 JOM(4, " purb->complete = easycap_complete;\n");
3790 JOM(4, " purb->context = peasycap;\n");
3791 JOM(4, " purb->start_frame = 0;\n");
3792 JOM(4, " purb->number_of_packets = %i;\n",
3793 peasycap->video_isoc_framesperdesc);
3794 JOM(4, " for (j = 0; j < %i; j++)\n",
3795 peasycap->video_isoc_framesperdesc);
3796 JOM(4, " {\n");
3797 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3798 peasycap->video_isoc_maxframesize);
3799 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3800 peasycap->video_isoc_maxframesize);
3801 JOM(4, " }\n");
3804 purb->interval = 1;
3805 purb->dev = peasycap->pusb_device;
3806 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3807 peasycap->video_endpointnumber);
3808 purb->transfer_flags = URB_ISO_ASAP;
3809 purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
3810 purb->transfer_buffer_length =
3811 peasycap->video_isoc_buffer_size;
3812 purb->complete = easycap_complete;
3813 purb->context = peasycap;
3814 purb->start_frame = 0;
3815 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3816 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
3817 purb->iso_frame_desc[j].offset = j *
3818 peasycap->video_isoc_maxframesize;
3819 purb->iso_frame_desc[j].length =
3820 peasycap->video_isoc_maxframesize;
3823 JOM(4, "allocation of %i struct urb done.\n", k);
3824 /*--------------------------------------------------------------------------*/
3826 * SAVE POINTER peasycap IN THIS INTERFACE.
3828 /*--------------------------------------------------------------------------*/
3829 usb_set_intfdata(intf, peasycap);
3830 /*---------------------------------------------------------------------------*/
3832 * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
3833 * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
3834 * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
3835 * BEWARE.
3837 /*---------------------------------------------------------------------------*/
3838 peasycap->ntsc = easycap_ntsc;
3839 JOM(8, "defaulting initially to %s\n",
3840 easycap_ntsc ? "NTSC" : "PAL");
3841 rc = reset(peasycap);
3842 if (rc) {
3843 SAM("ERROR: reset() rc = %i\n", rc);
3844 return -EFAULT;
3846 /*--------------------------------------------------------------------------*/
3848 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3850 /*--------------------------------------------------------------------------*/
3851 if (0 != (v4l2_device_register(&(intf->dev),
3852 &(peasycap->v4l2_device)))) {
3853 SAM("v4l2_device_register() failed\n");
3854 return -ENODEV;
3855 } else {
3856 JOM(4, "registered device instance: %s\n",
3857 &(peasycap->v4l2_device.name[0]));
3859 /*---------------------------------------------------------------------------*/
3861 * FIXME
3864 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
3866 /*---------------------------------------------------------------------------*/
3867 peasycap->video_device.v4l2_dev = NULL;
3868 /*---------------------------------------------------------------------------*/
3871 strcpy(&peasycap->video_device.name[0], "easycapdc60");
3872 peasycap->video_device.fops = &v4l2_fops;
3873 peasycap->video_device.minor = -1;
3874 peasycap->video_device.release = (void *)(&videodev_release);
3876 video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3878 if (0 != (video_register_device(&(peasycap->video_device),
3879 VFL_TYPE_GRABBER, -1))) {
3880 err("Not able to register with videodev");
3881 videodev_release(&(peasycap->video_device));
3882 return -ENODEV;
3883 } else {
3884 (peasycap->registered_video)++;
3885 SAM("registered with videodev: %i=minor\n",
3886 peasycap->video_device.minor);
3887 peasycap->minor = peasycap->video_device.minor;
3889 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3891 break;
3893 /*--------------------------------------------------------------------------*/
3895 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3896 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3898 /*--------------------------------------------------------------------------*/
3899 case 1: {
3900 if (!peasycap) {
3901 SAM("MISTAKE: peasycap is NULL\n");
3902 return -EFAULT;
3904 /*--------------------------------------------------------------------------*/
3906 * SAVE POINTER peasycap IN INTERFACE 1
3908 /*--------------------------------------------------------------------------*/
3909 usb_set_intfdata(intf, peasycap);
3910 JOM(4, "no initialization required for interface %i\n",
3911 interface->bInterfaceNumber);
3912 break;
3914 /*--------------------------------------------------------------------------*/
3915 case 2: {
3916 if (!peasycap) {
3917 SAM("MISTAKE: peasycap is NULL\n");
3918 return -EFAULT;
3920 if (!isokalt) {
3921 SAM("ERROR: no viable audio_altsetting_on\n");
3922 return -ENOENT;
3923 } else {
3924 peasycap->audio_altsetting_on = okalt[isokalt - 1];
3925 JOM(4, "%i=audio_altsetting_on <====\n",
3926 peasycap->audio_altsetting_on);
3929 peasycap->audio_endpointnumber = okepn[isokalt - 1];
3930 JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3932 peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
3933 JOM(4, "%i=audio_isoc_maxframesize\n",
3934 peasycap->audio_isoc_maxframesize);
3935 if (0 >= peasycap->audio_isoc_maxframesize) {
3936 SAM("ERROR: bad audio_isoc_maxframesize\n");
3937 return -ENOENT;
3939 if (9 == peasycap->audio_isoc_maxframesize) {
3940 peasycap->ilk |= 0x02;
3941 SAM("audio hardware is microphone\n");
3942 peasycap->microphone = true;
3943 peasycap->audio_pages_per_fragment =
3944 PAGES_PER_AUDIO_FRAGMENT;
3945 } else if (256 == peasycap->audio_isoc_maxframesize) {
3946 peasycap->ilk &= ~0x02;
3947 SAM("audio hardware is AC'97\n");
3948 peasycap->microphone = false;
3949 peasycap->audio_pages_per_fragment =
3950 PAGES_PER_AUDIO_FRAGMENT;
3951 } else {
3952 SAM("hardware is unidentified:\n");
3953 SAM("%i=audio_isoc_maxframesize\n",
3954 peasycap->audio_isoc_maxframesize);
3955 return -ENOENT;
3958 peasycap->audio_bytes_per_fragment =
3959 peasycap->audio_pages_per_fragment * PAGE_SIZE;
3960 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3961 peasycap->audio_pages_per_fragment);
3963 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
3964 JOM(4, "%6i=audio_pages_per_fragment\n",
3965 peasycap->audio_pages_per_fragment);
3966 JOM(4, "%6i=audio_bytes_per_fragment\n",
3967 peasycap->audio_bytes_per_fragment);
3968 JOM(4, "%6i=audio_buffer_page_many\n",
3969 peasycap->audio_buffer_page_many);
3971 peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
3973 JOM(4, "%i=audio_isoc_framesperdesc\n",
3974 peasycap->audio_isoc_framesperdesc);
3975 if (0 >= peasycap->audio_isoc_framesperdesc) {
3976 SAM("ERROR: bad audio_isoc_framesperdesc\n");
3977 return -ENOENT;
3980 peasycap->audio_isoc_buffer_size =
3981 peasycap->audio_isoc_maxframesize *
3982 peasycap->audio_isoc_framesperdesc;
3983 JOM(4, "%i=audio_isoc_buffer_size\n",
3984 peasycap->audio_isoc_buffer_size);
3985 if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
3986 SAM("MISTAKE: audio_isoc_buffer_size bigger "
3987 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
3988 AUDIO_ISOC_BUFFER_SIZE);
3989 return -EFAULT;
3991 if (-1 == peasycap->audio_interface) {
3992 SAM("MISTAKE: audio_interface is unset\n");
3993 return -EFAULT;
3995 if (-1 == peasycap->audio_altsetting_on) {
3996 SAM("MISTAKE: audio_altsetting_on is unset\n");
3997 return -EFAULT;
3999 if (-1 == peasycap->audio_altsetting_off) {
4000 SAM("MISTAKE: audio_interface_off is unset\n");
4001 return -EFAULT;
4003 if (-1 == peasycap->audio_endpointnumber) {
4004 SAM("MISTAKE: audio_endpointnumber is unset\n");
4005 return -EFAULT;
4007 if (-1 == peasycap->audio_isoc_maxframesize) {
4008 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
4009 return -EFAULT;
4011 if (-1 == peasycap->audio_isoc_buffer_size) {
4012 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
4013 return -EFAULT;
4015 /*---------------------------------------------------------------------------*/
4017 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
4019 /*---------------------------------------------------------------------------*/
4020 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
4021 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
4023 #ifdef CONFIG_EASYCAP_OSS
4024 JOM(4, "allocating an audio buffer\n");
4025 JOM(4, ".... scattered over %i pages\n",
4026 peasycap->audio_buffer_page_many);
4028 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
4029 if (peasycap->audio_buffer[k].pgo) {
4030 SAM("ERROR: attempting to reallocate audio buffers\n");
4031 } else {
4032 pbuf = (void *) __get_free_page(GFP_KERNEL);
4033 if (!pbuf) {
4034 SAM("ERROR: Could not allocate audio "
4035 "buffer page %i\n", k);
4036 return -ENOMEM;
4037 } else
4038 peasycap->allocation_audio_page += 1;
4040 peasycap->audio_buffer[k].pgo = pbuf;
4042 peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
4045 peasycap->audio_fill = 0;
4046 peasycap->audio_read = 0;
4047 JOM(4, "allocation of audio buffer done: %i pages\n", k);
4048 #endif /* CONFIG_EASYCAP_OSS */
4049 /*---------------------------------------------------------------------------*/
4050 JOM(4, "allocating %i isoc audio buffers of size %i\n",
4051 AUDIO_ISOC_BUFFER_MANY,
4052 peasycap->audio_isoc_buffer_size);
4053 JOM(4, ".... each occupying contiguous memory pages\n");
4055 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4056 pbuf = (void *)__get_free_pages(GFP_KERNEL,
4057 AUDIO_ISOC_ORDER);
4058 if (!pbuf) {
4059 SAM("ERROR: Could not allocate isoc audio buffer "
4060 "%i\n", k);
4061 return -ENOMEM;
4062 } else
4063 peasycap->allocation_audio_page +=
4064 BIT(AUDIO_ISOC_ORDER);
4066 peasycap->audio_isoc_buffer[k].pgo = pbuf;
4067 peasycap->audio_isoc_buffer[k].pto = pbuf +
4068 peasycap->audio_isoc_buffer_size;
4069 peasycap->audio_isoc_buffer[k].kount = k;
4071 JOM(4, "allocation of isoc audio buffers done.\n");
4072 /*---------------------------------------------------------------------------*/
4074 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4076 /*---------------------------------------------------------------------------*/
4077 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
4078 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
4079 peasycap->audio_isoc_framesperdesc);
4080 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
4081 peasycap->audio_isoc_maxframesize);
4082 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
4083 peasycap->audio_isoc_buffer_size);
4085 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4086 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
4087 GFP_KERNEL);
4088 if (!purb) {
4089 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4090 "%i\n", k);
4091 return -ENOMEM;
4093 peasycap->allocation_audio_urb += 1 ;
4094 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4095 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
4096 if (!pdata_urb) {
4097 SAM("ERROR: Could not allocate struct data_urb.\n");
4098 return -ENOMEM;
4100 peasycap->allocation_audio_struct +=
4101 sizeof(struct data_urb);
4103 pdata_urb->purb = purb;
4104 pdata_urb->isbuf = k;
4105 pdata_urb->length = 0;
4106 list_add_tail(&(pdata_urb->list_head),
4107 peasycap->purb_audio_head);
4108 /*---------------------------------------------------------------------------*/
4110 * ... AND INITIALIZE THEM
4112 /*---------------------------------------------------------------------------*/
4113 if (!k) {
4114 JOM(4, "initializing audio urbs thus:\n");
4115 JOM(4, " purb->interval = 1;\n");
4116 JOM(4, " purb->dev = peasycap->pusb_device;\n");
4117 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
4118 "pusb_device,%i);\n",
4119 peasycap->audio_endpointnumber);
4120 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4121 JOM(4, " purb->transfer_buffer = "
4122 "peasycap->audio_isoc_buffer[.].pgo;\n");
4123 JOM(4, " purb->transfer_buffer_length = %i;\n",
4124 peasycap->audio_isoc_buffer_size);
4125 #ifdef CONFIG_EASYCAP_OSS
4126 JOM(4, " purb->complete = easyoss_complete;\n");
4127 #else /* CONFIG_EASYCAP_OSS */
4128 JOM(4, " purb->complete = easycap_alsa_complete;\n");
4129 #endif /* CONFIG_EASYCAP_OSS */
4130 JOM(4, " purb->context = peasycap;\n");
4131 JOM(4, " purb->start_frame = 0;\n");
4132 JOM(4, " purb->number_of_packets = %i;\n",
4133 peasycap->audio_isoc_framesperdesc);
4134 JOM(4, " for (j = 0; j < %i; j++)\n",
4135 peasycap->audio_isoc_framesperdesc);
4136 JOM(4, " {\n");
4137 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
4138 peasycap->audio_isoc_maxframesize);
4139 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
4140 peasycap->audio_isoc_maxframesize);
4141 JOM(4, " }\n");
4144 purb->interval = 1;
4145 purb->dev = peasycap->pusb_device;
4146 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
4147 peasycap->audio_endpointnumber);
4148 purb->transfer_flags = URB_ISO_ASAP;
4149 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
4150 purb->transfer_buffer_length =
4151 peasycap->audio_isoc_buffer_size;
4152 #ifdef CONFIG_EASYCAP_OSS
4153 purb->complete = easyoss_complete;
4154 #else /* CONFIG_EASYCAP_OSS */
4155 purb->complete = easycap_alsa_complete;
4156 #endif /* CONFIG_EASYCAP_OSS */
4157 purb->context = peasycap;
4158 purb->start_frame = 0;
4159 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
4160 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
4161 purb->iso_frame_desc[j].offset = j *
4162 peasycap->audio_isoc_maxframesize;
4163 purb->iso_frame_desc[j].length =
4164 peasycap->audio_isoc_maxframesize;
4167 JOM(4, "allocation of %i struct urb done.\n", k);
4168 /*---------------------------------------------------------------------------*/
4170 * SAVE POINTER peasycap IN THIS INTERFACE.
4172 /*---------------------------------------------------------------------------*/
4173 usb_set_intfdata(intf, peasycap);
4174 /*---------------------------------------------------------------------------*/
4176 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4178 /*---------------------------------------------------------------------------*/
4179 #ifndef CONFIG_EASYCAP_OSS
4180 JOM(4, "initializing ALSA card\n");
4182 rc = easycap_alsa_probe(peasycap);
4183 if (rc) {
4184 err("easycap_alsa_probe() rc = %i\n", rc);
4185 return -ENODEV;
4186 } else {
4187 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4188 peasycap->kref.refcount.counter);
4189 kref_get(&peasycap->kref);
4190 peasycap->registered_audio++;
4193 #else /* CONFIG_EASYCAP_OSS */
4194 rc = usb_register_dev(intf, &easyoss_class);
4195 if (rc) {
4196 SAY("ERROR: usb_register_dev() failed\n");
4197 usb_set_intfdata(intf, NULL);
4198 return -ENODEV;
4199 } else {
4200 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4201 peasycap->kref.refcount.counter);
4202 kref_get(&peasycap->kref);
4203 peasycap->registered_audio++;
4205 SAM("easyoss attached to minor #%d\n", intf->minor);
4206 #endif /* CONFIG_EASYCAP_OSS */
4208 break;
4210 /*---------------------------------------------------------------------------*/
4212 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4214 /*---------------------------------------------------------------------------*/
4215 default:
4216 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4217 return -EINVAL;
4219 SAM("ends successfully for interface %i\n", bInterfaceNumber);
4220 return 0;
4222 /*****************************************************************************/
4223 /*---------------------------------------------------------------------------*/
4225 * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4226 * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
4228 * THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
4230 /*---------------------------------------------------------------------------*/
4231 static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4233 struct usb_host_interface *pusb_host_interface;
4234 struct usb_interface_descriptor *pusb_interface_descriptor;
4235 u8 bInterfaceNumber;
4236 struct easycap *peasycap;
4238 struct list_head *plist_head;
4239 struct data_urb *pdata_urb;
4240 int minor, m, kd;
4241 struct v4l2_device *pv4l2_device;
4243 JOT(4, "\n");
4245 pusb_host_interface = pusb_interface->cur_altsetting;
4246 if (!pusb_host_interface) {
4247 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4248 return;
4250 pusb_interface_descriptor = &(pusb_host_interface->desc);
4251 if (!pusb_interface_descriptor) {
4252 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4253 return;
4255 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4256 minor = pusb_interface->minor;
4257 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4259 if (1 == bInterfaceNumber)
4260 return;
4262 peasycap = usb_get_intfdata(pusb_interface);
4263 if (!peasycap) {
4264 SAY("ERROR: peasycap is NULL\n");
4265 return;
4267 /*---------------------------------------------------------------------------*/
4269 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
4270 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
4271 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
4272 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
4274 /*---------------------------------------------------------------------------*/
4275 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4276 pv4l2_device = usb_get_intfdata(pusb_interface);
4277 if (!pv4l2_device) {
4278 SAY("ERROR: pv4l2_device is NULL\n");
4279 return;
4281 peasycap = (struct easycap *)
4282 container_of(pv4l2_device, struct easycap, v4l2_device);
4284 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4285 /*---------------------------------------------------------------------------*/
4286 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4287 SAY("ERROR: bad peasycap: %p\n", peasycap);
4288 return;
4290 /*---------------------------------------------------------------------------*/
4292 * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
4294 /*---------------------------------------------------------------------------*/
4295 peasycap->video_eof = 1;
4296 peasycap->audio_eof = 1;
4297 wake_up_interruptible(&(peasycap->wq_video));
4298 wake_up_interruptible(&(peasycap->wq_audio));
4299 /*---------------------------------------------------------------------------*/
4300 switch (bInterfaceNumber) {
4301 case 0: {
4302 if (peasycap->purb_video_head) {
4303 JOM(4, "killing video urbs\n");
4304 m = 0;
4305 list_for_each(plist_head, peasycap->purb_video_head) {
4306 pdata_urb = list_entry(plist_head,
4307 struct data_urb, list_head);
4308 if (pdata_urb) {
4309 if (pdata_urb->purb) {
4310 usb_kill_urb(pdata_urb->purb);
4311 m++;
4315 JOM(4, "%i video urbs killed\n", m);
4317 break;
4319 /*---------------------------------------------------------------------------*/
4320 case 2: {
4321 if (peasycap->purb_audio_head) {
4322 JOM(4, "killing audio urbs\n");
4323 m = 0;
4324 list_for_each(plist_head, peasycap->purb_audio_head) {
4325 pdata_urb = list_entry(plist_head,
4326 struct data_urb, list_head);
4327 if (pdata_urb) {
4328 if (pdata_urb->purb) {
4329 usb_kill_urb(pdata_urb->purb);
4330 m++;
4334 JOM(4, "%i audio urbs killed\n", m);
4336 break;
4338 default:
4339 break;
4341 /*--------------------------------------------------------------------------*/
4343 * DEREGISTER
4345 * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4346 * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4347 * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
4349 /*--------------------------------------------------------------------------*/
4350 kd = isdongle(peasycap);
4351 switch (bInterfaceNumber) {
4352 case 0: {
4353 if (0 <= kd && DONGLE_MANY > kd) {
4354 wake_up_interruptible(&peasycap->wq_video);
4355 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4356 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4357 mutex_video)) {
4358 SAY("ERROR: "
4359 "cannot lock dongle[%i].mutex_video\n", kd);
4360 return;
4362 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4363 } else {
4364 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4366 /*---------------------------------------------------------------------------*/
4367 if (!peasycap->v4l2_device.name[0]) {
4368 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4369 if (0 <= kd && DONGLE_MANY > kd)
4370 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4371 return;
4373 v4l2_device_disconnect(&peasycap->v4l2_device);
4374 JOM(4, "v4l2_device_disconnect() OK\n");
4375 v4l2_device_unregister(&peasycap->v4l2_device);
4376 JOM(4, "v4l2_device_unregister() OK\n");
4378 video_unregister_device(&peasycap->video_device);
4379 JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4380 bInterfaceNumber, minor);
4381 peasycap->registered_video--;
4382 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4384 if (0 <= kd && DONGLE_MANY > kd) {
4385 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4386 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4388 break;
4390 case 2: {
4391 if (0 <= kd && DONGLE_MANY > kd) {
4392 wake_up_interruptible(&peasycap->wq_audio);
4393 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4394 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4395 mutex_audio)) {
4396 SAY("ERROR: "
4397 "cannot lock dongle[%i].mutex_audio\n", kd);
4398 return;
4400 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4401 } else
4402 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4403 #ifndef CONFIG_EASYCAP_OSS
4404 if (0 != snd_card_free(peasycap->psnd_card)) {
4405 SAY("ERROR: snd_card_free() failed\n");
4406 } else {
4407 peasycap->psnd_card = NULL;
4408 (peasycap->registered_audio)--;
4410 #else /* CONFIG_EASYCAP_OSS */
4411 usb_deregister_dev(pusb_interface, &easyoss_class);
4412 peasycap->registered_audio--;
4413 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
4414 SAM("easyoss detached from minor #%d\n", minor);
4415 #endif /* CONFIG_EASYCAP_OSS */
4416 if (0 <= kd && DONGLE_MANY > kd) {
4417 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4418 JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4420 break;
4422 default:
4423 break;
4425 /*---------------------------------------------------------------------------*/
4427 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4428 * (ALSO WHEN ALSA HAS BEEN IN USE)
4430 /*---------------------------------------------------------------------------*/
4431 if (!peasycap->kref.refcount.counter) {
4432 SAM("ERROR: peasycap->kref.refcount.counter is zero "
4433 "so cannot call kref_put()\n");
4434 SAM("ending unsuccessfully: may cause memory leak\n");
4435 return;
4437 if (0 <= kd && DONGLE_MANY > kd) {
4438 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4439 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4440 SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4441 SAM("ending unsuccessfully: may cause memory leak\n");
4442 return;
4444 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4445 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4446 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4447 SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4448 mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4449 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4450 SAM("ending unsuccessfully: may cause memory leak\n");
4451 return;
4453 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4455 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4456 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4457 kref_put(&peasycap->kref, easycap_delete);
4458 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4459 if (0 <= kd && DONGLE_MANY > kd) {
4460 mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4461 JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4462 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4463 JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4465 /*---------------------------------------------------------------------------*/
4466 JOM(4, "ends\n");
4467 return;
4469 /*****************************************************************************/
4471 /*---------------------------------------------------------------------------*/
4473 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4475 /*---------------------------------------------------------------------------*/
4476 static struct usb_device_id easycap_usb_device_id_table[] = {
4477 {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4481 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4482 struct usb_driver easycap_usb_driver = {
4483 .name = "easycap",
4484 .id_table = easycap_usb_device_id_table,
4485 .probe = easycap_usb_probe,
4486 .disconnect = easycap_usb_disconnect,
4489 static int __init easycap_module_init(void)
4491 int k, rc;
4493 printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4495 JOT(4, "begins. %i=debug %i=bars %i=gain\n",
4496 easycap_debug, easycap_bars, easycap_gain);
4498 mutex_init(&mutex_dongle);
4499 for (k = 0; k < DONGLE_MANY; k++) {
4500 easycapdc60_dongle[k].peasycap = NULL;
4501 mutex_init(&easycapdc60_dongle[k].mutex_video);
4502 mutex_init(&easycapdc60_dongle[k].mutex_audio);
4504 rc = usb_register(&easycap_usb_driver);
4505 if (rc)
4506 printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4508 return rc;
4510 /*****************************************************************************/
4511 static void __exit easycap_module_exit(void)
4513 usb_deregister(&easycap_usb_driver);
4515 /*****************************************************************************/
4517 module_init(easycap_module_init);
4518 module_exit(easycap_module_exit);
4520 /*****************************************************************************/