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