x86/PCI: use host bridge _CRS info on ASUS M2V-MX SE
[linux-btrfs-devel.git] / drivers / staging / easycap / easycap_main.c
blobbea281624c41a3889ac50954d12b9ff611a127b5
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 (!peasycap->pusb_device) {
162 SAM("ERROR: peasycap->pusb_device is NULL\n");
163 return -EFAULT;
164 } else {
165 JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
167 file->private_data = peasycap;
168 rc = wakeup_device(peasycap->pusb_device);
169 if (0 == rc)
170 JOM(8, "wakeup_device() OK\n");
171 else {
172 SAM("ERROR: wakeup_device() rc = %i\n", rc);
173 if (-ENODEV == rc)
174 SAM("ERROR: wakeup_device() returned -ENODEV\n");
175 else
176 SAM("ERROR: wakeup_device() rc = %i\n", rc);
177 return rc;
179 peasycap->input = 0;
180 rc = reset(peasycap);
181 if (rc) {
182 SAM("ERROR: reset() rc = %i\n", rc);
183 return -EFAULT;
185 return 0;
188 /*****************************************************************************/
189 /*---------------------------------------------------------------------------*/
191 * RESET THE HARDWARE TO ITS REFERENCE STATE.
193 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
194 * A BAD VIDEO FRAME SIZE.
196 /*---------------------------------------------------------------------------*/
197 static int reset(struct easycap *peasycap)
199 struct easycap_standard const *peasycap_standard;
200 int fmtidx, input, rate;
201 bool ntsc, other;
202 int rc;
204 if (!peasycap) {
205 SAY("ERROR: peasycap is NULL\n");
206 return -EFAULT;
208 input = peasycap->input;
210 /*---------------------------------------------------------------------------*/
212 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
213 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
214 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
215 * A SWITCH BETWEEN PAL AND NTSC.
217 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
218 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
220 /*---------------------------------------------------------------------------*/
221 other = false;
222 JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
224 rate = ready_saa(peasycap->pusb_device);
225 if (rate < 0) {
226 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
227 ntsc = !peasycap->ntsc;
228 JOM(8, "... trying %s ..\n", ntsc ? "NTSC" : "PAL");
229 rc = setup_stk(peasycap->pusb_device, ntsc);
230 if (rc) {
231 SAM("ERROR: setup_stk() rc = %i\n", rc);
232 return -EFAULT;
234 rc = setup_saa(peasycap->pusb_device, ntsc);
235 if (rc) {
236 SAM("ERROR: setup_saa() rc = %i\n", rc);
237 return -EFAULT;
240 rate = ready_saa(peasycap->pusb_device);
241 if (rate < 0) {
242 JOM(8, "not ready to capture after %i ms\n", PATIENCE);
243 JOM(8, "... saa register 0x1F has 0x%02X\n",
244 read_saa(peasycap->pusb_device, 0x1F));
245 ntsc = peasycap->ntsc;
246 } else {
247 JOM(8, "... success at second try: %i=rate\n", rate);
248 ntsc = (0 < (rate/2)) ? true : false ;
249 other = true;
251 } else {
252 JOM(8, "... success at first try: %i=rate\n", rate);
253 ntsc = (0 < rate/2) ? true : false ;
255 JOM(8, "ntsc=%d\n", ntsc);
256 /*---------------------------------------------------------------------------*/
258 rc = setup_stk(peasycap->pusb_device, ntsc);
259 if (rc) {
260 SAM("ERROR: setup_stk() rc = %i\n", rc);
261 return -EFAULT;
263 rc = setup_saa(peasycap->pusb_device, ntsc);
264 if (rc) {
265 SAM("ERROR: setup_saa() rc = %i\n", rc);
266 return -EFAULT;
269 memset(peasycap->merit, 0, sizeof(peasycap->merit));
271 peasycap->video_eof = 0;
272 peasycap->audio_eof = 0;
273 do_gettimeofday(&peasycap->timeval7);
274 /*---------------------------------------------------------------------------*/
276 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
278 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
280 /*---------------------------------------------------------------------------*/
281 peasycap->input = -8192;
282 peasycap->standard_offset = -8192;
283 fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
284 if (other) {
285 peasycap_standard = &easycap_standard[0];
286 while (0xFFFF != peasycap_standard->mask) {
287 if (fmtidx == peasycap_standard->v4l2_standard.index) {
288 peasycap->inputset[input].standard_offset =
289 peasycap_standard - easycap_standard;
290 break;
292 peasycap_standard++;
294 if (0xFFFF == peasycap_standard->mask) {
295 SAM("ERROR: standard not found\n");
296 return -EINVAL;
298 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
299 peasycap->inputset[input].standard_offset, input);
301 peasycap->format_offset = -8192;
302 peasycap->brightness = -8192;
303 peasycap->contrast = -8192;
304 peasycap->saturation = -8192;
305 peasycap->hue = -8192;
307 rc = newinput(peasycap, input);
309 if (rc) {
310 SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
311 return -EFAULT;
313 JOM(4, "restored input, standard and format\n");
315 JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
317 if (0 > peasycap->input) {
318 SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
319 return -ENOENT;
321 if (0 > peasycap->standard_offset) {
322 SAM("MISTAKE: %i=peasycap->standard_offset\n",
323 peasycap->standard_offset);
324 return -ENOENT;
326 if (0 > peasycap->format_offset) {
327 SAM("MISTAKE: %i=peasycap->format_offset\n",
328 peasycap->format_offset);
329 return -ENOENT;
331 if (0 > peasycap->brightness) {
332 SAM("MISTAKE: %i=peasycap->brightness\n",
333 peasycap->brightness);
334 return -ENOENT;
336 if (0 > peasycap->contrast) {
337 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
338 return -ENOENT;
340 if (0 > peasycap->saturation) {
341 SAM("MISTAKE: %i=peasycap->saturation\n",
342 peasycap->saturation);
343 return -ENOENT;
345 if (0 > peasycap->hue) {
346 SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
347 return -ENOENT;
349 return 0;
351 /*****************************************************************************/
352 /*---------------------------------------------------------------------------*/
354 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
355 * OTHERWISE:
356 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
357 * _read AND _fill POINTERS.
358 * SELECT THE NEW INPUT.
359 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
360 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
361 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
363 * NOTE:
364 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
365 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
367 /*---------------------------------------------------------------------------*/
369 newinput(struct easycap *peasycap, int input)
371 int rc, k, m, mood, off;
372 int inputnow, video_idlenow, audio_idlenow;
373 bool resubmit;
375 if (!peasycap) {
376 SAY("ERROR: peasycap is NULL\n");
377 return -EFAULT;
379 JOM(8, "%i=input sought\n", input);
381 if (0 > input && INPUT_MANY <= input)
382 return -ENOENT;
383 inputnow = peasycap->input;
384 if (input == inputnow)
385 return 0;
386 /*---------------------------------------------------------------------------*/
388 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
389 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
390 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
391 * ROUTINE.
393 /*---------------------------------------------------------------------------*/
394 video_idlenow = peasycap->video_idle;
395 audio_idlenow = peasycap->audio_idle;
397 peasycap->video_idle = 1;
398 peasycap->audio_idle = 1;
399 if (peasycap->video_isoc_streaming) {
400 resubmit = true;
401 kill_video_urbs(peasycap);
402 } else {
403 resubmit = false;
405 /*---------------------------------------------------------------------------*/
406 if (!peasycap->pusb_device) {
407 SAM("ERROR: peasycap->pusb_device is NULL\n");
408 return -ENODEV;
410 rc = usb_set_interface(peasycap->pusb_device,
411 peasycap->video_interface,
412 peasycap->video_altsetting_off);
413 if (rc) {
414 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
415 return -EFAULT;
417 rc = stop_100(peasycap->pusb_device);
418 if (rc) {
419 SAM("ERROR: stop_100() rc = %i\n", rc);
420 return -EFAULT;
422 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
423 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
424 memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
426 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
427 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
428 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
430 peasycap->field_page = 0;
431 peasycap->field_read = 0;
432 peasycap->field_fill = 0;
434 peasycap->frame_read = 0;
435 peasycap->frame_fill = 0;
436 for (k = 0; k < peasycap->input; k++) {
437 (peasycap->frame_fill)++;
438 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
439 peasycap->frame_fill = 0;
441 peasycap->input = input;
442 select_input(peasycap->pusb_device, peasycap->input, 9);
443 /*---------------------------------------------------------------------------*/
444 if (input == peasycap->inputset[input].input) {
445 off = peasycap->inputset[input].standard_offset;
446 if (off != peasycap->standard_offset) {
447 rc = adjust_standard(peasycap,
448 easycap_standard[off].v4l2_standard.id);
449 if (rc) {
450 SAM("ERROR: adjust_standard() rc = %i\n", rc);
451 return -EFAULT;
453 JOM(8, "%i=peasycap->standard_offset\n",
454 peasycap->standard_offset);
455 } else {
456 JOM(8, "%i=peasycap->standard_offset unchanged\n",
457 peasycap->standard_offset);
459 off = peasycap->inputset[input].format_offset;
460 if (off != peasycap->format_offset) {
461 struct v4l2_pix_format *pix =
462 &easycap_format[off].v4l2_format.fmt.pix;
463 rc = adjust_format(peasycap,
464 pix->width, pix->height,
465 pix->pixelformat, pix->field, false);
466 if (0 > rc) {
467 SAM("ERROR: adjust_format() rc = %i\n", rc);
468 return -EFAULT;
470 JOM(8, "%i=peasycap->format_offset\n",
471 peasycap->format_offset);
472 } else {
473 JOM(8, "%i=peasycap->format_offset unchanged\n",
474 peasycap->format_offset);
476 mood = peasycap->inputset[input].brightness;
477 if (mood != peasycap->brightness) {
478 rc = adjust_brightness(peasycap, mood);
479 if (rc) {
480 SAM("ERROR: adjust_brightness rc = %i\n", rc);
481 return -EFAULT;
483 JOM(8, "%i=peasycap->brightness\n",
484 peasycap->brightness);
486 mood = peasycap->inputset[input].contrast;
487 if (mood != peasycap->contrast) {
488 rc = adjust_contrast(peasycap, mood);
489 if (rc) {
490 SAM("ERROR: adjust_contrast rc = %i\n", rc);
491 return -EFAULT;
493 JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
495 mood = peasycap->inputset[input].saturation;
496 if (mood != peasycap->saturation) {
497 rc = adjust_saturation(peasycap, mood);
498 if (rc) {
499 SAM("ERROR: adjust_saturation rc = %i\n", rc);
500 return -EFAULT;
502 JOM(8, "%i=peasycap->saturation\n",
503 peasycap->saturation);
505 mood = peasycap->inputset[input].hue;
506 if (mood != peasycap->hue) {
507 rc = adjust_hue(peasycap, mood);
508 if (rc) {
509 SAM("ERROR: adjust_hue rc = %i\n", rc);
510 return -EFAULT;
512 JOM(8, "%i=peasycap->hue\n", peasycap->hue);
514 } else {
515 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
516 return -ENOENT;
518 /*---------------------------------------------------------------------------*/
519 if (!peasycap->pusb_device) {
520 SAM("ERROR: peasycap->pusb_device is NULL\n");
521 return -ENODEV;
523 rc = usb_set_interface(peasycap->pusb_device,
524 peasycap->video_interface,
525 peasycap->video_altsetting_on);
526 if (rc) {
527 SAM("ERROR: usb_set_interface() rc = %i\n", rc);
528 return -EFAULT;
530 rc = start_100(peasycap->pusb_device);
531 if (rc) {
532 SAM("ERROR: start_100() rc = %i\n", rc);
533 return -EFAULT;
535 if (resubmit)
536 submit_video_urbs(peasycap);
538 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
539 peasycap->video_idle = video_idlenow;
540 peasycap->audio_idle = audio_idlenow;
541 peasycap->video_junk = 0;
543 return 0;
545 /*****************************************************************************/
546 int submit_video_urbs(struct easycap *peasycap)
548 struct data_urb *pdata_urb;
549 struct urb *purb;
550 struct list_head *plist_head;
551 int j, isbad, nospc, m, rc;
552 int isbuf;
554 if (!peasycap) {
555 SAY("ERROR: peasycap is NULL\n");
556 return -EFAULT;
559 if (!peasycap->purb_video_head) {
560 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
561 return -EFAULT;
563 if (!peasycap->pusb_device) {
564 SAY("ERROR: peasycap->pusb_device is NULL\n");
565 return -ENODEV;
567 if (!peasycap->video_isoc_streaming) {
568 JOM(4, "submission of all video urbs\n");
569 isbad = 0; nospc = 0; m = 0;
570 list_for_each(plist_head, (peasycap->purb_video_head)) {
571 pdata_urb = list_entry(plist_head,
572 struct data_urb, list_head);
573 if (pdata_urb && pdata_urb->purb) {
574 purb = pdata_urb->purb;
575 isbuf = pdata_urb->isbuf;
576 purb->interval = 1;
577 purb->dev = peasycap->pusb_device;
578 purb->pipe =
579 usb_rcvisocpipe(peasycap->pusb_device,
580 peasycap->video_endpointnumber);
581 purb->transfer_flags = URB_ISO_ASAP;
582 purb->transfer_buffer =
583 peasycap->video_isoc_buffer[isbuf].pgo;
584 purb->transfer_buffer_length =
585 peasycap->video_isoc_buffer_size;
586 purb->complete = easycap_complete;
587 purb->context = peasycap;
588 purb->start_frame = 0;
589 purb->number_of_packets =
590 peasycap->video_isoc_framesperdesc;
592 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
593 purb->iso_frame_desc[j]. offset =
594 j * peasycap->video_isoc_maxframesize;
595 purb->iso_frame_desc[j]. length =
596 peasycap->video_isoc_maxframesize;
599 rc = usb_submit_urb(purb, GFP_KERNEL);
600 if (rc) {
601 isbad++;
602 SAM("ERROR: usb_submit_urb() failed "
603 "for urb with rc:-%s\n",
604 strerror(rc));
605 if (rc == -ENOSPC)
606 nospc++;
607 } else {
608 m++;
610 } else {
611 isbad++;
614 if (nospc) {
615 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
616 SAM("..... possibly inadequate USB bandwidth\n");
617 peasycap->video_eof = 1;
620 if (isbad) {
621 JOM(4, "attempting cleanup instead of submitting\n");
622 list_for_each(plist_head, (peasycap->purb_video_head)) {
623 pdata_urb = list_entry(plist_head,
624 struct data_urb, list_head);
625 if (pdata_urb) {
626 purb = pdata_urb->purb;
627 if (purb)
628 usb_kill_urb(purb);
631 peasycap->video_isoc_streaming = 0;
632 } else {
633 peasycap->video_isoc_streaming = 1;
634 JOM(4, "submitted %i video urbs\n", m);
636 } else {
637 JOM(4, "already streaming video urbs\n");
639 return 0;
641 /*****************************************************************************/
642 int kill_video_urbs(struct easycap *peasycap)
644 int m;
645 struct list_head *plist_head;
646 struct data_urb *pdata_urb;
648 if (!peasycap) {
649 SAY("ERROR: peasycap is NULL\n");
650 return -EFAULT;
652 if (!peasycap->video_isoc_streaming) {
653 JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
654 peasycap->video_isoc_streaming);
655 return 0;
657 if (!peasycap->purb_video_head) {
658 SAM("ERROR: peasycap->purb_video_head is NULL\n");
659 return -EFAULT;
662 peasycap->video_isoc_streaming = 0;
663 JOM(4, "killing video urbs\n");
664 m = 0;
665 list_for_each(plist_head, (peasycap->purb_video_head)) {
666 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
667 if (pdata_urb && pdata_urb->purb) {
668 usb_kill_urb(pdata_urb->purb);
669 m++;
672 JOM(4, "%i video urbs killed\n", m);
674 return 0;
676 /****************************************************************************/
677 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
678 /*--------------------------------------------------------------------------*/
679 static int easycap_open_noinode(struct file *file)
681 return easycap_open(NULL, file);
684 static int videodev_release(struct video_device *pvideo_device)
686 struct easycap *peasycap;
688 peasycap = video_get_drvdata(pvideo_device);
689 if (!peasycap) {
690 SAY("ERROR: peasycap is NULL\n");
691 SAY("ending unsuccessfully\n");
692 return -EFAULT;
694 if (0 != kill_video_urbs(peasycap)) {
695 SAM("ERROR: kill_video_urbs() failed\n");
696 return -EFAULT;
698 JOM(4, "ending successfully\n");
699 return 0;
701 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
702 /*****************************************************************************/
703 /*--------------------------------------------------------------------------*/
705 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
706 * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
708 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
709 * peasycap->pusb_device IS NO LONGER VALID.
711 /*---------------------------------------------------------------------------*/
712 static void easycap_delete(struct kref *pkref)
714 struct easycap *peasycap;
715 struct data_urb *pdata_urb;
716 struct list_head *plist_head, *plist_next;
717 int k, m, gone, kd;
718 int allocation_video_urb;
719 int allocation_video_page;
720 int allocation_video_struct;
721 int allocation_audio_urb;
722 int allocation_audio_page;
723 int allocation_audio_struct;
724 int registered_video, registered_audio;
726 peasycap = container_of(pkref, struct easycap, kref);
727 if (!peasycap) {
728 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
729 return;
731 kd = isdongle(peasycap);
732 /*---------------------------------------------------------------------------*/
734 * FREE VIDEO.
736 /*---------------------------------------------------------------------------*/
737 if (peasycap->purb_video_head) {
738 JOM(4, "freeing video urbs\n");
739 m = 0;
740 list_for_each(plist_head, (peasycap->purb_video_head)) {
741 pdata_urb = list_entry(plist_head,
742 struct data_urb, list_head);
743 if (!pdata_urb) {
744 JOM(4, "ERROR: pdata_urb is NULL\n");
745 } else {
746 if (pdata_urb->purb) {
747 usb_free_urb(pdata_urb->purb);
748 pdata_urb->purb = NULL;
749 peasycap->allocation_video_urb -= 1;
750 m++;
755 JOM(4, "%i video urbs freed\n", m);
756 /*---------------------------------------------------------------------------*/
757 JOM(4, "freeing video data_urb structures.\n");
758 m = 0;
759 list_for_each_safe(plist_head, plist_next,
760 peasycap->purb_video_head) {
761 pdata_urb = list_entry(plist_head,
762 struct data_urb, list_head);
763 if (pdata_urb) {
764 peasycap->allocation_video_struct -=
765 sizeof(struct data_urb);
766 kfree(pdata_urb);
767 pdata_urb = NULL;
768 m++;
771 JOM(4, "%i video data_urb structures freed\n", m);
772 JOM(4, "setting peasycap->purb_video_head=NULL\n");
773 peasycap->purb_video_head = NULL;
775 /*---------------------------------------------------------------------------*/
776 JOM(4, "freeing video isoc buffers.\n");
777 m = 0;
778 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
779 if (peasycap->video_isoc_buffer[k].pgo) {
780 free_pages((unsigned long)
781 peasycap->video_isoc_buffer[k].pgo,
782 VIDEO_ISOC_ORDER);
783 peasycap->video_isoc_buffer[k].pgo = NULL;
784 peasycap->allocation_video_page -=
785 BIT(VIDEO_ISOC_ORDER);
786 m++;
789 JOM(4, "isoc video buffers freed: %i pages\n",
790 m * (0x01 << VIDEO_ISOC_ORDER));
791 /*---------------------------------------------------------------------------*/
792 JOM(4, "freeing video field buffers.\n");
793 gone = 0;
794 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
795 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
796 if (peasycap->field_buffer[k][m].pgo) {
797 free_page((unsigned long)
798 peasycap->field_buffer[k][m].pgo);
799 peasycap->field_buffer[k][m].pgo = NULL;
800 peasycap->allocation_video_page -= 1;
801 gone++;
805 JOM(4, "video field buffers freed: %i pages\n", gone);
806 /*---------------------------------------------------------------------------*/
807 JOM(4, "freeing video frame buffers.\n");
808 gone = 0;
809 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
810 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
811 if (peasycap->frame_buffer[k][m].pgo) {
812 free_page((unsigned long)
813 peasycap->frame_buffer[k][m].pgo);
814 peasycap->frame_buffer[k][m].pgo = NULL;
815 peasycap->allocation_video_page -= 1;
816 gone++;
820 JOM(4, "video frame buffers freed: %i pages\n", gone);
821 /*---------------------------------------------------------------------------*/
823 * FREE AUDIO.
825 /*---------------------------------------------------------------------------*/
826 if (peasycap->purb_audio_head) {
827 JOM(4, "freeing audio urbs\n");
828 m = 0;
829 list_for_each(plist_head, (peasycap->purb_audio_head)) {
830 pdata_urb = list_entry(plist_head,
831 struct data_urb, list_head);
832 if (!pdata_urb)
833 JOM(4, "ERROR: pdata_urb is NULL\n");
834 else {
835 if (pdata_urb->purb) {
836 usb_free_urb(pdata_urb->purb);
837 pdata_urb->purb = NULL;
838 peasycap->allocation_audio_urb -= 1;
839 m++;
843 JOM(4, "%i audio urbs freed\n", m);
844 /*---------------------------------------------------------------------------*/
845 JOM(4, "freeing audio data_urb structures.\n");
846 m = 0;
847 list_for_each_safe(plist_head, plist_next,
848 peasycap->purb_audio_head) {
849 pdata_urb = list_entry(plist_head,
850 struct data_urb, list_head);
851 if (pdata_urb) {
852 peasycap->allocation_audio_struct -=
853 sizeof(struct data_urb);
854 kfree(pdata_urb);
855 pdata_urb = NULL;
856 m++;
859 JOM(4, "%i audio data_urb structures freed\n", m);
860 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
861 peasycap->purb_audio_head = NULL;
863 /*---------------------------------------------------------------------------*/
864 JOM(4, "freeing audio isoc buffers.\n");
865 m = 0;
866 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
867 if (peasycap->audio_isoc_buffer[k].pgo) {
868 free_pages((unsigned long)
869 (peasycap->audio_isoc_buffer[k].pgo),
870 AUDIO_ISOC_ORDER);
871 peasycap->audio_isoc_buffer[k].pgo = NULL;
872 peasycap->allocation_audio_page -=
873 BIT(AUDIO_ISOC_ORDER);
874 m++;
877 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
878 m * (0x01 << AUDIO_ISOC_ORDER));
879 /*---------------------------------------------------------------------------*/
880 JOM(4, "freeing easycap structure.\n");
881 allocation_video_urb = peasycap->allocation_video_urb;
882 allocation_video_page = peasycap->allocation_video_page;
883 allocation_video_struct = peasycap->allocation_video_struct;
884 registered_video = peasycap->registered_video;
885 allocation_audio_urb = peasycap->allocation_audio_urb;
886 allocation_audio_page = peasycap->allocation_audio_page;
887 allocation_audio_struct = peasycap->allocation_audio_struct;
888 registered_audio = peasycap->registered_audio;
890 if (0 <= kd && DONGLE_MANY > kd) {
891 if (mutex_lock_interruptible(&mutex_dongle)) {
892 SAY("ERROR: cannot down mutex_dongle\n");
893 } else {
894 JOM(4, "locked mutex_dongle\n");
895 easycapdc60_dongle[kd].peasycap = NULL;
896 mutex_unlock(&mutex_dongle);
897 JOM(4, "unlocked mutex_dongle\n");
898 JOT(4, " null-->dongle[%i].peasycap\n", kd);
899 allocation_video_struct -= sizeof(struct easycap);
901 } else {
902 SAY("ERROR: cannot purge dongle[].peasycap");
905 kfree(peasycap);
907 /*---------------------------------------------------------------------------*/
908 SAY("%8i=video urbs after all deletions\n", allocation_video_urb);
909 SAY("%8i=video pages after all deletions\n", allocation_video_page);
910 SAY("%8i=video structs after all deletions\n", allocation_video_struct);
911 SAY("%8i=video devices after all deletions\n", registered_video);
912 SAY("%8i=audio urbs after all deletions\n", allocation_audio_urb);
913 SAY("%8i=audio pages after all deletions\n", allocation_audio_page);
914 SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
915 SAY("%8i=audio devices after all deletions\n", registered_audio);
917 JOT(4, "ending.\n");
918 return;
920 /*****************************************************************************/
921 static unsigned int easycap_poll(struct file *file, poll_table *wait)
923 struct easycap *peasycap;
924 int rc, kd;
926 JOT(8, "\n");
928 if (NULL == ((poll_table *)wait))
929 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
930 if (!file) {
931 SAY("ERROR: file pointer is NULL\n");
932 return -ERESTARTSYS;
934 peasycap = file->private_data;
935 if (!peasycap) {
936 SAY("ERROR: peasycap is NULL\n");
937 return -EFAULT;
939 if (!peasycap->pusb_device) {
940 SAY("ERROR: peasycap->pusb_device is NULL\n");
941 return -EFAULT;
943 /*---------------------------------------------------------------------------*/
944 kd = isdongle(peasycap);
945 if (0 <= kd && DONGLE_MANY > kd) {
946 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
947 SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
948 return -ERESTARTSYS;
950 JOM(4, "locked dongle[%i].mutex_video\n", kd);
952 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
953 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
954 * IF NECESSARY, BAIL OUT.
956 if (kd != isdongle(peasycap))
957 return -ERESTARTSYS;
958 if (!file) {
959 SAY("ERROR: file is NULL\n");
960 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
961 return -ERESTARTSYS;
963 peasycap = file->private_data;
964 if (!peasycap) {
965 SAY("ERROR: peasycap is NULL\n");
966 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
967 return -ERESTARTSYS;
969 if (!peasycap->pusb_device) {
970 SAM("ERROR: peasycap->pusb_device is NULL\n");
971 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
972 return -ERESTARTSYS;
974 } else
976 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
977 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
978 * HAVE FAILED. BAIL OUT.
980 return -ERESTARTSYS;
981 /*---------------------------------------------------------------------------*/
982 rc = easycap_dqbuf(peasycap, 0);
983 peasycap->polled = 1;
984 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
985 if (0 == rc)
986 return POLLIN | POLLRDNORM;
987 else
988 return POLLERR;
990 /*****************************************************************************/
991 /*---------------------------------------------------------------------------*/
993 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
995 /*---------------------------------------------------------------------------*/
996 int easycap_dqbuf(struct easycap *peasycap, int mode)
998 int input, ifield, miss, rc;
1001 if (!peasycap) {
1002 SAY("ERROR: peasycap is NULL\n");
1003 return -EFAULT;
1005 if (!peasycap->pusb_device) {
1006 SAY("ERROR: peasycap->pusb_device is NULL\n");
1007 return -EFAULT;
1009 ifield = 0;
1010 JOM(8, "%i=ifield\n", ifield);
1011 /*---------------------------------------------------------------------------*/
1013 * CHECK FOR LOST INPUT SIGNAL.
1015 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1016 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1017 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1018 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
1020 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
1021 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
1022 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1023 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1025 /*---------------------------------------------------------------------------*/
1026 input = peasycap->input;
1027 if (0 <= input && INPUT_MANY > input) {
1028 rc = read_saa(peasycap->pusb_device, 0x1F);
1029 if (0 <= rc) {
1030 if (rc & 0x40)
1031 peasycap->lost[input] += 1;
1032 else
1033 peasycap->lost[input] -= 2;
1035 if (0 > peasycap->lost[input])
1036 peasycap->lost[input] = 0;
1037 else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1038 peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1041 /*---------------------------------------------------------------------------*/
1043 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
1045 /*---------------------------------------------------------------------------*/
1046 miss = 0;
1047 while ((peasycap->field_read == peasycap->field_fill) ||
1048 (0 != (0xFF00 & peasycap->field_buffer
1049 [peasycap->field_read][0].kount)) ||
1050 (ifield != (0x00FF & peasycap->field_buffer
1051 [peasycap->field_read][0].kount))) {
1052 if (mode)
1053 return -EAGAIN;
1055 JOM(8, "first wait on wq_video, %i=field_read %i=field_fill\n",
1056 peasycap->field_read, peasycap->field_fill);
1058 if (0 != (wait_event_interruptible(peasycap->wq_video,
1059 (peasycap->video_idle || peasycap->video_eof ||
1060 ((peasycap->field_read != peasycap->field_fill) &&
1061 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1062 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1063 SAM("aborted by signal\n");
1064 return -EIO;
1066 if (peasycap->video_idle) {
1067 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1068 peasycap->video_idle);
1069 return -EAGAIN;
1071 if (peasycap->video_eof) {
1072 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1073 #if defined(PERSEVERE)
1074 if (1 == peasycap->status) {
1075 JOM(8, "persevering ...\n");
1076 peasycap->video_eof = 0;
1077 peasycap->audio_eof = 0;
1078 if (0 != reset(peasycap)) {
1079 JOM(8, " ... failed returning -EIO\n");
1080 peasycap->video_eof = 1;
1081 peasycap->audio_eof = 1;
1082 kill_video_urbs(peasycap);
1083 return -EIO;
1085 peasycap->status = 0;
1086 JOM(8, " ... OK returning -EAGAIN\n");
1087 return -EAGAIN;
1089 #endif /*PERSEVERE*/
1090 peasycap->video_eof = 1;
1091 peasycap->audio_eof = 1;
1092 kill_video_urbs(peasycap);
1093 JOM(8, "returning -EIO\n");
1094 return -EIO;
1096 miss++;
1098 JOM(8, "first awakening on wq_video after %i waits\n", miss);
1100 rc = field2frame(peasycap);
1101 if (rc)
1102 SAM("ERROR: field2frame() rc = %i\n", rc);
1103 /*---------------------------------------------------------------------------*/
1105 * WAIT FOR THE OTHER FIELD
1107 /*---------------------------------------------------------------------------*/
1108 if (ifield)
1109 ifield = 0;
1110 else
1111 ifield = 1;
1112 miss = 0;
1113 while ((peasycap->field_read == peasycap->field_fill) ||
1114 (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
1115 (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
1116 if (mode)
1117 return -EAGAIN;
1119 JOM(8, "second wait on wq_video %i=field_read %i=field_fill\n",
1120 peasycap->field_read, peasycap->field_fill);
1121 if (0 != (wait_event_interruptible(peasycap->wq_video,
1122 (peasycap->video_idle || peasycap->video_eof ||
1123 ((peasycap->field_read != peasycap->field_fill) &&
1124 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
1125 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
1126 SAM("aborted by signal\n");
1127 return -EIO;
1129 if (peasycap->video_idle) {
1130 JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
1131 peasycap->video_idle);
1132 return -EAGAIN;
1134 if (peasycap->video_eof) {
1135 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1136 #if defined(PERSEVERE)
1137 if (1 == peasycap->status) {
1138 JOM(8, "persevering ...\n");
1139 peasycap->video_eof = 0;
1140 peasycap->audio_eof = 0;
1141 if (0 != reset(peasycap)) {
1142 JOM(8, " ... failed returning -EIO\n");
1143 peasycap->video_eof = 1;
1144 peasycap->audio_eof = 1;
1145 kill_video_urbs(peasycap);
1146 return -EIO;
1148 peasycap->status = 0;
1149 JOM(8, " ... OK ... returning -EAGAIN\n");
1150 return -EAGAIN;
1152 #endif /*PERSEVERE*/
1153 peasycap->video_eof = 1;
1154 peasycap->audio_eof = 1;
1155 kill_video_urbs(peasycap);
1156 JOM(8, "returning -EIO\n");
1157 return -EIO;
1159 miss++;
1161 JOM(8, "second awakening on wq_video after %i waits\n", miss);
1163 rc = field2frame(peasycap);
1164 if (rc)
1165 SAM("ERROR: field2frame() rc = %i\n", rc);
1166 /*---------------------------------------------------------------------------*/
1168 * WASTE THIS FRAME
1170 /*---------------------------------------------------------------------------*/
1171 if (peasycap->skip) {
1172 peasycap->skipped++;
1173 if (peasycap->skip != peasycap->skipped)
1174 return peasycap->skip - peasycap->skipped;
1175 else
1176 peasycap->skipped = 0;
1178 /*---------------------------------------------------------------------------*/
1179 peasycap->frame_read = peasycap->frame_fill;
1180 peasycap->queued[peasycap->frame_read] = 0;
1181 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
1183 peasycap->frame_fill++;
1184 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1185 peasycap->frame_fill = 0;
1187 if (0x01 & easycap_standard[peasycap->standard_offset].mask)
1188 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1189 V4L2_FIELD_TOP;
1190 else
1191 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1192 V4L2_FIELD_BOTTOM;
1195 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
1196 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
1198 return 0;
1200 /*****************************************************************************/
1201 /*---------------------------------------------------------------------------*/
1203 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1204 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1206 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1207 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1209 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1210 * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1212 /*---------------------------------------------------------------------------*/
1214 field2frame(struct easycap *peasycap)
1216 struct timeval timeval;
1217 long long int above, below;
1218 u32 remainder;
1219 struct signed_div_result sdr;
1221 void *pex, *pad;
1222 int kex, kad, mex, mad, rex, rad, rad2;
1223 int c2, c3, w2, w3, cz, wz;
1224 int rc, bytesperpixel, multiplier;
1225 int much, more, over, rump, caches, input;
1226 u8 mask, margin;
1227 bool odd, isuy, decimatepixel, offerfields, badinput;
1229 if (!peasycap) {
1230 SAY("ERROR: peasycap is NULL\n");
1231 return -EFAULT;
1234 badinput = false;
1235 input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1237 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1238 "frame buffer %i\n",
1239 peasycap->field_buffer[peasycap->field_read][0].kount,
1240 peasycap->field_buffer[peasycap->field_read][0].input,
1241 peasycap->field_read, peasycap->frame_fill);
1242 JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1243 if (peasycap->offerfields)
1244 JOM(8, "===== offerfields\n");
1246 /*---------------------------------------------------------------------------*/
1248 * REJECT OR CLEAN BAD FIELDS
1250 /*---------------------------------------------------------------------------*/
1251 if (peasycap->field_read == peasycap->field_fill) {
1252 SAM("ERROR: on entry, still filling field buffer %i\n",
1253 peasycap->field_read);
1254 return 0;
1256 #ifdef EASYCAP_TESTCARD
1257 easycap_testcard(peasycap, peasycap->field_read);
1258 #else
1259 if (0 <= input && INPUT_MANY > input) {
1260 if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1261 easycap_testcard(peasycap, peasycap->field_read);
1263 #endif /*EASYCAP_TESTCARD*/
1264 /*---------------------------------------------------------------------------*/
1266 offerfields = peasycap->offerfields;
1267 bytesperpixel = peasycap->bytesperpixel;
1268 decimatepixel = peasycap->decimatepixel;
1270 if ((2 != bytesperpixel) &&
1271 (3 != bytesperpixel) &&
1272 (4 != bytesperpixel)) {
1273 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1274 return -EFAULT;
1276 if (decimatepixel)
1277 multiplier = 2;
1278 else
1279 multiplier = 1;
1281 w2 = 2 * multiplier * (peasycap->width);
1282 w3 = bytesperpixel * multiplier * (peasycap->width);
1283 wz = multiplier * (peasycap->height) *
1284 multiplier * (peasycap->width);
1286 kex = peasycap->field_read; mex = 0;
1287 kad = peasycap->frame_fill; mad = 0;
1289 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1290 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1291 odd = !!(peasycap->field_buffer[kex][0].kount);
1293 if (odd && (!decimatepixel)) {
1294 JOM(8, "initial skipping %4i bytes p.%4i\n",
1295 w3/multiplier, mad);
1296 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1298 isuy = true;
1299 mask = 0; rump = 0; caches = 0;
1301 cz = 0;
1302 while (cz < wz) {
1304 * PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1305 * READ w2 BYTES FROM FIELD BUFFER,
1306 * WRITE w3 BYTES TO FRAME BUFFER
1308 if (!decimatepixel) {
1309 over = w2;
1310 do {
1311 much = over; more = 0;
1312 margin = 0; mask = 0x00;
1313 if (rex < much)
1314 much = rex;
1315 rump = 0;
1317 if (much % 2) {
1318 SAM("MISTAKE: much is odd\n");
1319 return -EFAULT;
1322 more = (bytesperpixel *
1323 much) / 2;
1324 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1325 if (1 < bytesperpixel) {
1326 if (rad * 2 < much * bytesperpixel) {
1328 * INJUDICIOUS ALTERATION OF
1329 * THIS STATEMENT BLOCK WILL
1330 * CAUSE BREAKAGE. BEWARE.
1332 rad2 = rad + bytesperpixel - 1;
1333 much = ((((2 * rad2)/bytesperpixel)/2) * 2);
1334 rump = ((bytesperpixel * much) / 2) - rad;
1335 more = rad;
1337 mask = (u8)rump;
1338 margin = 0;
1339 if (much == rex) {
1340 mask |= 0x04;
1341 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1342 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1343 else
1344 mask |= 0x08;
1346 } else {
1347 SAM("MISTAKE: %i=bytesperpixel\n",
1348 bytesperpixel);
1349 return -EFAULT;
1351 if (rump)
1352 caches++;
1353 if (badinput) {
1354 JOM(8, "ERROR: 0x%02X=->field_buffer"
1355 "[%i][%i].input, "
1356 "0x%02X=(0x08|->input)\n",
1357 peasycap->field_buffer
1358 [kex][mex].input, kex, mex,
1359 (0x08|peasycap->input));
1361 rc = redaub(peasycap, pad, pex, much, more,
1362 mask, margin, isuy);
1363 if (0 > rc) {
1364 SAM("ERROR: redaub() failed\n");
1365 return -EFAULT;
1367 if (much % 4)
1368 isuy = !isuy;
1370 over -= much; cz += much;
1371 pex += much; rex -= much;
1372 if (!rex) {
1373 mex++;
1374 pex = peasycap->field_buffer[kex][mex].pgo;
1375 rex = PAGE_SIZE;
1376 if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
1377 badinput = true;
1379 pad += more;
1380 rad -= more;
1381 if (!rad) {
1382 mad++;
1383 pad = peasycap->frame_buffer[kad][mad].pgo;
1384 rad = PAGE_SIZE;
1385 if (rump) {
1386 pad += rump;
1387 rad -= rump;
1390 } while (over);
1391 /*---------------------------------------------------------------------------*/
1393 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1394 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1396 /*---------------------------------------------------------------------------*/
1397 if (!odd || (cz != wz)) {
1398 over = w3;
1399 do {
1400 if (!rad) {
1401 mad++;
1402 pad = peasycap->frame_buffer
1403 [kad][mad].pgo;
1404 rad = PAGE_SIZE;
1406 more = over;
1407 if (rad < more)
1408 more = rad;
1409 over -= more;
1410 pad += more;
1411 rad -= more;
1412 } while (over);
1414 /*---------------------------------------------------------------------------*/
1416 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1417 * ONLY IF false==odd,
1418 * READ w2 BYTES FROM FIELD BUFFER,
1419 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1421 /*---------------------------------------------------------------------------*/
1422 } else if (!odd) {
1423 over = w2;
1424 do {
1425 much = over; more = 0; margin = 0; mask = 0x00;
1426 if (rex < much)
1427 much = rex;
1428 rump = 0;
1430 if (much % 2) {
1431 SAM("MISTAKE: much is odd\n");
1432 return -EFAULT;
1435 more = (bytesperpixel * much) / 4;
1436 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1437 if (1 < bytesperpixel) {
1438 if (rad * 4 < much * bytesperpixel) {
1440 * INJUDICIOUS ALTERATION OF
1441 * THIS STATEMENT BLOCK
1442 * WILL CAUSE BREAKAGE.
1443 * BEWARE.
1445 rad2 = rad + bytesperpixel - 1;
1446 much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
1447 rump = ((bytesperpixel * much) / 4) - rad;
1448 more = rad;
1450 mask = (u8)rump;
1451 margin = 0;
1452 if (much == rex) {
1453 mask |= 0x04;
1454 if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
1455 margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
1456 else
1457 mask |= 0x08;
1459 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1460 } else {
1461 SAM("MISTAKE: %i=bytesperpixel\n",
1462 bytesperpixel);
1463 return -EFAULT;
1465 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1466 if (rump)
1467 caches++;
1469 if (badinput) {
1470 JOM(8, "ERROR: 0x%02X=->field_buffer"
1471 "[%i][%i].input, "
1472 "0x%02X=(0x08|->input)\n",
1473 peasycap->field_buffer
1474 [kex][mex].input, kex, mex,
1475 (0x08|peasycap->input));
1477 rc = redaub(peasycap, pad, pex, much, more,
1478 mask, margin, isuy);
1479 if (0 > rc) {
1480 SAM("ERROR: redaub() failed\n");
1481 return -EFAULT;
1483 over -= much; cz += much;
1484 pex += much; rex -= much;
1485 if (!rex) {
1486 mex++;
1487 pex = peasycap->field_buffer[kex][mex].pgo;
1488 rex = PAGE_SIZE;
1489 if (peasycap->field_buffer[kex][mex].input !=
1490 (0x08|peasycap->input))
1491 badinput = true;
1493 pad += more;
1494 rad -= more;
1495 if (!rad) {
1496 mad++;
1497 pad = peasycap->frame_buffer[kad][mad].pgo;
1498 rad = PAGE_SIZE;
1499 if (rump) {
1500 pad += rump;
1501 rad -= rump;
1504 } while (over);
1505 /*---------------------------------------------------------------------------*/
1507 * OTHERWISE JUST
1508 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1510 /*---------------------------------------------------------------------------*/
1511 } else {
1512 over = w2;
1513 do {
1514 if (!rex) {
1515 mex++;
1516 pex = peasycap->field_buffer[kex][mex].pgo;
1517 rex = PAGE_SIZE;
1518 if (peasycap->field_buffer[kex][mex].input !=
1519 (0x08|peasycap->input)) {
1520 JOM(8, "ERROR: 0x%02X=->field_buffer"
1521 "[%i][%i].input, "
1522 "0x%02X=(0x08|->input)\n",
1523 peasycap->field_buffer
1524 [kex][mex].input, kex, mex,
1525 (0x08|peasycap->input));
1526 badinput = true;
1529 much = over;
1530 if (rex < much)
1531 much = rex;
1532 over -= much;
1533 cz += much;
1534 pex += much;
1535 rex -= much;
1536 } while (over);
1539 /*---------------------------------------------------------------------------*/
1541 * SANITY CHECKS
1543 /*---------------------------------------------------------------------------*/
1544 c2 = (mex + 1)*PAGE_SIZE - rex;
1545 if (cz != c2)
1546 SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1547 c3 = (mad + 1)*PAGE_SIZE - rad;
1549 if (!decimatepixel) {
1550 if (bytesperpixel * cz != c3)
1551 SAM("ERROR: discrepancy %i in bytes written\n",
1552 c3 - (bytesperpixel * cz));
1553 } else {
1554 if (!odd) {
1555 if (bytesperpixel *
1556 cz != (4 * c3))
1557 SAM("ERROR: discrepancy %i in bytes written\n",
1558 (2*c3)-(bytesperpixel * cz));
1559 } else {
1560 if (0 != c3)
1561 SAM("ERROR: discrepancy %i "
1562 "in bytes written\n", c3);
1565 if (rump)
1566 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1568 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1569 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1571 if (odd)
1572 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1574 if (peasycap->field_read == peasycap->field_fill)
1575 SAM("WARNING: on exit, filling field buffer %i\n",
1576 peasycap->field_read);
1577 /*---------------------------------------------------------------------------*/
1579 * CALCULATE VIDEO STREAMING RATE
1581 /*---------------------------------------------------------------------------*/
1582 do_gettimeofday(&timeval);
1583 if (peasycap->timeval6.tv_sec) {
1584 below = ((long long int)(1000000)) *
1585 ((long long int)(timeval.tv_sec -
1586 peasycap->timeval6.tv_sec)) +
1587 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1588 above = (long long int)1000000;
1590 sdr = signed_div(above, below);
1591 above = sdr.quotient;
1592 remainder = (u32)sdr.remainder;
1594 JOM(8, "video streaming at %3lli.%03i fields per second\n",
1595 above, (remainder/1000));
1597 peasycap->timeval6 = timeval;
1599 if (caches)
1600 JOM(8, "%i=caches\n", caches);
1601 return 0;
1603 /*****************************************************************************/
1604 struct signed_div_result
1605 signed_div(long long int above, long long int below)
1607 struct signed_div_result sdr;
1609 if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) {
1610 sdr.remainder = (unsigned long long int) do_div(above, below);
1611 sdr.quotient = (long long int) above;
1612 } else {
1613 if (0 > above)
1614 above = -above;
1615 if (0 > below)
1616 below = -below;
1617 sdr.remainder = (unsigned long long int) do_div(above, below);
1618 sdr.quotient = -((long long int) above);
1620 return sdr;
1622 /*****************************************************************************/
1623 /*---------------------------------------------------------------------------*/
1625 * DECIMATION AND COLOURSPACE CONVERSION.
1627 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1628 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1629 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1630 * ALSO ENSURE THAT much IS EVEN.
1632 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1633 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1635 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1636 * 0x03 & mask = number of bytes to be written to cache instead of to
1637 * frame buffer
1638 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1639 * 0x08 & mask => do not set the chrominance for last pixel
1641 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1643 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1644 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1645 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1647 /*---------------------------------------------------------------------------*/
1649 redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1650 u8 mask, u8 margin, bool isuy)
1652 static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1653 u8 *pcache;
1654 u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1655 int bytesperpixel;
1656 bool byteswaporder, decimatepixel, last;
1657 int j, rump;
1658 s32 tmp;
1660 if (much % 2) {
1661 SAM("MISTAKE: much is odd\n");
1662 return -EFAULT;
1664 bytesperpixel = peasycap->bytesperpixel;
1665 byteswaporder = peasycap->byteswaporder;
1666 decimatepixel = peasycap->decimatepixel;
1668 /*---------------------------------------------------------------------------*/
1669 if (!bu[255]) {
1670 for (j = 0; j < 112; j++) {
1671 tmp = (0xFF00 & (453 * j)) >> 8;
1672 bu[j + 128] = tmp; bu[127 - j] = -tmp;
1673 tmp = (0xFF00 & (359 * j)) >> 8;
1674 rv[j + 128] = tmp; rv[127 - j] = -tmp;
1675 tmp = (0xFF00 & (88 * j)) >> 8;
1676 gu[j + 128] = tmp; gu[127 - j] = -tmp;
1677 tmp = (0xFF00 & (183 * j)) >> 8;
1678 gv[j + 128] = tmp; gv[127 - j] = -tmp;
1680 for (j = 0; j < 16; j++) {
1681 bu[j] = bu[16]; rv[j] = rv[16];
1682 gu[j] = gu[16]; gv[j] = gv[16];
1684 for (j = 240; j < 256; j++) {
1685 bu[j] = bu[239]; rv[j] = rv[239];
1686 gu[j] = gu[239]; gv[j] = gv[239];
1688 for (j = 16; j < 236; j++)
1689 ay[j] = j;
1690 for (j = 0; j < 16; j++)
1691 ay[j] = ay[16];
1692 for (j = 236; j < 256; j++)
1693 ay[j] = ay[235];
1694 JOM(8, "lookup tables are prepared\n");
1696 pcache = peasycap->pcache;
1697 if (!pcache)
1698 pcache = &peasycap->cache[0];
1699 /*---------------------------------------------------------------------------*/
1701 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1703 /*---------------------------------------------------------------------------*/
1704 if (!pcache) {
1705 SAM("MISTAKE: pcache is NULL\n");
1706 return -EFAULT;
1709 if (pcache != &peasycap->cache[0])
1710 JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1711 p2 = &peasycap->cache[0];
1712 p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1713 while (p2 < pcache) {
1714 *p3++ = *p2; p2++;
1716 pcache = &peasycap->cache[0];
1717 if (p3 != pad) {
1718 SAM("MISTAKE: pointer misalignment\n");
1719 return -EFAULT;
1721 /*---------------------------------------------------------------------------*/
1722 rump = (int)(0x03 & mask);
1723 u = 0; v = 0;
1724 p2 = (u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1725 p2++;
1727 if (isuy)
1728 u = *(p2 - 1);
1729 else
1730 v = *(p2 - 1);
1732 if (rump)
1733 JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1735 /*---------------------------------------------------------------------------*/
1736 switch (bytesperpixel) {
1737 case 2: {
1738 if (!decimatepixel) {
1739 memcpy(pad, pex, (size_t)much);
1740 if (!byteswaporder) {
1741 /* UYVY */
1742 return 0;
1743 } else {
1744 /* YUYV */
1745 p3 = (u8 *)pad; pz = p3 + much;
1746 while (pz > p3) {
1747 c = *p3;
1748 *p3 = *(p3 + 1);
1749 *(p3 + 1) = c;
1750 p3 += 2;
1752 return 0;
1754 } else {
1755 if (!byteswaporder) {
1756 /* UYVY DECIMATED */
1757 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1758 while (pz > p2) {
1759 *p3 = *p2;
1760 *(p3 + 1) = *(p2 + 1);
1761 *(p3 + 2) = *(p2 + 2);
1762 *(p3 + 3) = *(p2 + 3);
1763 p3 += 4; p2 += 8;
1765 return 0;
1766 } else {
1767 /* YUYV DECIMATED */
1768 p2 = (u8 *)pex; p3 = (u8 *)pad; pz = p2 + much;
1769 while (pz > p2) {
1770 *p3 = *(p2 + 1);
1771 *(p3 + 1) = *p2;
1772 *(p3 + 2) = *(p2 + 3);
1773 *(p3 + 3) = *(p2 + 2);
1774 p3 += 4; p2 += 8;
1776 return 0;
1779 break;
1781 case 3:
1783 if (!decimatepixel) {
1784 if (!byteswaporder) {
1785 /* RGB */
1786 while (pz > p2) {
1787 if (pr <= (p3 + bytesperpixel))
1788 last = true;
1789 else
1790 last = false;
1791 y = *p2;
1792 if (last && (0x0C & mask)) {
1793 if (0x04 & mask) {
1794 if (isuy)
1795 v = margin;
1796 else
1797 u = margin;
1798 } else
1799 if (0x08 & mask)
1801 } else {
1802 if (isuy)
1803 v = *(p2 + 1);
1804 else
1805 u = *(p2 + 1);
1808 tmp = ay[(int)y] + rv[(int)v];
1809 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1810 0 : (u8)tmp);
1811 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1812 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1813 0 : (u8)tmp);
1814 tmp = ay[(int)y] + bu[(int)u];
1815 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1816 0 : (u8)tmp);
1818 if (last && rump) {
1819 pcache = &peasycap->cache[0];
1820 switch (bytesperpixel - rump) {
1821 case 1: {
1822 *p3 = r;
1823 *pcache++ = g;
1824 *pcache++ = b;
1825 break;
1827 case 2: {
1828 *p3 = r;
1829 *(p3 + 1) = g;
1830 *pcache++ = b;
1831 break;
1833 default: {
1834 SAM("MISTAKE: %i=rump\n",
1835 bytesperpixel - rump);
1836 return -EFAULT;
1839 } else {
1840 *p3 = r;
1841 *(p3 + 1) = g;
1842 *(p3 + 2) = b;
1844 p2 += 2;
1845 if (isuy)
1846 isuy = false;
1847 else
1848 isuy = true;
1849 p3 += bytesperpixel;
1851 return 0;
1852 } else {
1853 /* BGR */
1854 while (pz > p2) {
1855 if (pr <= (p3 + bytesperpixel))
1856 last = true;
1857 else
1858 last = false;
1859 y = *p2;
1860 if (last && (0x0C & mask)) {
1861 if (0x04 & mask) {
1862 if (isuy)
1863 v = margin;
1864 else
1865 u = margin;
1867 else
1868 if (0x08 & mask)
1870 } else {
1871 if (isuy)
1872 v = *(p2 + 1);
1873 else
1874 u = *(p2 + 1);
1877 tmp = ay[(int)y] + rv[(int)v];
1878 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1879 0 : (u8)tmp);
1880 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
1881 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1882 0 : (u8)tmp);
1883 tmp = ay[(int)y] + bu[(int)u];
1884 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1885 0 : (u8)tmp);
1887 if (last && rump) {
1888 pcache = &peasycap->cache[0];
1889 switch (bytesperpixel - rump) {
1890 case 1: {
1891 *p3 = b;
1892 *pcache++ = g;
1893 *pcache++ = r;
1894 break;
1896 case 2: {
1897 *p3 = b;
1898 *(p3 + 1) = g;
1899 *pcache++ = r;
1900 break;
1902 default: {
1903 SAM("MISTAKE: %i=rump\n",
1904 bytesperpixel - rump);
1905 return -EFAULT;
1908 } else {
1909 *p3 = b;
1910 *(p3 + 1) = g;
1911 *(p3 + 2) = r;
1913 p2 += 2;
1914 if (isuy)
1915 isuy = false;
1916 else
1917 isuy = true;
1918 p3 += bytesperpixel;
1921 return 0;
1922 } else {
1923 if (!byteswaporder) {
1924 /* RGB DECIMATED */
1925 while (pz > p2) {
1926 if (pr <= (p3 + bytesperpixel))
1927 last = true;
1928 else
1929 last = false;
1930 y = *p2;
1931 if (last && (0x0C & mask)) {
1932 if (0x04 & mask) {
1933 if (isuy)
1934 v = margin;
1935 else
1936 u = margin;
1937 } else
1938 if (0x08 & mask)
1940 } else {
1941 if (isuy)
1942 v = *(p2 + 1);
1943 else
1944 u = *(p2 + 1);
1947 if (isuy) {
1948 tmp = ay[(int)y] + rv[(int)v];
1949 r = (255 < tmp) ? 255 : ((0 > tmp) ?
1950 0 : (u8)tmp);
1951 tmp = ay[(int)y] - gu[(int)u] -
1952 gv[(int)v];
1953 g = (255 < tmp) ? 255 : ((0 > tmp) ?
1954 0 : (u8)tmp);
1955 tmp = ay[(int)y] + bu[(int)u];
1956 b = (255 < tmp) ? 255 : ((0 > tmp) ?
1957 0 : (u8)tmp);
1959 if (last && rump) {
1960 pcache = &peasycap->cache[0];
1961 switch (bytesperpixel - rump) {
1962 case 1: {
1963 *p3 = r;
1964 *pcache++ = g;
1965 *pcache++ = b;
1966 break;
1968 case 2: {
1969 *p3 = r;
1970 *(p3 + 1) = g;
1971 *pcache++ = b;
1972 break;
1974 default: {
1975 SAM("MISTAKE: "
1976 "%i=rump\n",
1977 bytesperpixel - rump);
1978 return -EFAULT;
1981 } else {
1982 *p3 = r;
1983 *(p3 + 1) = g;
1984 *(p3 + 2) = b;
1986 isuy = false;
1987 p3 += bytesperpixel;
1988 } else {
1989 isuy = true;
1991 p2 += 2;
1993 return 0;
1994 } else {
1995 /* BGR DECIMATED */
1996 while (pz > p2) {
1997 if (pr <= (p3 + bytesperpixel))
1998 last = true;
1999 else
2000 last = false;
2001 y = *p2;
2002 if (last && (0x0C & mask)) {
2003 if (0x04 & mask) {
2004 if (isuy)
2005 v = margin;
2006 else
2007 u = margin;
2008 } else
2009 if (0x08 & mask)
2011 } else {
2012 if (isuy)
2013 v = *(p2 + 1);
2014 else
2015 u = *(p2 + 1);
2018 if (isuy) {
2020 tmp = ay[(int)y] + rv[(int)v];
2021 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2022 0 : (u8)tmp);
2023 tmp = ay[(int)y] - gu[(int)u] -
2024 gv[(int)v];
2025 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2026 0 : (u8)tmp);
2027 tmp = ay[(int)y] + bu[(int)u];
2028 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2029 0 : (u8)tmp);
2031 if (last && rump) {
2032 pcache = &peasycap->cache[0];
2033 switch (bytesperpixel - rump) {
2034 case 1: {
2035 *p3 = b;
2036 *pcache++ = g;
2037 *pcache++ = r;
2038 break;
2040 case 2: {
2041 *p3 = b;
2042 *(p3 + 1) = g;
2043 *pcache++ = r;
2044 break;
2046 default: {
2047 SAM("MISTAKE: "
2048 "%i=rump\n",
2049 bytesperpixel - rump);
2050 return -EFAULT;
2053 } else {
2054 *p3 = b;
2055 *(p3 + 1) = g;
2056 *(p3 + 2) = r;
2058 isuy = false;
2059 p3 += bytesperpixel;
2061 else
2062 isuy = true;
2063 p2 += 2;
2065 return 0;
2068 break;
2070 case 4:
2072 if (!decimatepixel) {
2073 if (!byteswaporder) {
2074 /* RGBA */
2075 while (pz > p2) {
2076 if (pr <= (p3 + bytesperpixel))
2077 last = true;
2078 else
2079 last = false;
2080 y = *p2;
2081 if (last && (0x0C & mask)) {
2082 if (0x04 & mask) {
2083 if (isuy)
2084 v = margin;
2085 else
2086 u = margin;
2087 } else
2088 if (0x08 & mask)
2090 } else {
2091 if (isuy)
2092 v = *(p2 + 1);
2093 else
2094 u = *(p2 + 1);
2097 tmp = ay[(int)y] + rv[(int)v];
2098 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2099 0 : (u8)tmp);
2100 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2101 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2102 0 : (u8)tmp);
2103 tmp = ay[(int)y] + bu[(int)u];
2104 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2105 0 : (u8)tmp);
2107 if (last && rump) {
2108 pcache = &peasycap->cache[0];
2109 switch (bytesperpixel - rump) {
2110 case 1: {
2111 *p3 = r;
2112 *pcache++ = g;
2113 *pcache++ = b;
2114 *pcache++ = 0;
2115 break;
2117 case 2: {
2118 *p3 = r;
2119 *(p3 + 1) = g;
2120 *pcache++ = b;
2121 *pcache++ = 0;
2122 break;
2124 case 3: {
2125 *p3 = r;
2126 *(p3 + 1) = g;
2127 *(p3 + 2) = b;
2128 *pcache++ = 0;
2129 break;
2131 default: {
2132 SAM("MISTAKE: %i=rump\n",
2133 bytesperpixel - rump);
2134 return -EFAULT;
2137 } else {
2138 *p3 = r;
2139 *(p3 + 1) = g;
2140 *(p3 + 2) = b;
2141 *(p3 + 3) = 0;
2143 p2 += 2;
2144 if (isuy)
2145 isuy = false;
2146 else
2147 isuy = true;
2148 p3 += bytesperpixel;
2150 return 0;
2151 } else {
2153 * BGRA
2155 while (pz > p2) {
2156 if (pr <= (p3 + bytesperpixel))
2157 last = true;
2158 else
2159 last = false;
2160 y = *p2;
2161 if (last && (0x0C & mask)) {
2162 if (0x04 & mask) {
2163 if (isuy)
2164 v = margin;
2165 else
2166 u = margin;
2167 } else
2168 if (0x08 & mask)
2170 } else {
2171 if (isuy)
2172 v = *(p2 + 1);
2173 else
2174 u = *(p2 + 1);
2177 tmp = ay[(int)y] + rv[(int)v];
2178 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2179 0 : (u8)tmp);
2180 tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
2181 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2182 0 : (u8)tmp);
2183 tmp = ay[(int)y] + bu[(int)u];
2184 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2185 0 : (u8)tmp);
2187 if (last && rump) {
2188 pcache = &peasycap->cache[0];
2189 switch (bytesperpixel - rump) {
2190 case 1: {
2191 *p3 = b;
2192 *pcache++ = g;
2193 *pcache++ = r;
2194 *pcache++ = 0;
2195 break;
2197 case 2: {
2198 *p3 = b;
2199 *(p3 + 1) = g;
2200 *pcache++ = r;
2201 *pcache++ = 0;
2202 break;
2204 case 3: {
2205 *p3 = b;
2206 *(p3 + 1) = g;
2207 *(p3 + 2) = r;
2208 *pcache++ = 0;
2209 break;
2211 default:
2212 SAM("MISTAKE: %i=rump\n",
2213 bytesperpixel - rump);
2214 return -EFAULT;
2216 } else {
2217 *p3 = b;
2218 *(p3 + 1) = g;
2219 *(p3 + 2) = r;
2220 *(p3 + 3) = 0;
2222 p2 += 2;
2223 if (isuy)
2224 isuy = false;
2225 else
2226 isuy = true;
2227 p3 += bytesperpixel;
2230 return 0;
2231 } else {
2232 if (!byteswaporder) {
2234 * RGBA DECIMATED
2236 while (pz > p2) {
2237 if (pr <= (p3 + bytesperpixel))
2238 last = true;
2239 else
2240 last = false;
2241 y = *p2;
2242 if (last && (0x0C & mask)) {
2243 if (0x04 & mask) {
2244 if (isuy)
2245 v = margin;
2246 else
2247 u = margin;
2248 } else
2249 if (0x08 & mask)
2251 } else {
2252 if (isuy)
2253 v = *(p2 + 1);
2254 else
2255 u = *(p2 + 1);
2258 if (isuy) {
2260 tmp = ay[(int)y] + rv[(int)v];
2261 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2262 0 : (u8)tmp);
2263 tmp = ay[(int)y] - gu[(int)u] -
2264 gv[(int)v];
2265 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2266 0 : (u8)tmp);
2267 tmp = ay[(int)y] + bu[(int)u];
2268 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2269 0 : (u8)tmp);
2271 if (last && rump) {
2272 pcache = &peasycap->cache[0];
2273 switch (bytesperpixel - rump) {
2274 case 1: {
2275 *p3 = r;
2276 *pcache++ = g;
2277 *pcache++ = b;
2278 *pcache++ = 0;
2279 break;
2281 case 2: {
2282 *p3 = r;
2283 *(p3 + 1) = g;
2284 *pcache++ = b;
2285 *pcache++ = 0;
2286 break;
2288 case 3: {
2289 *p3 = r;
2290 *(p3 + 1) = g;
2291 *(p3 + 2) = b;
2292 *pcache++ = 0;
2293 break;
2295 default: {
2296 SAM("MISTAKE: "
2297 "%i=rump\n",
2298 bytesperpixel -
2299 rump);
2300 return -EFAULT;
2303 } else {
2304 *p3 = r;
2305 *(p3 + 1) = g;
2306 *(p3 + 2) = b;
2307 *(p3 + 3) = 0;
2309 isuy = false;
2310 p3 += bytesperpixel;
2311 } else
2312 isuy = true;
2313 p2 += 2;
2315 return 0;
2316 } else {
2318 * BGRA DECIMATED
2320 while (pz > p2) {
2321 if (pr <= (p3 + bytesperpixel))
2322 last = true;
2323 else
2324 last = false;
2325 y = *p2;
2326 if (last && (0x0C & mask)) {
2327 if (0x04 & mask) {
2328 if (isuy)
2329 v = margin;
2330 else
2331 u = margin;
2332 } else
2333 if (0x08 & mask)
2335 } else {
2336 if (isuy)
2337 v = *(p2 + 1);
2338 else
2339 u = *(p2 + 1);
2342 if (isuy) {
2343 tmp = ay[(int)y] + rv[(int)v];
2344 r = (255 < tmp) ? 255 : ((0 > tmp) ?
2345 0 : (u8)tmp);
2346 tmp = ay[(int)y] - gu[(int)u] -
2347 gv[(int)v];
2348 g = (255 < tmp) ? 255 : ((0 > tmp) ?
2349 0 : (u8)tmp);
2350 tmp = ay[(int)y] + bu[(int)u];
2351 b = (255 < tmp) ? 255 : ((0 > tmp) ?
2352 0 : (u8)tmp);
2354 if (last && rump) {
2355 pcache = &peasycap->cache[0];
2356 switch (bytesperpixel - rump) {
2357 case 1: {
2358 *p3 = b;
2359 *pcache++ = g;
2360 *pcache++ = r;
2361 *pcache++ = 0;
2362 break;
2364 case 2: {
2365 *p3 = b;
2366 *(p3 + 1) = g;
2367 *pcache++ = r;
2368 *pcache++ = 0;
2369 break;
2371 case 3: {
2372 *p3 = b;
2373 *(p3 + 1) = g;
2374 *(p3 + 2) = r;
2375 *pcache++ = 0;
2376 break;
2378 default: {
2379 SAM("MISTAKE: "
2380 "%i=rump\n",
2381 bytesperpixel - rump);
2382 return -EFAULT;
2385 } else {
2386 *p3 = b;
2387 *(p3 + 1) = g;
2388 *(p3 + 2) = r;
2389 *(p3 + 3) = 0;
2391 isuy = false;
2392 p3 += bytesperpixel;
2393 } else
2394 isuy = true;
2395 p2 += 2;
2397 return 0;
2400 break;
2402 default: {
2403 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2404 return -EFAULT;
2407 return 0;
2409 /*****************************************************************************/
2411 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2413 /*****************************************************************************/
2414 static void easycap_vma_open(struct vm_area_struct *pvma)
2416 struct easycap *peasycap;
2418 peasycap = pvma->vm_private_data;
2419 if (!peasycap) {
2420 SAY("ERROR: peasycap is NULL\n");
2421 return;
2423 peasycap->vma_many++;
2424 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2425 return;
2427 /*****************************************************************************/
2428 static void easycap_vma_close(struct vm_area_struct *pvma)
2430 struct easycap *peasycap;
2432 peasycap = pvma->vm_private_data;
2433 if (!peasycap) {
2434 SAY("ERROR: peasycap is NULL\n");
2435 return;
2437 peasycap->vma_many--;
2438 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2439 return;
2441 /*****************************************************************************/
2442 static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2444 int k, m, retcode;
2445 void *pbuf;
2446 struct page *page;
2447 struct easycap *peasycap;
2449 retcode = VM_FAULT_NOPAGE;
2451 if (!pvma) {
2452 SAY("pvma is NULL\n");
2453 return retcode;
2455 if (!pvmf) {
2456 SAY("pvmf is NULL\n");
2457 return retcode;
2460 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2461 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2463 if (!m)
2464 JOT(4, "%4i=k, %4i=m\n", k, m);
2465 else
2466 JOT(16, "%4i=k, %4i=m\n", k, m);
2468 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2469 SAY("ERROR: buffer index %i out of range\n", k);
2470 return retcode;
2472 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2473 SAY("ERROR: page number %i out of range\n", m);
2474 return retcode;
2476 peasycap = pvma->vm_private_data;
2477 if (!peasycap) {
2478 SAY("ERROR: peasycap is NULL\n");
2479 return retcode;
2481 /*---------------------------------------------------------------------------*/
2482 pbuf = peasycap->frame_buffer[k][m].pgo;
2483 if (!pbuf) {
2484 SAM("ERROR: pbuf is NULL\n");
2485 return retcode;
2487 page = virt_to_page(pbuf);
2488 if (!page) {
2489 SAM("ERROR: page is NULL\n");
2490 return retcode;
2492 get_page(page);
2493 /*---------------------------------------------------------------------------*/
2494 if (!page) {
2495 SAM("ERROR: page is NULL after get_page(page)\n");
2496 } else {
2497 pvmf->page = page;
2498 retcode = VM_FAULT_MINOR;
2500 return retcode;
2503 static const struct vm_operations_struct easycap_vm_ops = {
2504 .open = easycap_vma_open,
2505 .close = easycap_vma_close,
2506 .fault = easycap_vma_fault,
2509 static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2511 JOT(8, "\n");
2513 pvma->vm_ops = &easycap_vm_ops;
2514 pvma->vm_flags |= VM_RESERVED;
2515 if (file)
2516 pvma->vm_private_data = file->private_data;
2517 easycap_vma_open(pvma);
2518 return 0;
2520 /*****************************************************************************/
2521 /*---------------------------------------------------------------------------*/
2523 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2524 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2525 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2527 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2529 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2530 * STORED IN THE TWO-BYTE STATUS PARAMETER
2531 * peasycap->field_buffer[peasycap->field_fill][0].kount
2532 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2534 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2535 * CHIP.
2537 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2538 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2539 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2540 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2541 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2542 * 0 != (kount & 0x0400) => RESERVED
2543 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2544 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2546 /*---------------------------------------------------------------------------*/
2547 static void easycap_complete(struct urb *purb)
2549 struct easycap *peasycap;
2550 struct data_buffer *pfield_buffer;
2551 char errbuf[16];
2552 int i, more, much, leap, rc, last;
2553 int videofieldamount;
2554 unsigned int override, bad;
2555 int framestatus, framelength, frameactual, frameoffset;
2556 u8 *pu;
2558 if (!purb) {
2559 SAY("ERROR: easycap_complete(): purb is NULL\n");
2560 return;
2562 peasycap = purb->context;
2563 if (!peasycap) {
2564 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2565 return;
2567 if (peasycap->video_eof)
2568 return;
2569 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2570 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2571 break;
2572 JOM(16, "%2i=urb\n", i);
2573 last = peasycap->video_isoc_sequence;
2574 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
2575 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
2576 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
2577 last, i);
2579 peasycap->video_isoc_sequence = i;
2581 if (peasycap->video_idle) {
2582 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2583 peasycap->video_idle, peasycap->video_isoc_streaming);
2584 if (peasycap->video_isoc_streaming) {
2585 rc = usb_submit_urb(purb, GFP_ATOMIC);
2586 if (rc) {
2587 SAM("%s:%d ENOMEM\n", strerror(rc), rc);
2588 if (-ENODEV != rc)
2589 SAM("ERROR: while %i=video_idle, "
2590 "usb_submit_urb() "
2591 "failed with rc:\n",
2592 peasycap->video_idle);
2595 return;
2597 override = 0;
2598 /*---------------------------------------------------------------------------*/
2599 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2600 SAM("ERROR: bad peasycap->field_fill\n");
2601 return;
2603 if (purb->status) {
2604 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2605 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2606 return;
2609 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2610 SAM("ERROR: bad urb status -%s: %d\n",
2611 strerror(purb->status), purb->status);
2612 /*---------------------------------------------------------------------------*/
2613 } else {
2614 for (i = 0; i < purb->number_of_packets; i++) {
2615 if (0 != purb->iso_frame_desc[i].status) {
2616 (peasycap->field_buffer
2617 [peasycap->field_fill][0].kount) |= 0x8000 ;
2618 /* FIXME: 1. missing '-' check boundaries */
2619 strcpy(&errbuf[0],
2620 strerror(purb->iso_frame_desc[i].status));
2622 framestatus = purb->iso_frame_desc[i].status;
2623 framelength = purb->iso_frame_desc[i].length;
2624 frameactual = purb->iso_frame_desc[i].actual_length;
2625 frameoffset = purb->iso_frame_desc[i].offset;
2627 JOM(16, "frame[%2i]:"
2628 "%4i=status "
2629 "%4i=actual "
2630 "%4i=length "
2631 "%5i=offset\n",
2632 i, framestatus, frameactual, framelength, frameoffset);
2633 if (!purb->iso_frame_desc[i].status) {
2634 more = purb->iso_frame_desc[i].actual_length;
2635 pfield_buffer = &peasycap->field_buffer
2636 [peasycap->field_fill][peasycap->field_page];
2637 videofieldamount = (peasycap->field_page *
2638 PAGE_SIZE) +
2639 (int)(pfield_buffer->pto - pfield_buffer->pgo);
2640 if (4 == more)
2641 peasycap->video_mt++;
2642 if (4 < more) {
2643 if (peasycap->video_mt) {
2644 JOM(8, "%4i empty video urb frames\n",
2645 peasycap->video_mt);
2646 peasycap->video_mt = 0;
2648 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2649 SAM("ERROR: bad peasycap->field_fill\n");
2650 return;
2652 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2653 peasycap->field_page) {
2654 SAM("ERROR: bad peasycap->field_page\n");
2655 return;
2657 pfield_buffer = &peasycap->field_buffer
2658 [peasycap->field_fill][peasycap->field_page];
2659 pu = (u8 *)(purb->transfer_buffer +
2660 purb->iso_frame_desc[i].offset);
2661 if (0x80 & *pu)
2662 leap = 8;
2663 else
2664 leap = 4;
2665 /*--------------------------------------------------------------------------*/
2667 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
2668 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
2669 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
2671 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
2672 * BYTE OF
2673 * peasycap->field_buffer[peasycap->field_fill][0].kount
2674 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
2675 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
2676 * NOTHING IS OFFERED TO dqbuf().
2678 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
2679 * RESTS WITH dqbuf().
2681 /*---------------------------------------------------------------------------*/
2682 if ((8 == more) || override) {
2683 if (videofieldamount >
2684 peasycap->videofieldamount) {
2685 if (2 == videofieldamount -
2686 peasycap->
2687 videofieldamount) {
2688 (peasycap->field_buffer
2689 [peasycap->field_fill]
2690 [0].kount) |= 0x0100;
2691 peasycap->video_junk += (1 +
2692 VIDEO_JUNK_TOLERATE);
2693 } else
2694 (peasycap->field_buffer
2695 [peasycap->field_fill]
2696 [0].kount) |= 0x4000;
2697 } else if (videofieldamount <
2698 peasycap->
2699 videofieldamount) {
2700 (peasycap->field_buffer
2701 [peasycap->field_fill]
2702 [0].kount) |= 0x2000;
2704 bad = 0xFF00 & peasycap->field_buffer
2705 [peasycap->field_fill]
2706 [0].kount;
2707 if (!bad) {
2708 (peasycap->video_junk)--;
2709 if (-VIDEO_JUNK_TOLERATE >
2710 peasycap->video_junk)
2711 peasycap->video_junk =
2712 -VIDEO_JUNK_TOLERATE;
2713 peasycap->field_read =
2714 (peasycap->
2715 field_fill)++;
2716 if (FIELD_BUFFER_MANY <=
2717 peasycap->
2718 field_fill)
2719 peasycap->
2720 field_fill = 0;
2721 peasycap->field_page = 0;
2722 pfield_buffer = &peasycap->
2723 field_buffer
2724 [peasycap->
2725 field_fill]
2726 [peasycap->
2727 field_page];
2728 pfield_buffer->pto =
2729 pfield_buffer->pgo;
2730 JOM(8, "bumped to: %i="
2731 "peasycap->"
2732 "field_fill %i="
2733 "parity\n",
2734 peasycap->field_fill,
2735 0x00FF &
2736 pfield_buffer->kount);
2737 JOM(8, "field buffer %i has "
2738 "%i bytes fit to be "
2739 "read\n",
2740 peasycap->field_read,
2741 videofieldamount);
2742 JOM(8, "wakeup call to "
2743 "wq_video, "
2744 "%i=field_read "
2745 "%i=field_fill "
2746 "%i=parity\n",
2747 peasycap->field_read,
2748 peasycap->field_fill,
2749 0x00FF & peasycap->
2750 field_buffer
2751 [peasycap->
2752 field_read][0].kount);
2753 wake_up_interruptible
2754 (&(peasycap->
2755 wq_video));
2756 do_gettimeofday
2757 (&peasycap->timeval7);
2758 } else {
2759 peasycap->video_junk++;
2760 if (bad & 0x0010)
2761 peasycap->video_junk +=
2762 (1 + VIDEO_JUNK_TOLERATE/2);
2763 JOM(8, "field buffer %i had %i "
2764 "bytes, now discarded: "
2765 "0x%04X\n",
2766 peasycap->field_fill,
2767 videofieldamount,
2768 (0xFF00 &
2769 peasycap->field_buffer
2770 [peasycap->field_fill][0].
2771 kount));
2772 (peasycap->field_fill)++;
2774 if (FIELD_BUFFER_MANY <=
2775 peasycap->field_fill)
2776 peasycap->field_fill = 0;
2777 peasycap->field_page = 0;
2778 pfield_buffer =
2779 &peasycap->field_buffer
2780 [peasycap->field_fill]
2781 [peasycap->field_page];
2782 pfield_buffer->pto =
2783 pfield_buffer->pgo;
2785 JOM(8, "bumped to: %i=peasycap->"
2786 "field_fill %i=parity\n",
2787 peasycap->field_fill,
2788 0x00FF & pfield_buffer->kount);
2790 if (8 == more) {
2791 JOM(8, "end-of-field: received "
2792 "parity byte 0x%02X\n",
2793 (0xFF & *pu));
2794 if (0x40 & *pu)
2795 pfield_buffer->kount = 0x0000;
2796 else
2797 pfield_buffer->kount = 0x0001;
2798 pfield_buffer->input = 0x08 |
2799 (0x07 & peasycap->input);
2800 JOM(8, "end-of-field: 0x%02X=kount\n",
2801 0xFF & pfield_buffer->kount);
2804 /*---------------------------------------------------------------------------*/
2806 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
2808 /*---------------------------------------------------------------------------*/
2809 pu += leap;
2810 more -= leap;
2812 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2813 SAM("ERROR: bad peasycap->field_fill\n");
2814 return;
2816 if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
2817 SAM("ERROR: bad peasycap->field_page\n");
2818 return;
2820 pfield_buffer = &peasycap->field_buffer
2821 [peasycap->field_fill][peasycap->field_page];
2822 while (more) {
2823 pfield_buffer = &peasycap->field_buffer
2824 [peasycap->field_fill]
2825 [peasycap->field_page];
2826 if (PAGE_SIZE < (pfield_buffer->pto -
2827 pfield_buffer->pgo)) {
2828 SAM("ERROR: bad pfield_buffer->pto\n");
2829 return;
2831 if (PAGE_SIZE == (pfield_buffer->pto -
2832 pfield_buffer->pgo)) {
2833 (peasycap->field_page)++;
2834 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
2835 peasycap->field_page) {
2836 JOM(16, "wrapping peasycap->"
2837 "field_page\n");
2838 peasycap->field_page = 0;
2840 pfield_buffer = &peasycap->
2841 field_buffer
2842 [peasycap->field_fill]
2843 [peasycap->field_page];
2844 pfield_buffer->pto = pfield_buffer->pgo;
2845 pfield_buffer->input = 0x08 |
2846 (0x07 & peasycap->input);
2847 if ((peasycap->field_buffer[peasycap->
2848 field_fill][0]).
2849 input !=
2850 pfield_buffer->input)
2851 (peasycap->field_buffer
2852 [peasycap->field_fill]
2853 [0]).kount |= 0x1000;
2856 much = PAGE_SIZE -
2857 (int)(pfield_buffer->pto -
2858 pfield_buffer->pgo);
2860 if (much > more)
2861 much = more;
2862 memcpy(pfield_buffer->pto, pu, much);
2863 pu += much;
2864 (pfield_buffer->pto) += much;
2865 more -= much;
2871 /*---------------------------------------------------------------------------*/
2873 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
2875 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
2876 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2878 /*---------------------------------------------------------------------------*/
2879 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
2880 SAM("easycap driver shutting down on condition green\n");
2881 peasycap->status = 1;
2882 peasycap->video_eof = 1;
2883 peasycap->video_junk = 0;
2884 wake_up_interruptible(&peasycap->wq_video);
2885 #if !defined(PERSEVERE)
2886 peasycap->audio_eof = 1;
2887 wake_up_interruptible(&peasycap->wq_audio);
2888 #endif /*PERSEVERE*/
2889 return;
2891 if (peasycap->video_isoc_streaming) {
2892 rc = usb_submit_urb(purb, GFP_ATOMIC);
2893 if (rc) {
2894 SAM("%s: %d\n", strerror(rc), rc);
2895 if (-ENODEV != rc)
2896 SAM("ERROR: while %i=video_idle, "
2897 "usb_submit_urb() "
2898 "failed with rc:\n",
2899 peasycap->video_idle);
2902 return;
2904 static const struct file_operations easycap_fops = {
2905 .owner = THIS_MODULE,
2906 .open = easycap_open,
2907 .unlocked_ioctl = easycap_unlocked_ioctl,
2908 .poll = easycap_poll,
2909 .mmap = easycap_mmap,
2910 .llseek = no_llseek,
2912 static const struct usb_class_driver easycap_class = {
2913 .name = "usb/easycap%d",
2914 .fops = &easycap_fops,
2915 .minor_base = USB_SKEL_MINOR_BASE,
2917 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2918 static const struct v4l2_file_operations v4l2_fops = {
2919 .owner = THIS_MODULE,
2920 .open = easycap_open_noinode,
2921 .unlocked_ioctl = easycap_unlocked_ioctl,
2922 .poll = easycap_poll,
2923 .mmap = easycap_mmap,
2925 /*****************************************************************************/
2926 /*---------------------------------------------------------------------------*/
2928 * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
2929 * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
2931 /*---------------------------------------------------------------------------*/
2932 static int easycap_usb_probe(struct usb_interface *intf,
2933 const struct usb_device_id *id)
2935 struct usb_device *usbdev;
2936 struct usb_host_interface *alt;
2937 struct usb_endpoint_descriptor *ep;
2938 struct usb_interface_descriptor *interface;
2939 struct urb *purb;
2940 struct easycap *peasycap;
2941 int ndong;
2942 struct data_urb *pdata_urb;
2943 int i, j, k, m, rc;
2944 u8 bInterfaceNumber;
2945 u8 bInterfaceClass;
2946 u8 bInterfaceSubClass;
2947 void *pbuf;
2948 int okalt[8], isokalt;
2949 int okepn[8];
2950 int okmps[8];
2951 int maxpacketsize;
2952 u16 mask;
2953 s32 value;
2954 struct easycap_format *peasycap_format;
2955 int fmtidx;
2956 struct inputset *inputset;
2958 usbdev = interface_to_usbdev(intf);
2960 /*---------------------------------------------------------------------------*/
2961 alt = usb_altnum_to_altsetting(intf, 0);
2962 if (!alt) {
2963 SAY("ERROR: usb_host_interface not found\n");
2964 return -EFAULT;
2966 interface = &alt->desc;
2967 if (!interface) {
2968 SAY("ERROR: intf_descriptor is NULL\n");
2969 return -EFAULT;
2971 /*---------------------------------------------------------------------------*/
2973 * GET PROPERTIES OF PROBED INTERFACE
2975 /*---------------------------------------------------------------------------*/
2976 bInterfaceNumber = interface->bInterfaceNumber;
2977 bInterfaceClass = interface->bInterfaceClass;
2978 bInterfaceSubClass = interface->bInterfaceSubClass;
2980 JOT(4, "intf[%i]: num_altsetting=%i\n",
2981 bInterfaceNumber, intf->num_altsetting);
2982 JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
2983 bInterfaceNumber,
2984 (long int)(intf->cur_altsetting - intf->altsetting));
2985 JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
2986 bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
2987 /*---------------------------------------------------------------------------*/
2989 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
2990 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
2991 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
2992 * PHYSICALLY UNPLUGGED.
2994 * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
2995 * INTERFACES 1 AND 2 ARE PROBED.
2997 /*---------------------------------------------------------------------------*/
2998 if (0 == bInterfaceNumber) {
2999 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3000 if (!peasycap) {
3001 SAY("ERROR: Could not allocate peasycap\n");
3002 return -ENOMEM;
3004 /*---------------------------------------------------------------------------*/
3006 * PERFORM URGENT INTIALIZATIONS ...
3008 /*---------------------------------------------------------------------------*/
3009 peasycap->minor = -1;
3010 kref_init(&peasycap->kref);
3011 JOM(8, "intf[%i]: after kref_init(..._video) "
3012 "%i=peasycap->kref.refcount.counter\n",
3013 bInterfaceNumber, peasycap->kref.refcount.counter);
3015 /* module params */
3016 peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
3018 init_waitqueue_head(&peasycap->wq_video);
3019 init_waitqueue_head(&peasycap->wq_audio);
3020 init_waitqueue_head(&peasycap->wq_trigger);
3022 if (mutex_lock_interruptible(&mutex_dongle)) {
3023 SAY("ERROR: cannot down mutex_dongle\n");
3024 return -ERESTARTSYS;
3025 } else {
3026 /*---------------------------------------------------------------------------*/
3028 * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3029 * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3031 * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3032 * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3033 * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3035 /*---------------------------------------------------------------------------*/
3036 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3037 if ((!easycapdc60_dongle[ndong].peasycap) &&
3038 (!mutex_is_locked(&easycapdc60_dongle
3039 [ndong].mutex_video)) &&
3040 (!mutex_is_locked(&easycapdc60_dongle
3041 [ndong].mutex_audio))) {
3042 easycapdc60_dongle[ndong].peasycap = peasycap;
3043 peasycap->isdongle = ndong;
3044 JOM(8, "intf[%i]: peasycap-->easycap"
3045 "_dongle[%i].peasycap\n",
3046 bInterfaceNumber, ndong);
3047 break;
3050 if (DONGLE_MANY <= ndong) {
3051 SAM("ERROR: too many dongles\n");
3052 mutex_unlock(&mutex_dongle);
3053 return -ENOMEM;
3055 mutex_unlock(&mutex_dongle);
3057 peasycap->allocation_video_struct = sizeof(struct easycap);
3058 peasycap->allocation_video_page = 0;
3059 peasycap->allocation_video_urb = 0;
3060 peasycap->allocation_audio_struct = 0;
3061 peasycap->allocation_audio_page = 0;
3062 peasycap->allocation_audio_urb = 0;
3064 /*---------------------------------------------------------------------------*/
3066 * ... AND FURTHER INITIALIZE THE STRUCTURE
3068 /*---------------------------------------------------------------------------*/
3069 peasycap->pusb_device = usbdev;
3070 peasycap->pusb_interface = intf;
3072 peasycap->ilk = 0;
3073 peasycap->microphone = false;
3075 peasycap->video_interface = -1;
3076 peasycap->video_altsetting_on = -1;
3077 peasycap->video_altsetting_off = -1;
3078 peasycap->video_endpointnumber = -1;
3079 peasycap->video_isoc_maxframesize = -1;
3080 peasycap->video_isoc_buffer_size = -1;
3082 peasycap->audio_interface = -1;
3083 peasycap->audio_altsetting_on = -1;
3084 peasycap->audio_altsetting_off = -1;
3085 peasycap->audio_endpointnumber = -1;
3086 peasycap->audio_isoc_maxframesize = -1;
3087 peasycap->audio_isoc_buffer_size = -1;
3089 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3091 for (k = 0; k < INPUT_MANY; k++)
3092 peasycap->lost[k] = 0;
3093 peasycap->skip = 0;
3094 peasycap->skipped = 0;
3095 peasycap->offerfields = 0;
3096 /*---------------------------------------------------------------------------*/
3098 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3100 /*---------------------------------------------------------------------------*/
3101 rc = fillin_formats();
3102 if (0 > rc) {
3103 SAM("ERROR: fillin_formats() rc = %i\n", rc);
3104 return -EFAULT;
3106 JOM(4, "%i formats available\n", rc);
3107 /*---------------------------------------------------------------------------*/
3109 * ... AND POPULATE easycap.inputset[]
3111 /*---------------------------------------------------------------------------*/
3112 /* FIXME: maybe we just use memset 0 */
3113 inputset = peasycap->inputset;
3114 for (k = 0; k < INPUT_MANY; k++) {
3115 inputset[k].input_ok = 0;
3116 inputset[k].standard_offset_ok = 0;
3117 inputset[k].format_offset_ok = 0;
3118 inputset[k].brightness_ok = 0;
3119 inputset[k].contrast_ok = 0;
3120 inputset[k].saturation_ok = 0;
3121 inputset[k].hue_ok = 0;
3124 fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
3125 m = 0;
3126 mask = 0;
3127 for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
3128 if (fmtidx == easycap_standard[i].v4l2_standard.index) {
3129 m++;
3130 for (k = 0; k < INPUT_MANY; k++)
3131 inputset[k].standard_offset = i;
3133 mask = easycap_standard[i].mask;
3137 if (1 != m) {
3138 SAM("ERROR: "
3139 "inputset->standard_offset unpopulated, %i=m\n", m);
3140 return -ENOENT;
3143 peasycap_format = &easycap_format[0];
3144 m = 0;
3145 for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
3146 struct v4l2_pix_format *pix =
3147 &peasycap_format->v4l2_format.fmt.pix;
3148 if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3149 pix->field == V4L2_FIELD_NONE &&
3150 pix->pixelformat == V4L2_PIX_FMT_UYVY &&
3151 pix->width == 640 && pix->height == 480) {
3152 m++;
3153 for (k = 0; k < INPUT_MANY; k++)
3154 inputset[k].format_offset = i;
3155 break;
3157 peasycap_format++;
3159 if (1 != m) {
3160 SAM("ERROR: inputset[]->format_offset unpopulated\n");
3161 return -ENOENT;
3164 m = 0;
3165 for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
3166 value = easycap_control[i].default_value;
3167 if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
3168 m++;
3169 for (k = 0; k < INPUT_MANY; k++)
3170 inputset[k].brightness = value;
3171 } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
3172 m++;
3173 for (k = 0; k < INPUT_MANY; k++)
3174 inputset[k].contrast = value;
3175 } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
3176 m++;
3177 for (k = 0; k < INPUT_MANY; k++)
3178 inputset[k].saturation = value;
3179 } else if (V4L2_CID_HUE == easycap_control[i].id) {
3180 m++;
3181 for (k = 0; k < INPUT_MANY; k++)
3182 inputset[k].hue = value;
3186 if (4 != m) {
3187 SAM("ERROR: inputset[]->brightness underpopulated\n");
3188 return -ENOENT;
3190 for (k = 0; k < INPUT_MANY; k++)
3191 inputset[k].input = k;
3192 JOM(4, "populated inputset[]\n");
3193 JOM(4, "finished initialization\n");
3194 } else {
3195 /*---------------------------------------------------------------------------*/
3197 * FIXME
3199 * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3200 * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3202 /*---------------------------------------------------------------------------*/
3203 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3204 if (usbdev == easycapdc60_dongle[ndong].peasycap->
3205 pusb_device) {
3206 peasycap = easycapdc60_dongle[ndong].peasycap;
3207 JOT(8, "intf[%i]: dongle[%i].peasycap\n",
3208 bInterfaceNumber, ndong);
3209 break;
3212 if (DONGLE_MANY <= ndong) {
3213 SAY("ERROR: peasycap is unknown when probing interface %i\n",
3214 bInterfaceNumber);
3215 return -ENODEV;
3217 if (!peasycap) {
3218 SAY("ERROR: peasycap is NULL when probing interface %i\n",
3219 bInterfaceNumber);
3220 return -ENODEV;
3223 /*---------------------------------------------------------------------------*/
3224 if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3225 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3226 if (-1 == peasycap->video_interface) {
3227 peasycap->video_interface = bInterfaceNumber;
3228 JOM(4, "setting peasycap->video_interface=%i\n",
3229 peasycap->video_interface);
3230 } else {
3231 if (peasycap->video_interface != bInterfaceNumber) {
3232 SAM("ERROR: attempting to reset "
3233 "peasycap->video_interface\n");
3234 SAM("...... continuing with "
3235 "%i=peasycap->video_interface\n",
3236 peasycap->video_interface);
3239 } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3240 (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
3241 if (-1 == peasycap->audio_interface) {
3242 peasycap->audio_interface = bInterfaceNumber;
3243 JOM(4, "setting peasycap->audio_interface=%i\n",
3244 peasycap->audio_interface);
3245 } else {
3246 if (peasycap->audio_interface != bInterfaceNumber) {
3247 SAM("ERROR: attempting to reset "
3248 "peasycap->audio_interface\n");
3249 SAM("...... continuing with "
3250 "%i=peasycap->audio_interface\n",
3251 peasycap->audio_interface);
3255 /*---------------------------------------------------------------------------*/
3257 * INVESTIGATE ALL ALTSETTINGS.
3258 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3260 /*---------------------------------------------------------------------------*/
3261 isokalt = 0;
3263 for (i = 0; i < intf->num_altsetting; i++) {
3264 alt = usb_altnum_to_altsetting(intf, i);
3265 if (!alt) {
3266 SAM("ERROR: alt is NULL\n");
3267 return -EFAULT;
3269 interface = &alt->desc;
3270 if (!interface) {
3271 SAM("ERROR: intf_descriptor is NULL\n");
3272 return -EFAULT;
3275 if (0 == interface->bNumEndpoints)
3276 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3277 bInterfaceNumber, i);
3278 /*---------------------------------------------------------------------------*/
3279 for (j = 0; j < interface->bNumEndpoints; j++) {
3280 ep = &alt->endpoint[j].desc;
3281 if (!ep) {
3282 SAM("ERROR: ep is NULL.\n");
3283 SAM("...... skipping\n");
3284 continue;
3287 if (!usb_endpoint_is_isoc_in(ep)) {
3288 JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n",
3289 bInterfaceNumber,
3290 i, j, ep->bmAttributes);
3291 if (usb_endpoint_dir_out(ep)) {
3292 SAM("ERROR: OUT endpoint unexpected\n");
3293 SAM("...... continuing\n");
3295 continue;
3297 switch (bInterfaceClass) {
3298 case USB_CLASS_VIDEO:
3299 case USB_CLASS_VENDOR_SPEC: {
3300 if (ep->wMaxPacketSize) {
3301 if (8 > isokalt) {
3302 okalt[isokalt] = i;
3303 JOM(4,
3304 "%i=okalt[%i]\n",
3305 okalt[isokalt],
3306 isokalt);
3307 okepn[isokalt] =
3308 ep->
3309 bEndpointAddress &
3310 0x0F;
3311 JOM(4,
3312 "%i=okepn[%i]\n",
3313 okepn[isokalt],
3314 isokalt);
3315 okmps[isokalt] =
3316 le16_to_cpu(ep->
3317 wMaxPacketSize);
3318 JOM(4,
3319 "%i=okmps[%i]\n",
3320 okmps[isokalt],
3321 isokalt);
3322 isokalt++;
3324 } else {
3325 if (-1 == peasycap->
3326 video_altsetting_off) {
3327 peasycap->
3328 video_altsetting_off =
3330 JOM(4, "%i=video_"
3331 "altsetting_off "
3332 "<====\n",
3333 peasycap->
3334 video_altsetting_off);
3335 } else {
3336 SAM("ERROR: peasycap"
3337 "->video_altsetting_"
3338 "off already set\n");
3339 SAM("...... "
3340 "continuing with "
3341 "%i=peasycap->video_"
3342 "altsetting_off\n",
3343 peasycap->
3344 video_altsetting_off);
3347 break;
3349 case USB_CLASS_AUDIO: {
3350 if (bInterfaceSubClass !=
3351 USB_SUBCLASS_AUDIOSTREAMING)
3352 break;
3353 if (!peasycap) {
3354 SAM("MISTAKE: "
3355 "peasycap is NULL\n");
3356 return -EFAULT;
3358 if (ep->wMaxPacketSize) {
3359 if (8 > isokalt) {
3360 okalt[isokalt] = i ;
3361 JOM(4,
3362 "%i=okalt[%i]\n",
3363 okalt[isokalt],
3364 isokalt);
3365 okepn[isokalt] =
3366 ep->
3367 bEndpointAddress &
3368 0x0F;
3369 JOM(4,
3370 "%i=okepn[%i]\n",
3371 okepn[isokalt],
3372 isokalt);
3373 okmps[isokalt] =
3374 le16_to_cpu(ep->
3375 wMaxPacketSize);
3376 JOM(4,
3377 "%i=okmps[%i]\n",
3378 okmps[isokalt],
3379 isokalt);
3380 isokalt++;
3382 } else {
3383 if (-1 == peasycap->
3384 audio_altsetting_off) {
3385 peasycap->
3386 audio_altsetting_off =
3388 JOM(4, "%i=audio_"
3389 "altsetting_off "
3390 "<====\n",
3391 peasycap->
3392 audio_altsetting_off);
3393 } else {
3394 SAM("ERROR: peasycap"
3395 "->audio_altsetting_"
3396 "off already set\n");
3397 SAM("...... "
3398 "continuing with "
3399 "%i=peasycap->"
3400 "audio_altsetting_"
3401 "off\n",
3402 peasycap->
3403 audio_altsetting_off);
3406 break;
3408 default:
3409 break;
3411 if (0 == ep->wMaxPacketSize) {
3412 JOM(4, "intf[%i]alt[%i]end[%i] "
3413 "has zero packet size\n",
3414 bInterfaceNumber, i, j);
3418 /*---------------------------------------------------------------------------*/
3420 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
3422 /*---------------------------------------------------------------------------*/
3423 JOM(4, "initialization begins for interface %i\n",
3424 interface->bInterfaceNumber);
3425 switch (bInterfaceNumber) {
3426 /*---------------------------------------------------------------------------*/
3428 * INTERFACE 0 IS THE VIDEO INTERFACE
3430 /*---------------------------------------------------------------------------*/
3431 case 0: {
3432 if (!peasycap) {
3433 SAM("MISTAKE: peasycap is NULL\n");
3434 return -EFAULT;
3436 if (!isokalt) {
3437 SAM("ERROR: no viable video_altsetting_on\n");
3438 return -ENOENT;
3439 } else {
3440 peasycap->video_altsetting_on = okalt[isokalt - 1];
3441 JOM(4, "%i=video_altsetting_on <====\n",
3442 peasycap->video_altsetting_on);
3444 /*---------------------------------------------------------------------------*/
3446 * DECIDE THE VIDEO STREAMING PARAMETERS
3448 /*---------------------------------------------------------------------------*/
3449 peasycap->video_endpointnumber = okepn[isokalt - 1];
3450 JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
3451 maxpacketsize = okmps[isokalt - 1];
3453 peasycap->video_isoc_maxframesize =
3454 min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
3455 if (0 >= peasycap->video_isoc_maxframesize) {
3456 SAM("ERROR: bad video_isoc_maxframesize\n");
3457 SAM(" possibly because port is USB 1.1\n");
3458 return -ENOENT;
3460 JOM(4, "%i=video_isoc_maxframesize\n",
3461 peasycap->video_isoc_maxframesize);
3463 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
3464 JOM(4, "%i=video_isoc_framesperdesc\n",
3465 peasycap->video_isoc_framesperdesc);
3466 if (0 >= peasycap->video_isoc_framesperdesc) {
3467 SAM("ERROR: bad video_isoc_framesperdesc\n");
3468 return -ENOENT;
3470 peasycap->video_isoc_buffer_size =
3471 peasycap->video_isoc_maxframesize *
3472 peasycap->video_isoc_framesperdesc;
3473 JOM(4, "%i=video_isoc_buffer_size\n",
3474 peasycap->video_isoc_buffer_size);
3475 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
3476 peasycap->video_isoc_buffer_size) {
3477 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
3478 return -EFAULT;
3480 /*---------------------------------------------------------------------------*/
3481 if (-1 == peasycap->video_interface) {
3482 SAM("MISTAKE: video_interface is unset\n");
3483 return -EFAULT;
3485 if (-1 == peasycap->video_altsetting_on) {
3486 SAM("MISTAKE: video_altsetting_on is unset\n");
3487 return -EFAULT;
3489 if (-1 == peasycap->video_altsetting_off) {
3490 SAM("MISTAKE: video_interface_off is unset\n");
3491 return -EFAULT;
3493 if (-1 == peasycap->video_endpointnumber) {
3494 SAM("MISTAKE: video_endpointnumber is unset\n");
3495 return -EFAULT;
3497 if (-1 == peasycap->video_isoc_maxframesize) {
3498 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
3499 return -EFAULT;
3501 if (-1 == peasycap->video_isoc_buffer_size) {
3502 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
3503 return -EFAULT;
3505 /*---------------------------------------------------------------------------*/
3507 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3509 /*---------------------------------------------------------------------------*/
3510 INIT_LIST_HEAD(&(peasycap->urb_video_head));
3511 peasycap->purb_video_head = &(peasycap->urb_video_head);
3512 /*---------------------------------------------------------------------------*/
3513 JOM(4, "allocating %i frame buffers of size %li\n",
3514 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
3515 JOM(4, ".... each scattered over %li pages\n",
3516 FRAME_BUFFER_SIZE/PAGE_SIZE);
3518 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
3519 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
3520 if (peasycap->frame_buffer[k][m].pgo)
3521 SAM("attempting to reallocate frame "
3522 " buffers\n");
3523 else {
3524 pbuf = (void *)__get_free_page(GFP_KERNEL);
3525 if (!pbuf) {
3526 SAM("ERROR: Could not allocate frame "
3527 "buffer %i page %i\n", k, m);
3528 return -ENOMEM;
3529 } else
3530 peasycap->allocation_video_page += 1;
3531 peasycap->frame_buffer[k][m].pgo = pbuf;
3533 peasycap->frame_buffer[k][m].pto =
3534 peasycap->frame_buffer[k][m].pgo;
3538 peasycap->frame_fill = 0;
3539 peasycap->frame_read = 0;
3540 JOM(4, "allocation of frame buffers done: %i pages\n", k *
3542 /*---------------------------------------------------------------------------*/
3543 JOM(4, "allocating %i field buffers of size %li\n",
3544 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
3545 JOM(4, ".... each scattered over %li pages\n",
3546 FIELD_BUFFER_SIZE/PAGE_SIZE);
3548 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
3549 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
3550 if (peasycap->field_buffer[k][m].pgo) {
3551 SAM("ERROR: attempting to reallocate "
3552 "field buffers\n");
3553 } else {
3554 pbuf = (void *) __get_free_page(GFP_KERNEL);
3555 if (!pbuf) {
3556 SAM("ERROR: Could not allocate field"
3557 " buffer %i page %i\n", k, m);
3558 return -ENOMEM;
3560 else
3561 peasycap->allocation_video_page += 1;
3562 peasycap->field_buffer[k][m].pgo = pbuf;
3564 peasycap->field_buffer[k][m].pto =
3565 peasycap->field_buffer[k][m].pgo;
3567 peasycap->field_buffer[k][0].kount = 0x0200;
3569 peasycap->field_fill = 0;
3570 peasycap->field_page = 0;
3571 peasycap->field_read = 0;
3572 JOM(4, "allocation of field buffers done: %i pages\n", k *
3574 /*---------------------------------------------------------------------------*/
3575 JOM(4, "allocating %i isoc video buffers of size %i\n",
3576 VIDEO_ISOC_BUFFER_MANY,
3577 peasycap->video_isoc_buffer_size);
3578 JOM(4, ".... each occupying contiguous memory pages\n");
3580 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3581 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3582 VIDEO_ISOC_ORDER);
3583 if (!pbuf) {
3584 SAM("ERROR: Could not allocate isoc video buffer "
3585 "%i\n", k);
3586 return -ENOMEM;
3587 } else
3588 peasycap->allocation_video_page +=
3589 BIT(VIDEO_ISOC_ORDER);
3591 peasycap->video_isoc_buffer[k].pgo = pbuf;
3592 peasycap->video_isoc_buffer[k].pto =
3593 pbuf + peasycap->video_isoc_buffer_size;
3594 peasycap->video_isoc_buffer[k].kount = k;
3596 JOM(4, "allocation of isoc video buffers done: %i pages\n",
3597 k * (0x01 << VIDEO_ISOC_ORDER));
3598 /*---------------------------------------------------------------------------*/
3600 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3602 /*---------------------------------------------------------------------------*/
3603 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
3604 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
3605 peasycap->video_isoc_framesperdesc);
3606 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
3607 peasycap->video_isoc_maxframesize);
3608 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
3609 peasycap->video_isoc_buffer_size);
3611 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
3612 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
3613 GFP_KERNEL);
3614 if (!purb) {
3615 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3616 "%i\n", k);
3617 return -ENOMEM;
3618 } else
3619 peasycap->allocation_video_urb += 1;
3620 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3621 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3622 if (!pdata_urb) {
3623 SAM("ERROR: Could not allocate struct data_urb.\n");
3624 return -ENOMEM;
3625 } else
3626 peasycap->allocation_video_struct +=
3627 sizeof(struct data_urb);
3629 pdata_urb->purb = purb;
3630 pdata_urb->isbuf = k;
3631 pdata_urb->length = 0;
3632 list_add_tail(&(pdata_urb->list_head),
3633 peasycap->purb_video_head);
3634 /*---------------------------------------------------------------------------*/
3636 * ... AND INITIALIZE THEM
3638 /*---------------------------------------------------------------------------*/
3639 if (!k) {
3640 JOM(4, "initializing video urbs thus:\n");
3641 JOM(4, " purb->interval = 1;\n");
3642 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3643 JOM(4, " purb->pipe = usb_rcvisocpipe"
3644 "(peasycap->pusb_device,%i);\n",
3645 peasycap->video_endpointnumber);
3646 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3647 JOM(4, " purb->transfer_buffer = peasycap->"
3648 "video_isoc_buffer[.].pgo;\n");
3649 JOM(4, " purb->transfer_buffer_length = %i;\n",
3650 peasycap->video_isoc_buffer_size);
3651 JOM(4, " purb->complete = easycap_complete;\n");
3652 JOM(4, " purb->context = peasycap;\n");
3653 JOM(4, " purb->start_frame = 0;\n");
3654 JOM(4, " purb->number_of_packets = %i;\n",
3655 peasycap->video_isoc_framesperdesc);
3656 JOM(4, " for (j = 0; j < %i; j++)\n",
3657 peasycap->video_isoc_framesperdesc);
3658 JOM(4, " {\n");
3659 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3660 peasycap->video_isoc_maxframesize);
3661 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3662 peasycap->video_isoc_maxframesize);
3663 JOM(4, " }\n");
3666 purb->interval = 1;
3667 purb->dev = peasycap->pusb_device;
3668 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3669 peasycap->video_endpointnumber);
3670 purb->transfer_flags = URB_ISO_ASAP;
3671 purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
3672 purb->transfer_buffer_length =
3673 peasycap->video_isoc_buffer_size;
3674 purb->complete = easycap_complete;
3675 purb->context = peasycap;
3676 purb->start_frame = 0;
3677 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
3678 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
3679 purb->iso_frame_desc[j].offset = j *
3680 peasycap->video_isoc_maxframesize;
3681 purb->iso_frame_desc[j].length =
3682 peasycap->video_isoc_maxframesize;
3685 JOM(4, "allocation of %i struct urb done.\n", k);
3686 /*--------------------------------------------------------------------------*/
3688 * SAVE POINTER peasycap IN THIS INTERFACE.
3690 /*--------------------------------------------------------------------------*/
3691 usb_set_intfdata(intf, peasycap);
3692 /*---------------------------------------------------------------------------*/
3694 * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
3695 * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
3696 * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
3697 * BEWARE.
3699 /*---------------------------------------------------------------------------*/
3700 peasycap->ntsc = easycap_ntsc;
3701 JOM(8, "defaulting initially to %s\n",
3702 easycap_ntsc ? "NTSC" : "PAL");
3703 rc = reset(peasycap);
3704 if (rc) {
3705 SAM("ERROR: reset() rc = %i\n", rc);
3706 return -EFAULT;
3708 /*--------------------------------------------------------------------------*/
3710 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
3712 /*--------------------------------------------------------------------------*/
3713 if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
3714 SAM("v4l2_device_register() failed\n");
3715 return -ENODEV;
3717 JOM(4, "registered device instance: %s\n",
3718 peasycap->v4l2_device.name);
3719 /*---------------------------------------------------------------------------*/
3721 * FIXME
3724 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
3726 /*---------------------------------------------------------------------------*/
3727 peasycap->video_device.v4l2_dev = NULL;
3728 /*---------------------------------------------------------------------------*/
3731 strcpy(&peasycap->video_device.name[0], "easycapdc60");
3732 peasycap->video_device.fops = &v4l2_fops;
3733 peasycap->video_device.minor = -1;
3734 peasycap->video_device.release = (void *)(&videodev_release);
3736 video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
3738 if (0 != (video_register_device(&(peasycap->video_device),
3739 VFL_TYPE_GRABBER, -1))) {
3740 err("Not able to register with videodev");
3741 videodev_release(&(peasycap->video_device));
3742 return -ENODEV;
3743 } else {
3744 (peasycap->registered_video)++;
3745 SAM("registered with videodev: %i=minor\n",
3746 peasycap->video_device.minor);
3747 peasycap->minor = peasycap->video_device.minor;
3749 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3751 break;
3753 /*--------------------------------------------------------------------------*/
3755 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
3756 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
3758 /*--------------------------------------------------------------------------*/
3759 case 1: {
3760 if (!peasycap) {
3761 SAM("MISTAKE: peasycap is NULL\n");
3762 return -EFAULT;
3764 /*--------------------------------------------------------------------------*/
3766 * SAVE POINTER peasycap IN INTERFACE 1
3768 /*--------------------------------------------------------------------------*/
3769 usb_set_intfdata(intf, peasycap);
3770 JOM(4, "no initialization required for interface %i\n",
3771 interface->bInterfaceNumber);
3772 break;
3774 /*--------------------------------------------------------------------------*/
3775 case 2: {
3776 if (!peasycap) {
3777 SAM("MISTAKE: peasycap is NULL\n");
3778 return -EFAULT;
3780 if (!isokalt) {
3781 SAM("ERROR: no viable audio_altsetting_on\n");
3782 return -ENOENT;
3783 } else {
3784 peasycap->audio_altsetting_on = okalt[isokalt - 1];
3785 JOM(4, "%i=audio_altsetting_on <====\n",
3786 peasycap->audio_altsetting_on);
3789 peasycap->audio_endpointnumber = okepn[isokalt - 1];
3790 JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
3792 peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
3793 JOM(4, "%i=audio_isoc_maxframesize\n",
3794 peasycap->audio_isoc_maxframesize);
3795 if (0 >= peasycap->audio_isoc_maxframesize) {
3796 SAM("ERROR: bad audio_isoc_maxframesize\n");
3797 return -ENOENT;
3799 if (9 == peasycap->audio_isoc_maxframesize) {
3800 peasycap->ilk |= 0x02;
3801 SAM("audio hardware is microphone\n");
3802 peasycap->microphone = true;
3803 peasycap->audio_pages_per_fragment =
3804 PAGES_PER_AUDIO_FRAGMENT;
3805 } else if (256 == peasycap->audio_isoc_maxframesize) {
3806 peasycap->ilk &= ~0x02;
3807 SAM("audio hardware is AC'97\n");
3808 peasycap->microphone = false;
3809 peasycap->audio_pages_per_fragment =
3810 PAGES_PER_AUDIO_FRAGMENT;
3811 } else {
3812 SAM("hardware is unidentified:\n");
3813 SAM("%i=audio_isoc_maxframesize\n",
3814 peasycap->audio_isoc_maxframesize);
3815 return -ENOENT;
3818 peasycap->audio_bytes_per_fragment =
3819 peasycap->audio_pages_per_fragment * PAGE_SIZE;
3820 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
3821 peasycap->audio_pages_per_fragment);
3823 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
3824 JOM(4, "%6i=audio_pages_per_fragment\n",
3825 peasycap->audio_pages_per_fragment);
3826 JOM(4, "%6i=audio_bytes_per_fragment\n",
3827 peasycap->audio_bytes_per_fragment);
3828 JOM(4, "%6i=audio_buffer_page_many\n",
3829 peasycap->audio_buffer_page_many);
3831 peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
3833 JOM(4, "%i=audio_isoc_framesperdesc\n",
3834 peasycap->audio_isoc_framesperdesc);
3835 if (0 >= peasycap->audio_isoc_framesperdesc) {
3836 SAM("ERROR: bad audio_isoc_framesperdesc\n");
3837 return -ENOENT;
3840 peasycap->audio_isoc_buffer_size =
3841 peasycap->audio_isoc_maxframesize *
3842 peasycap->audio_isoc_framesperdesc;
3843 JOM(4, "%i=audio_isoc_buffer_size\n",
3844 peasycap->audio_isoc_buffer_size);
3845 if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
3846 SAM("MISTAKE: audio_isoc_buffer_size bigger "
3847 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
3848 AUDIO_ISOC_BUFFER_SIZE);
3849 return -EFAULT;
3851 if (-1 == peasycap->audio_interface) {
3852 SAM("MISTAKE: audio_interface is unset\n");
3853 return -EFAULT;
3855 if (-1 == peasycap->audio_altsetting_on) {
3856 SAM("MISTAKE: audio_altsetting_on is unset\n");
3857 return -EFAULT;
3859 if (-1 == peasycap->audio_altsetting_off) {
3860 SAM("MISTAKE: audio_interface_off is unset\n");
3861 return -EFAULT;
3863 if (-1 == peasycap->audio_endpointnumber) {
3864 SAM("MISTAKE: audio_endpointnumber is unset\n");
3865 return -EFAULT;
3867 if (-1 == peasycap->audio_isoc_maxframesize) {
3868 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
3869 return -EFAULT;
3871 if (-1 == peasycap->audio_isoc_buffer_size) {
3872 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
3873 return -EFAULT;
3875 /*---------------------------------------------------------------------------*/
3877 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
3879 /*---------------------------------------------------------------------------*/
3880 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
3881 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
3883 /*---------------------------------------------------------------------------*/
3884 JOM(4, "allocating %i isoc audio buffers of size %i\n",
3885 AUDIO_ISOC_BUFFER_MANY,
3886 peasycap->audio_isoc_buffer_size);
3887 JOM(4, ".... each occupying contiguous memory pages\n");
3889 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3890 pbuf = (void *)__get_free_pages(GFP_KERNEL,
3891 AUDIO_ISOC_ORDER);
3892 if (!pbuf) {
3893 SAM("ERROR: Could not allocate isoc audio buffer "
3894 "%i\n", k);
3895 return -ENOMEM;
3896 } else
3897 peasycap->allocation_audio_page +=
3898 BIT(AUDIO_ISOC_ORDER);
3900 peasycap->audio_isoc_buffer[k].pgo = pbuf;
3901 peasycap->audio_isoc_buffer[k].pto = pbuf +
3902 peasycap->audio_isoc_buffer_size;
3903 peasycap->audio_isoc_buffer[k].kount = k;
3905 JOM(4, "allocation of isoc audio buffers done.\n");
3906 /*---------------------------------------------------------------------------*/
3908 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
3910 /*---------------------------------------------------------------------------*/
3911 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
3912 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
3913 peasycap->audio_isoc_framesperdesc);
3914 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
3915 peasycap->audio_isoc_maxframesize);
3916 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
3917 peasycap->audio_isoc_buffer_size);
3919 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
3920 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
3921 GFP_KERNEL);
3922 if (!purb) {
3923 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
3924 "%i\n", k);
3925 return -ENOMEM;
3927 peasycap->allocation_audio_urb += 1 ;
3928 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3929 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
3930 if (!pdata_urb) {
3931 SAM("ERROR: Could not allocate struct data_urb.\n");
3932 return -ENOMEM;
3934 peasycap->allocation_audio_struct +=
3935 sizeof(struct data_urb);
3937 pdata_urb->purb = purb;
3938 pdata_urb->isbuf = k;
3939 pdata_urb->length = 0;
3940 list_add_tail(&(pdata_urb->list_head),
3941 peasycap->purb_audio_head);
3942 /*---------------------------------------------------------------------------*/
3944 * ... AND INITIALIZE THEM
3946 /*---------------------------------------------------------------------------*/
3947 if (!k) {
3948 JOM(4, "initializing audio urbs thus:\n");
3949 JOM(4, " purb->interval = 1;\n");
3950 JOM(4, " purb->dev = peasycap->pusb_device;\n");
3951 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
3952 "pusb_device,%i);\n",
3953 peasycap->audio_endpointnumber);
3954 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
3955 JOM(4, " purb->transfer_buffer = "
3956 "peasycap->audio_isoc_buffer[.].pgo;\n");
3957 JOM(4, " purb->transfer_buffer_length = %i;\n",
3958 peasycap->audio_isoc_buffer_size);
3959 JOM(4, " purb->complete = easycap_alsa_complete;\n");
3960 JOM(4, " purb->context = peasycap;\n");
3961 JOM(4, " purb->start_frame = 0;\n");
3962 JOM(4, " purb->number_of_packets = %i;\n",
3963 peasycap->audio_isoc_framesperdesc);
3964 JOM(4, " for (j = 0; j < %i; j++)\n",
3965 peasycap->audio_isoc_framesperdesc);
3966 JOM(4, " {\n");
3967 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
3968 peasycap->audio_isoc_maxframesize);
3969 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
3970 peasycap->audio_isoc_maxframesize);
3971 JOM(4, " }\n");
3974 purb->interval = 1;
3975 purb->dev = peasycap->pusb_device;
3976 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
3977 peasycap->audio_endpointnumber);
3978 purb->transfer_flags = URB_ISO_ASAP;
3979 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
3980 purb->transfer_buffer_length =
3981 peasycap->audio_isoc_buffer_size;
3982 purb->complete = easycap_alsa_complete;
3983 purb->context = peasycap;
3984 purb->start_frame = 0;
3985 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
3986 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
3987 purb->iso_frame_desc[j].offset = j *
3988 peasycap->audio_isoc_maxframesize;
3989 purb->iso_frame_desc[j].length =
3990 peasycap->audio_isoc_maxframesize;
3993 JOM(4, "allocation of %i struct urb done.\n", k);
3994 /*---------------------------------------------------------------------------*/
3996 * SAVE POINTER peasycap IN THIS INTERFACE.
3998 /*---------------------------------------------------------------------------*/
3999 usb_set_intfdata(intf, peasycap);
4000 /*---------------------------------------------------------------------------*/
4002 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4004 /*---------------------------------------------------------------------------*/
4005 JOM(4, "initializing ALSA card\n");
4007 rc = easycap_alsa_probe(peasycap);
4008 if (rc) {
4009 err("easycap_alsa_probe() rc = %i\n", rc);
4010 return -ENODEV;
4014 JOM(8, "kref_get() with %i=kref.refcount.counter\n",
4015 peasycap->kref.refcount.counter);
4016 kref_get(&peasycap->kref);
4017 peasycap->registered_audio++;
4018 break;
4020 /*---------------------------------------------------------------------------*/
4022 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4024 /*---------------------------------------------------------------------------*/
4025 default:
4026 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4027 return -EINVAL;
4029 SAM("ends successfully for interface %i\n", bInterfaceNumber);
4030 return 0;
4032 /*****************************************************************************/
4033 /*---------------------------------------------------------------------------*/
4035 * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4036 * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
4038 * THIS FUNCTION AFFECTS ALSA. BEWARE.
4040 /*---------------------------------------------------------------------------*/
4041 static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
4043 struct usb_host_interface *pusb_host_interface;
4044 struct usb_interface_descriptor *pusb_interface_descriptor;
4045 u8 bInterfaceNumber;
4046 struct easycap *peasycap;
4048 struct list_head *plist_head;
4049 struct data_urb *pdata_urb;
4050 int minor, m, kd;
4052 JOT(4, "\n");
4054 pusb_host_interface = pusb_interface->cur_altsetting;
4055 if (!pusb_host_interface) {
4056 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4057 return;
4059 pusb_interface_descriptor = &(pusb_host_interface->desc);
4060 if (!pusb_interface_descriptor) {
4061 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4062 return;
4064 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4065 minor = pusb_interface->minor;
4066 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4068 if (1 == bInterfaceNumber)
4069 return;
4071 peasycap = usb_get_intfdata(pusb_interface);
4072 if (!peasycap) {
4073 SAY("ERROR: peasycap is NULL\n");
4074 return;
4076 /*---------------------------------------------------------------------------*/
4078 * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
4080 /*---------------------------------------------------------------------------*/
4081 peasycap->video_eof = 1;
4082 peasycap->audio_eof = 1;
4083 wake_up_interruptible(&(peasycap->wq_video));
4084 wake_up_interruptible(&(peasycap->wq_audio));
4085 /*---------------------------------------------------------------------------*/
4086 switch (bInterfaceNumber) {
4087 case 0: {
4088 if (peasycap->purb_video_head) {
4089 JOM(4, "killing video urbs\n");
4090 m = 0;
4091 list_for_each(plist_head, peasycap->purb_video_head) {
4092 pdata_urb = list_entry(plist_head,
4093 struct data_urb, list_head);
4094 if (pdata_urb) {
4095 if (pdata_urb->purb) {
4096 usb_kill_urb(pdata_urb->purb);
4097 m++;
4101 JOM(4, "%i video urbs killed\n", m);
4103 break;
4105 /*---------------------------------------------------------------------------*/
4106 case 2: {
4107 if (peasycap->purb_audio_head) {
4108 JOM(4, "killing audio urbs\n");
4109 m = 0;
4110 list_for_each(plist_head, peasycap->purb_audio_head) {
4111 pdata_urb = list_entry(plist_head,
4112 struct data_urb, list_head);
4113 if (pdata_urb) {
4114 if (pdata_urb->purb) {
4115 usb_kill_urb(pdata_urb->purb);
4116 m++;
4120 JOM(4, "%i audio urbs killed\n", m);
4122 break;
4124 default:
4125 break;
4127 /*--------------------------------------------------------------------------*/
4129 * DEREGISTER
4131 * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4132 * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4133 * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
4135 /*--------------------------------------------------------------------------*/
4136 kd = isdongle(peasycap);
4137 switch (bInterfaceNumber) {
4138 case 0: {
4139 if (0 <= kd && DONGLE_MANY > kd) {
4140 wake_up_interruptible(&peasycap->wq_video);
4141 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4142 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4143 mutex_video)) {
4144 SAY("ERROR: "
4145 "cannot lock dongle[%i].mutex_video\n", kd);
4146 return;
4148 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4149 } else {
4150 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4152 /*---------------------------------------------------------------------------*/
4153 if (!peasycap->v4l2_device.name[0]) {
4154 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4155 if (0 <= kd && DONGLE_MANY > kd)
4156 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4157 return;
4159 v4l2_device_disconnect(&peasycap->v4l2_device);
4160 JOM(4, "v4l2_device_disconnect() OK\n");
4161 v4l2_device_unregister(&peasycap->v4l2_device);
4162 JOM(4, "v4l2_device_unregister() OK\n");
4164 video_unregister_device(&peasycap->video_device);
4165 JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
4166 bInterfaceNumber, minor);
4167 peasycap->registered_video--;
4168 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4170 if (0 <= kd && DONGLE_MANY > kd) {
4171 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4172 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4174 break;
4176 case 2: {
4177 if (0 <= kd && DONGLE_MANY > kd) {
4178 wake_up_interruptible(&peasycap->wq_audio);
4179 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4180 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4181 mutex_audio)) {
4182 SAY("ERROR: "
4183 "cannot lock dongle[%i].mutex_audio\n", kd);
4184 return;
4186 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4187 } else
4188 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4189 if (0 != snd_card_free(peasycap->psnd_card)) {
4190 SAY("ERROR: snd_card_free() failed\n");
4191 } else {
4192 peasycap->psnd_card = NULL;
4193 (peasycap->registered_audio)--;
4195 if (0 <= kd && DONGLE_MANY > kd) {
4196 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
4197 JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
4199 break;
4201 default:
4202 break;
4204 /*---------------------------------------------------------------------------*/
4206 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
4207 * (ALSO WHEN ALSA HAS BEEN IN USE)
4209 /*---------------------------------------------------------------------------*/
4210 if (!peasycap->kref.refcount.counter) {
4211 SAM("ERROR: peasycap->kref.refcount.counter is zero "
4212 "so cannot call kref_put()\n");
4213 SAM("ending unsuccessfully: may cause memory leak\n");
4214 return;
4216 if (0 <= kd && DONGLE_MANY > kd) {
4217 JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
4218 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
4219 SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
4220 SAM("ending unsuccessfully: may cause memory leak\n");
4221 return;
4223 JOM(4, "locked dongle[%i].mutex_video\n", kd);
4224 JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
4225 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
4226 SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
4227 mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
4228 JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
4229 SAM("ending unsuccessfully: may cause memory leak\n");
4230 return;
4232 JOM(4, "locked dongle[%i].mutex_audio\n", kd);
4234 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
4235 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
4236 kref_put(&peasycap->kref, easycap_delete);
4237 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
4238 if (0 <= kd && DONGLE_MANY > kd) {
4239 mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
4240 JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
4241 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4242 JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
4244 /*---------------------------------------------------------------------------*/
4245 JOM(4, "ends\n");
4246 return;
4248 /*****************************************************************************/
4250 /*---------------------------------------------------------------------------*/
4252 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
4254 /*---------------------------------------------------------------------------*/
4255 static struct usb_device_id easycap_usb_device_id_table[] = {
4256 {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
4260 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
4261 struct usb_driver easycap_usb_driver = {
4262 .name = "easycap",
4263 .id_table = easycap_usb_device_id_table,
4264 .probe = easycap_usb_probe,
4265 .disconnect = easycap_usb_disconnect,
4268 static int __init easycap_module_init(void)
4270 int k, rc;
4272 printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
4274 JOT(4, "begins. %i=debug %i=bars %i=gain\n",
4275 easycap_debug, easycap_bars, easycap_gain);
4277 mutex_init(&mutex_dongle);
4278 for (k = 0; k < DONGLE_MANY; k++) {
4279 easycapdc60_dongle[k].peasycap = NULL;
4280 mutex_init(&easycapdc60_dongle[k].mutex_video);
4281 mutex_init(&easycapdc60_dongle[k].mutex_audio);
4283 rc = usb_register(&easycap_usb_driver);
4284 if (rc)
4285 printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
4287 return rc;
4289 /*****************************************************************************/
4290 static void __exit easycap_module_exit(void)
4292 usb_deregister(&easycap_usb_driver);
4294 /*****************************************************************************/
4296 module_init(easycap_module_init);
4297 module_exit(easycap_module_exit);
4299 /*****************************************************************************/