staging: easycap: drop redunant backslashes from the code
[linux-2.6.git] / drivers / staging / easycap / easycap_main.c
blob34a1ba663e0be6f6f17c58c6bca18192d58d2b4e
1 /******************************************************************************
2 * *
3 * easycap_main.c *
4 * *
5 * Video driver for EasyCAP USB2.0 Video Capture Device DC60 *
6 * *
7 * *
8 ******************************************************************************/
9 /*
11 * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
14 * This is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * The software is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this software; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 /*****************************************************************************/
31 #include "easycap.h"
32 #include "easycap_main.h"
34 int easycap_debug;
35 static int easycap_bars = 1;
36 static int easycap_gain = 16;
37 module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
38 module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
39 module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
41 struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
42 static struct mutex mutex_dongle;
44 /*---------------------------------------------------------------------------*/
46 * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
48 /*---------------------------------------------------------------------------*/
49 struct usb_device_id easycap_usb_device_id_table[] = {
50 { USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID) },
51 { }
53 MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
54 struct usb_driver easycap_usb_driver = {
55 .name = "easycap",
56 .id_table = easycap_usb_device_id_table,
57 .probe = easycap_usb_probe,
58 .disconnect = easycap_usb_disconnect,
60 /*---------------------------------------------------------------------------*/
62 * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
64 * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY
65 * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253.
66 * THIS IS THE CASE FOR OpenSUSE.
68 /*---------------------------------------------------------------------------*/
69 const struct file_operations easycap_fops = {
70 .owner = THIS_MODULE,
71 .open = easycap_open,
72 .release = easycap_release,
73 #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
74 .unlocked_ioctl = easycap_ioctl_noinode,
75 #else
76 .ioctl = easycap_ioctl,
77 #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
78 .poll = easycap_poll,
79 .mmap = easycap_mmap,
80 .llseek = no_llseek,
82 struct vm_operations_struct easycap_vm_ops = {
83 .open = easycap_vma_open,
84 .close = easycap_vma_close,
85 .fault = easycap_vma_fault,
87 struct usb_class_driver easycap_class = {
88 .name = "usb/easycap%d",
89 .fops = &easycap_fops,
90 .minor_base = USB_SKEL_MINOR_BASE,
92 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
93 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
94 #if defined(EASYCAP_NEEDS_V4L2_FOPS)
95 const struct v4l2_file_operations v4l2_fops = {
96 .owner = THIS_MODULE,
97 .open = easycap_open_noinode,
98 .release = easycap_release_noinode,
99 #if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
100 .unlocked_ioctl = easycap_ioctl_noinode,
101 #else
102 .ioctl = easycap_ioctl,
103 #endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
104 .poll = easycap_poll,
105 .mmap = easycap_mmap,
107 #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
108 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
109 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
110 /****************************************************************************/
111 /*---------------------------------------------------------------------------*/
113 * THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
115 /*---------------------------------------------------------------------------*/
117 isdongle(struct easycap *peasycap)
119 int k;
120 if (NULL == peasycap)
121 return -2;
122 for (k = 0; k < DONGLE_MANY; k++) {
123 if (easycapdc60_dongle[k].peasycap == peasycap) {
124 peasycap->isdongle = k;
125 return k;
128 return -1;
130 /*****************************************************************************/
131 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
132 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
134 easycap_open_noinode(struct file *file)
136 return easycap_open((struct inode *)NULL, file);
138 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
139 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
141 easycap_open(struct inode *inode, struct file *file)
143 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
144 struct usb_interface *pusb_interface;
145 #else
146 struct video_device *pvideo_device;
147 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
148 struct easycap *peasycap;
149 int rc;
151 JOT(4, "\n");
152 SAY("==========OPEN=========\n");
154 peasycap = (struct easycap *)NULL;
155 /*---------------------------------------------------------------------------*/
156 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
157 if ((struct inode *)NULL == inode) {
158 SAY("ERROR: inode is NULL.\n");
159 return -EFAULT;
161 pusb_interface = usb_find_interface(&easycap_usb_driver, iminor(inode));
162 if (!pusb_interface) {
163 SAY("ERROR: pusb_interface is NULL.\n");
164 return -EFAULT;
166 peasycap = usb_get_intfdata(pusb_interface);
167 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
168 #else
169 pvideo_device = video_devdata(file);
170 if ((struct video_device *)NULL == pvideo_device) {
171 SAY("ERROR: pvideo_device is NULL.\n");
172 return -EFAULT;
174 peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
175 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
176 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
177 if (NULL == peasycap) {
178 SAY("ERROR: peasycap is NULL\n");
179 return -EFAULT;
181 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
182 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
183 return -EFAULT;
185 if (NULL == peasycap->pusb_device) {
186 SAM("ERROR: peasycap->pusb_device is NULL\n");
187 return -EFAULT;
188 } else {
189 JOM(16, "0x%08lX=peasycap->pusb_device\n",
190 (long int)peasycap->pusb_device);
192 file->private_data = peasycap;
193 rc = wakeup_device(peasycap->pusb_device);
194 if (0 == rc)
195 JOM(8, "wakeup_device() OK\n");
196 else {
197 SAM("ERROR: wakeup_device() returned %i\n", rc);
198 if (-ENODEV == rc)
199 SAM("ERROR: wakeup_device() returned -ENODEV\n");
200 else
201 SAM("ERROR: wakeup_device() returned %i\n", rc);
202 return rc;
204 peasycap->input = 0;
205 rc = reset(peasycap);
206 if (0 != rc) {
207 SAM("ERROR: reset() returned %i\n", rc);
208 return -EFAULT;
210 return 0;
212 /*****************************************************************************/
213 /*---------------------------------------------------------------------------*/
215 * RESET THE HARDWARE TO ITS REFERENCE STATE.
217 * THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
218 * A BAD VIDEO FRAME SIZE.
220 /*---------------------------------------------------------------------------*/
222 reset(struct easycap *peasycap)
224 struct easycap_standard const *peasycap_standard;
225 int i, rc, input, rate;
226 bool ntsc, other;
228 if (NULL == peasycap) {
229 SAY("ERROR: peasycap is NULL\n");
230 return -EFAULT;
232 input = peasycap->input;
234 /*---------------------------------------------------------------------------*/
236 * IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
237 * FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL. THIS IS ESSENTIAL FOR
238 * gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
239 * A SWITCH BETWEEN PAL AND NTSC.
241 * FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
242 * COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
244 /*---------------------------------------------------------------------------*/
245 other = false;
246 if (true == peasycap->ntsc)
247 JOM(8, "true=peasycap->ntsc\n");
248 else
249 JOM(8, "false=peasycap->ntsc\n");
250 rate = ready_saa(peasycap->pusb_device);
251 if (0 > rate) {
252 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
253 if (true == peasycap->ntsc) {
254 JOM(8, "... trying PAL ...\n"); ntsc = false;
255 } else {
256 JOM(8, "... trying NTSC ...\n"); ntsc = true;
258 rc = setup_stk(peasycap->pusb_device, ntsc);
259 if (0 == rc)
260 JOM(4, "setup_stk() OK\n");
261 else {
262 SAM("ERROR: setup_stk() returned %i\n", rc);
263 return -EFAULT;
265 rc = setup_saa(peasycap->pusb_device, ntsc);
266 if (0 == rc)
267 JOM(4, "setup_saa() OK\n");
268 else {
269 SAM("ERROR: setup_saa() returned %i\n", rc);
270 return -EFAULT;
272 rate = ready_saa(peasycap->pusb_device);
273 if (0 > rate) {
274 JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
275 JOM(8, "... saa register 0x1F has 0x%02X\n",
276 read_saa(peasycap->pusb_device, 0x1F));
277 ntsc = peasycap->ntsc;
278 } else {
279 JOM(8, "... success at second try: %i=rate\n", rate);
280 ntsc = (0 < (rate/2)) ? true : false ;
281 other = true;
283 } else {
284 JOM(8, "... success at first try: %i=rate\n", rate);
285 ntsc = (0 < rate/2) ? true : false ;
287 if (true == ntsc)
288 JOM(8, "true=ntsc\n");
289 else
290 JOM(8, "false=ntsc\n");
291 /*---------------------------------------------------------------------------*/
293 rc = setup_stk(peasycap->pusb_device, ntsc);
294 if (0 == rc)
295 JOM(4, "setup_stk() OK\n");
296 else {
297 SAM("ERROR: setup_stk() returned %i\n", rc);
298 return -EFAULT;
300 rc = setup_saa(peasycap->pusb_device, ntsc);
301 if (0 == rc)
302 JOM(4, "setup_saa() OK\n");
303 else {
304 SAM("ERROR: setup_saa() returned %i\n", rc);
305 return -EFAULT;
308 for (i = 0; i < 180; i++)
309 peasycap->merit[i] = 0;
310 peasycap->video_eof = 0;
311 peasycap->audio_eof = 0;
312 do_gettimeofday(&peasycap->timeval7);
313 /*---------------------------------------------------------------------------*/
315 * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
317 * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
319 /*---------------------------------------------------------------------------*/
320 peasycap->input = -8192;
321 peasycap->standard_offset = -8192;
322 if (true == other) {
323 peasycap_standard = &easycap_standard[0];
324 while (0xFFFF != peasycap_standard->mask) {
325 if (true == ntsc) {
326 if (NTSC_M ==
327 peasycap_standard->v4l2_standard.index) {
328 peasycap->inputset[input].standard_offset =
329 peasycap_standard -
330 &easycap_standard[0];
331 break;
333 } else {
334 if (PAL_BGHIN ==
335 peasycap_standard->v4l2_standard.index) {
336 peasycap->inputset[input].standard_offset =
337 peasycap_standard -
338 &easycap_standard[0];
339 break;
342 peasycap_standard++;
344 if (0xFFFF == peasycap_standard->mask) {
345 SAM("ERROR: standard not found\n");
346 return -EINVAL;
348 JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
349 peasycap->inputset[input].standard_offset, input);
351 peasycap->format_offset = -8192;
352 peasycap->brightness = -8192;
353 peasycap->contrast = -8192;
354 peasycap->saturation = -8192;
355 peasycap->hue = -8192;
357 rc = newinput(peasycap, input);
359 if (0 == rc)
360 JOM(4, "restored input, standard and format\n");
361 else {
362 SAM("ERROR: newinput(.,%i) returned %i\n", rc, input);
363 return -EFAULT;
365 if (true == peasycap->ntsc)
366 JOM(8, "true=peasycap->ntsc\n");
367 else
368 JOM(8, "false=peasycap->ntsc\n");
370 if (0 > peasycap->input) {
371 SAM("MISTAKE: %i=peasycap->input\n", peasycap->input);
372 return -ENOENT;
374 if (0 > peasycap->standard_offset) {
375 SAM("MISTAKE: %i=peasycap->standard_offset\n",
376 peasycap->standard_offset);
377 return -ENOENT;
379 if (0 > peasycap->format_offset) {
380 SAM("MISTAKE: %i=peasycap->format_offset\n",
381 peasycap->format_offset);
382 return -ENOENT;
384 if (0 > peasycap->brightness) {
385 SAM("MISTAKE: %i=peasycap->brightness\n", peasycap->brightness);
386 return -ENOENT;
388 if (0 > peasycap->contrast) {
389 SAM("MISTAKE: %i=peasycap->contrast\n", peasycap->contrast);
390 return -ENOENT;
392 if (0 > peasycap->saturation) {
393 SAM("MISTAKE: %i=peasycap->saturation\n", peasycap->saturation);
394 return -ENOENT;
396 if (0 > peasycap->hue) {
397 SAM("MISTAKE: %i=peasycap->hue\n", peasycap->hue);
398 return -ENOENT;
400 return 0;
402 /*****************************************************************************/
403 /*---------------------------------------------------------------------------*/
405 * IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
406 * OTHERWISE:
407 * KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
408 * _read AND _fill POINTERS.
409 * SELECT THE NEW INPUT.
410 * ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
411 * ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
412 * RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
414 * NOTE:
415 * THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
416 * SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
418 /*---------------------------------------------------------------------------*/
420 newinput(struct easycap *peasycap, int input)
422 int rc, k, m, mood, off;
423 int inputnow, video_idlenow, audio_idlenow;
424 bool resubmit;
426 if (NULL == peasycap) {
427 SAY("ERROR: peasycap is NULL\n");
428 return -EFAULT;
430 JOM(8, "%i=input sought\n", input);
432 if (0 > input && INPUT_MANY <= input)
433 return -ENOENT;
434 inputnow = peasycap->input;
435 if (input == inputnow)
436 return 0;
437 /*---------------------------------------------------------------------------*/
439 * IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
440 * STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
441 * IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
442 * ROUTINE.
444 /*---------------------------------------------------------------------------*/
445 video_idlenow = peasycap->video_idle;
446 audio_idlenow = peasycap->audio_idle;
448 peasycap->video_idle = 1;
449 peasycap->audio_idle = 1;
450 if (peasycap->video_isoc_streaming) {
451 resubmit = true;
452 kill_video_urbs(peasycap);
453 } else
454 resubmit = false;
455 /*---------------------------------------------------------------------------*/
456 if (NULL == peasycap->pusb_device) {
457 SAM("ERROR: peasycap->pusb_device is NULL\n");
458 return -ENODEV;
460 rc = usb_set_interface(peasycap->pusb_device,
461 peasycap->video_interface,
462 peasycap->video_altsetting_off);
463 if (0 != rc) {
464 SAM("ERROR: usb_set_interface() returned %i\n", rc);
465 return -EFAULT;
467 rc = stop_100(peasycap->pusb_device);
468 if (0 != rc) {
469 SAM("ERROR: stop_100() returned %i\n", rc);
470 return -EFAULT;
472 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
473 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
474 memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
476 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
477 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
478 memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
480 peasycap->field_page = 0;
481 peasycap->field_read = 0;
482 peasycap->field_fill = 0;
484 peasycap->frame_read = 0;
485 peasycap->frame_fill = 0;
486 for (k = 0; k < peasycap->input; k++) {
487 (peasycap->frame_fill)++;
488 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
489 peasycap->frame_fill = 0;
491 peasycap->input = input;
492 select_input(peasycap->pusb_device, peasycap->input, 9);
493 /*---------------------------------------------------------------------------*/
494 if (input == peasycap->inputset[input].input) {
495 off = peasycap->inputset[input].standard_offset;
496 if (off != peasycap->standard_offset) {
497 rc = adjust_standard(peasycap,
498 easycap_standard[off].v4l2_standard.id);
499 if (0 != rc) {
500 SAM("ERROR: adjust_standard() returned %i\n", rc);
501 return -EFAULT;
503 JOM(8, "%i=peasycap->standard_offset\n",
504 peasycap->standard_offset);
505 } else {
506 JOM(8, "%i=peasycap->standard_offset unchanged\n",
507 peasycap->standard_offset);
509 off = peasycap->inputset[input].format_offset;
510 if (off != peasycap->format_offset) {
511 rc = adjust_format(peasycap,
512 easycap_format[off].v4l2_format.fmt.pix.width,
513 easycap_format[off].v4l2_format.fmt.pix.height,
514 easycap_format[off].v4l2_format.fmt.pix.pixelformat,
515 easycap_format[off].v4l2_format.fmt.pix.field, false);
516 if (0 > rc) {
517 SAM("ERROR: adjust_format() returned %i\n", rc);
518 return -EFAULT;
520 JOM(8, "%i=peasycap->format_offset\n", peasycap->format_offset);
521 } else {
522 JOM(8, "%i=peasycap->format_offset unchanged\n",
523 peasycap->format_offset);
525 mood = peasycap->inputset[input].brightness;
526 if (mood != peasycap->brightness) {
527 rc = adjust_brightness(peasycap, mood);
528 if (0 != rc) {
529 SAM("ERROR: adjust_brightness returned %i\n", rc);
530 return -EFAULT;
532 JOM(8, "%i=peasycap->brightness\n", peasycap->brightness);
534 mood = peasycap->inputset[input].contrast;
535 if (mood != peasycap->contrast) {
536 rc = adjust_contrast(peasycap, mood);
537 if (0 != rc) {
538 SAM("ERROR: adjust_contrast returned %i\n", rc);
539 return -EFAULT;
541 JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
543 mood = peasycap->inputset[input].saturation;
544 if (mood != peasycap->saturation) {
545 rc = adjust_saturation(peasycap, mood);
546 if (0 != rc) {
547 SAM("ERROR: adjust_saturation returned %i\n", rc);
548 return -EFAULT;
550 JOM(8, "%i=peasycap->saturation\n", peasycap->saturation);
552 mood = peasycap->inputset[input].hue;
553 if (mood != peasycap->hue) {
554 rc = adjust_hue(peasycap, mood);
555 if (0 != rc) {
556 SAM("ERROR: adjust_hue returned %i\n", rc);
557 return -EFAULT;
559 JOM(8, "%i=peasycap->hue\n", peasycap->hue);
561 } else {
562 SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
563 return -ENOENT;
565 /*---------------------------------------------------------------------------*/
566 if (NULL == peasycap->pusb_device) {
567 SAM("ERROR: peasycap->pusb_device is NULL\n");
568 return -ENODEV;
570 rc = usb_set_interface(peasycap->pusb_device,
571 peasycap->video_interface,
572 peasycap->video_altsetting_on);
573 if (0 != rc) {
574 SAM("ERROR: usb_set_interface() returned %i\n", rc);
575 return -EFAULT;
577 rc = start_100(peasycap->pusb_device);
578 if (0 != rc) {
579 SAM("ERROR: start_100() returned %i\n", rc);
580 return -EFAULT;
582 if (true == resubmit)
583 submit_video_urbs(peasycap);
585 peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
586 peasycap->video_idle = video_idlenow;
587 peasycap->audio_idle = audio_idlenow;
588 peasycap->video_junk = 0;
590 return 0;
592 /*****************************************************************************/
594 submit_video_urbs(struct easycap *peasycap)
596 struct data_urb *pdata_urb;
597 struct urb *purb;
598 struct list_head *plist_head;
599 int j, isbad, nospc, m, rc;
600 int isbuf;
602 if (NULL == peasycap) {
603 SAY("ERROR: peasycap is NULL\n");
604 return -EFAULT;
607 if (NULL == peasycap->purb_video_head) {
608 SAY("ERROR: peasycap->urb_video_head uninitialized\n");
609 return -EFAULT;
611 if (NULL == peasycap->pusb_device) {
612 SAY("ERROR: peasycap->pusb_device is NULL\n");
613 return -ENODEV;
615 if (!peasycap->video_isoc_streaming) {
616 JOM(4, "submission of all video urbs\n");
617 isbad = 0; nospc = 0; m = 0;
618 list_for_each(plist_head, (peasycap->purb_video_head)) {
619 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
620 if (NULL != pdata_urb) {
621 purb = pdata_urb->purb;
622 if (NULL != purb) {
623 isbuf = pdata_urb->isbuf;
624 purb->interval = 1;
625 purb->dev = peasycap->pusb_device;
626 purb->pipe =
627 usb_rcvisocpipe(peasycap->pusb_device,
628 peasycap->video_endpointnumber);
629 purb->transfer_flags = URB_ISO_ASAP;
630 purb->transfer_buffer =
631 peasycap->video_isoc_buffer[isbuf].pgo;
632 purb->transfer_buffer_length =
633 peasycap->video_isoc_buffer_size;
634 purb->complete = easycap_complete;
635 purb->context = peasycap;
636 purb->start_frame = 0;
637 purb->number_of_packets =
638 peasycap->video_isoc_framesperdesc;
640 for (j = 0; j < peasycap->
641 video_isoc_framesperdesc; j++) {
642 purb->iso_frame_desc[j].
643 offset = j *
644 peasycap->
645 video_isoc_maxframesize;
646 purb->iso_frame_desc[j].
647 length = peasycap->
648 video_isoc_maxframesize;
651 rc = usb_submit_urb(purb, GFP_KERNEL);
652 if (0 != rc) {
653 isbad++;
654 SAM("ERROR: usb_submit_urb() failed "
655 "for urb with rc:\n");
656 switch (rc) {
657 case -ENOMEM: {
658 SAM("ERROR: -ENOMEM="
659 "usb_submit_urb()\n");
660 break;
662 case -ENODEV: {
663 SAM("ERROR: -ENODEV="
664 "usb_submit_urb()\n");
665 break;
667 case -ENXIO: {
668 SAM("ERROR: -ENXIO="
669 "usb_submit_urb()\n");
670 break;
672 case -EINVAL: {
673 SAM("ERROR: -EINVAL="
674 "usb_submit_urb()\n");
675 break;
677 case -EAGAIN: {
678 SAM("ERROR: -EAGAIN="
679 "usb_submit_urb()\n");
680 break;
682 case -EFBIG: {
683 SAM("ERROR: -EFBIG="
684 "usb_submit_urb()\n");
685 break;
687 case -EPIPE: {
688 SAM("ERROR: -EPIPE="
689 "usb_submit_urb()\n");
690 break;
692 case -EMSGSIZE: {
693 SAM("ERROR: -EMSGSIZE="
694 "usb_submit_urb()\n");
695 break;
697 case -ENOSPC: {
698 nospc++;
699 break;
701 default: {
702 SAM("ERROR: %i="
703 "usb_submit_urb()\n",
704 rc);
705 break;
708 } else {
709 m++;
711 } else {
712 isbad++;
714 } else {
715 isbad++;
718 if (nospc) {
719 SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
720 SAM("..... possibly inadequate USB bandwidth\n");
721 peasycap->video_eof = 1;
724 if (isbad) {
725 JOM(4, "attempting cleanup instead of submitting\n");
726 list_for_each(plist_head, (peasycap->purb_video_head)) {
727 pdata_urb = list_entry(plist_head, struct data_urb,
728 list_head);
729 if (NULL != pdata_urb) {
730 purb = pdata_urb->purb;
731 if (NULL != purb)
732 usb_kill_urb(purb);
735 peasycap->video_isoc_streaming = 0;
736 } else {
737 peasycap->video_isoc_streaming = 1;
738 JOM(4, "submitted %i video urbs\n", m);
740 } else {
741 JOM(4, "already streaming video urbs\n");
743 return 0;
745 /*****************************************************************************/
747 kill_video_urbs(struct easycap *peasycap)
749 int m;
750 struct list_head *plist_head;
751 struct data_urb *pdata_urb;
753 if (NULL == peasycap) {
754 SAY("ERROR: peasycap is NULL\n");
755 return -EFAULT;
757 if (peasycap->video_isoc_streaming) {
758 if ((struct list_head *)NULL != peasycap->purb_video_head) {
759 peasycap->video_isoc_streaming = 0;
760 JOM(4, "killing video urbs\n");
761 m = 0;
762 list_for_each(plist_head, (peasycap->purb_video_head)) {
763 pdata_urb = list_entry(plist_head, struct data_urb,
764 list_head);
765 if (NULL != pdata_urb) {
766 if (NULL != pdata_urb->purb) {
767 usb_kill_urb(pdata_urb->purb);
768 m++;
772 JOM(4, "%i video urbs killed\n", m);
773 } else {
774 SAM("ERROR: peasycap->purb_video_head is NULL\n");
775 return -EFAULT;
777 } else {
778 JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
779 peasycap->video_isoc_streaming);
781 return 0;
783 /****************************************************************************/
784 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
785 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
787 easycap_release_noinode(struct file *file)
789 return easycap_release((struct inode *)NULL, file);
791 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
792 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
793 /*--------------------------------------------------------------------------*/
795 easycap_release(struct inode *inode, struct file *file)
797 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
798 struct easycap *peasycap;
800 JOT(4, "\n");
802 peasycap = file->private_data;
803 if (NULL == peasycap) {
804 SAY("ERROR: peasycap is NULL.\n");
805 SAY("ending unsuccessfully\n");
806 return -EFAULT;
808 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
809 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
810 return -EFAULT;
812 if (0 != kill_video_urbs(peasycap)) {
813 SAM("ERROR: kill_video_urbs() failed\n");
814 return -EFAULT;
816 JOM(4, "ending successfully\n");
817 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
818 #else
820 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
821 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
823 return 0;
825 /****************************************************************************/
826 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
827 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
829 videodev_release(struct video_device *pvideo_device)
831 struct easycap *peasycap;
833 JOT(4, "\n");
835 peasycap = video_get_drvdata(pvideo_device);
836 if (NULL == peasycap) {
837 SAY("ERROR: peasycap is NULL\n");
838 SAY("ending unsuccessfully\n");
839 return -EFAULT;
841 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
842 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
843 return -EFAULT;
845 if (0 != kill_video_urbs(peasycap)) {
846 SAM("ERROR: kill_video_urbs() failed\n");
847 return -EFAULT;
849 JOM(4, "ending successfully\n");
850 return 0;
852 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
853 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
854 /*****************************************************************************/
855 /*--------------------------------------------------------------------------*/
857 * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect() AND IS
858 * PROTECTED BY SEMAPHORES SET AND CLEARED BY easycap_usb_disconnect().
860 * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED, SO
861 * peasycap->pusb_device IS NO LONGER VALID.
863 /*---------------------------------------------------------------------------*/
864 void
865 easycap_delete(struct kref *pkref)
867 int k, m, gone, kd;
868 int allocation_video_urb, allocation_video_page, allocation_video_struct;
869 int allocation_audio_urb, allocation_audio_page, allocation_audio_struct;
870 int registered_video, registered_audio;
871 struct easycap *peasycap;
872 struct data_urb *pdata_urb;
873 struct list_head *plist_head, *plist_next;
875 JOT(4, "\n");
877 peasycap = container_of(pkref, struct easycap, kref);
878 if (NULL == peasycap) {
879 SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
880 return;
882 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
883 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
884 return;
886 kd = isdongle(peasycap);
887 /*---------------------------------------------------------------------------*/
889 * FREE VIDEO.
891 /*---------------------------------------------------------------------------*/
892 if ((struct list_head *)NULL != peasycap->purb_video_head) {
893 JOM(4, "freeing video urbs\n");
894 m = 0;
895 list_for_each(plist_head, (peasycap->purb_video_head)) {
896 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
897 if (NULL == pdata_urb)
898 JOM(4, "ERROR: pdata_urb is NULL\n");
899 else {
900 if ((struct urb *)NULL != pdata_urb->purb) {
901 usb_free_urb(pdata_urb->purb);
902 pdata_urb->purb = (struct urb *)NULL;
903 peasycap->allocation_video_urb -= 1;
904 m++;
909 JOM(4, "%i video urbs freed\n", m);
910 /*---------------------------------------------------------------------------*/
911 JOM(4, "freeing video data_urb structures.\n");
912 m = 0;
913 list_for_each_safe(plist_head, plist_next, peasycap->purb_video_head) {
914 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
915 if ((struct data_urb *)NULL != pdata_urb) {
916 kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL;
917 peasycap->allocation_video_struct -=
918 sizeof(struct data_urb);
919 m++;
922 JOM(4, "%i video data_urb structures freed\n", m);
923 JOM(4, "setting peasycap->purb_video_head=NULL\n");
924 peasycap->purb_video_head = (struct list_head *)NULL;
926 /*---------------------------------------------------------------------------*/
927 JOM(4, "freeing video isoc buffers.\n");
928 m = 0;
929 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
930 if ((void *)NULL != peasycap->video_isoc_buffer[k].pgo) {
931 free_pages((unsigned long)
932 (peasycap->video_isoc_buffer[k].pgo),
933 VIDEO_ISOC_ORDER);
934 peasycap->video_isoc_buffer[k].pgo = (void *)NULL;
935 peasycap->allocation_video_page -=
936 ((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
937 m++;
940 JOM(4, "isoc video buffers freed: %i pages\n", m * (0x01 << VIDEO_ISOC_ORDER));
941 /*---------------------------------------------------------------------------*/
942 JOM(4, "freeing video field buffers.\n");
943 gone = 0;
944 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
945 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
946 if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
947 free_page((unsigned long)
948 (peasycap->field_buffer[k][m].pgo));
949 peasycap->field_buffer[k][m].pgo = (void *)NULL;
950 peasycap->allocation_video_page -= 1;
951 gone++;
955 JOM(4, "video field buffers freed: %i pages\n", gone);
956 /*---------------------------------------------------------------------------*/
957 JOM(4, "freeing video frame buffers.\n");
958 gone = 0;
959 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
960 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
961 if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) {
962 free_page((unsigned long)
963 (peasycap->frame_buffer[k][m].pgo));
964 peasycap->frame_buffer[k][m].pgo = (void *)NULL;
965 peasycap->allocation_video_page -= 1;
966 gone++;
970 JOM(4, "video frame buffers freed: %i pages\n", gone);
971 /*---------------------------------------------------------------------------*/
973 * FREE AUDIO.
975 /*---------------------------------------------------------------------------*/
976 if ((struct list_head *)NULL != peasycap->purb_audio_head) {
977 JOM(4, "freeing audio urbs\n");
978 m = 0;
979 list_for_each(plist_head, (peasycap->purb_audio_head)) {
980 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
981 if (NULL == pdata_urb)
982 JOM(4, "ERROR: pdata_urb is NULL\n");
983 else {
984 if ((struct urb *)NULL != pdata_urb->purb) {
985 usb_free_urb(pdata_urb->purb);
986 pdata_urb->purb = (struct urb *)NULL;
987 peasycap->allocation_audio_urb -= 1;
988 m++;
992 JOM(4, "%i audio urbs freed\n", m);
993 /*---------------------------------------------------------------------------*/
994 JOM(4, "freeing audio data_urb structures.\n");
995 m = 0;
996 list_for_each_safe(plist_head, plist_next, peasycap->purb_audio_head) {
997 pdata_urb = list_entry(plist_head, struct data_urb, list_head);
998 if ((struct data_urb *)NULL != pdata_urb) {
999 kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL;
1000 peasycap->allocation_audio_struct -=
1001 sizeof(struct data_urb);
1002 m++;
1005 JOM(4, "%i audio data_urb structures freed\n", m);
1006 JOM(4, "setting peasycap->purb_audio_head=NULL\n");
1007 peasycap->purb_audio_head = (struct list_head *)NULL;
1009 /*---------------------------------------------------------------------------*/
1010 JOM(4, "freeing audio isoc buffers.\n");
1011 m = 0;
1012 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
1013 if ((void *)NULL != peasycap->audio_isoc_buffer[k].pgo) {
1014 free_pages((unsigned long)
1015 (peasycap->audio_isoc_buffer[k].pgo),
1016 AUDIO_ISOC_ORDER);
1017 peasycap->audio_isoc_buffer[k].pgo = (void *)NULL;
1018 peasycap->allocation_audio_page -=
1019 ((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
1020 m++;
1023 JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
1024 m * (0x01 << AUDIO_ISOC_ORDER));
1025 /*---------------------------------------------------------------------------*/
1026 #if !defined(EASYCAP_NEEDS_ALSA)
1027 JOM(4, "freeing audio buffers.\n");
1028 gone = 0;
1029 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
1030 if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
1031 free_page((unsigned long)(peasycap->audio_buffer[k].pgo));
1032 peasycap->audio_buffer[k].pgo = (void *)NULL;
1033 peasycap->allocation_audio_page -= 1;
1034 gone++;
1037 JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
1038 #endif /*!EASYCAP_NEEDS_ALSA*/
1039 /*---------------------------------------------------------------------------*/
1040 JOM(4, "freeing easycap structure.\n");
1041 allocation_video_urb = peasycap->allocation_video_urb;
1042 allocation_video_page = peasycap->allocation_video_page;
1043 allocation_video_struct = peasycap->allocation_video_struct;
1044 registered_video = peasycap->registered_video;
1045 allocation_audio_urb = peasycap->allocation_audio_urb;
1046 allocation_audio_page = peasycap->allocation_audio_page;
1047 allocation_audio_struct = peasycap->allocation_audio_struct;
1048 registered_audio = peasycap->registered_audio;
1050 kfree(peasycap);
1052 if (0 <= kd && DONGLE_MANY > kd) {
1053 if (mutex_lock_interruptible(&mutex_dongle)) {
1054 SAY("ERROR: cannot down mutex_dongle\n");
1055 } else {
1056 JOM(4, "locked mutex_dongle\n");
1057 easycapdc60_dongle[kd].peasycap = (struct easycap *)NULL;
1058 mutex_unlock(&mutex_dongle);
1059 JOM(4, "unlocked mutex_dongle\n");
1060 JOT(4, " null-->easycapdc60_dongle[%i].peasycap\n", kd);
1061 allocation_video_struct -= sizeof(struct easycap);
1063 } else {
1064 SAY("ERROR: cannot purge easycapdc60_dongle[].peasycap");
1066 /*---------------------------------------------------------------------------*/
1067 SAY("%8i= video urbs after all deletions\n", allocation_video_urb);
1068 SAY("%8i= video pages after all deletions\n", allocation_video_page);
1069 SAY("%8i= video structs after all deletions\n", allocation_video_struct);
1070 SAY("%8i= video devices after all deletions\n", registered_video);
1071 SAY("%8i= audio urbs after all deletions\n", allocation_audio_urb);
1072 SAY("%8i= audio pages after all deletions\n", allocation_audio_page);
1073 SAY("%8i= audio structs after all deletions\n", allocation_audio_struct);
1074 SAY("%8i= audio devices after all deletions\n", registered_audio);
1076 JOT(4, "ending.\n");
1077 return;
1079 /*****************************************************************************/
1080 unsigned int easycap_poll(struct file *file, poll_table *wait)
1082 struct easycap *peasycap;
1083 int rc, kd;
1085 JOT(8, "\n");
1087 if (NULL == ((poll_table *)wait))
1088 JOT(8, "WARNING: poll table pointer is NULL ... continuing\n");
1089 if ((struct file *)NULL == file) {
1090 SAY("ERROR: file pointer is NULL\n");
1091 return -ERESTARTSYS;
1093 peasycap = file->private_data;
1094 if (NULL == peasycap) {
1095 SAY("ERROR: peasycap is NULL\n");
1096 return -EFAULT;
1098 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1099 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
1100 return -EFAULT;
1102 if (NULL == peasycap->pusb_device) {
1103 SAY("ERROR: peasycap->pusb_device is NULL\n");
1104 return -EFAULT;
1106 /*---------------------------------------------------------------------------*/
1107 kd = isdongle(peasycap);
1108 if (0 <= kd && DONGLE_MANY > kd) {
1109 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
1110 SAY("ERROR: cannot down "
1111 "easycapdc60_dongle[%i].mutex_video\n", kd);
1112 return -ERESTARTSYS;
1114 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
1115 /*-------------------------------------------------------------------*/
1117 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
1118 * peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1119 * IF NECESSARY, BAIL OUT.
1121 /*-------------------------------------------------------------------*/
1122 if (kd != isdongle(peasycap))
1123 return -ERESTARTSYS;
1124 if (NULL == file) {
1125 SAY("ERROR: file is NULL\n");
1126 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1127 return -ERESTARTSYS;
1129 peasycap = file->private_data;
1130 if (NULL == peasycap) {
1131 SAY("ERROR: peasycap is NULL\n");
1132 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1133 return -ERESTARTSYS;
1135 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1136 SAY("ERROR: bad peasycap: 0x%08lX\n",
1137 (unsigned long int) peasycap);
1138 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1139 return -ERESTARTSYS;
1141 if (NULL == peasycap->pusb_device) {
1142 SAM("ERROR: peasycap->pusb_device is NULL\n");
1143 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1144 return -ERESTARTSYS;
1146 } else
1147 /*-------------------------------------------------------------------*/
1149 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
1150 * BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
1151 * HAVE FAILED. BAIL OUT.
1153 /*-------------------------------------------------------------------*/
1154 return -ERESTARTSYS;
1155 /*---------------------------------------------------------------------------*/
1156 rc = easycap_dqbuf(peasycap, 0);
1157 peasycap->polled = 1;
1158 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
1159 if (0 == rc)
1160 return POLLIN | POLLRDNORM;
1161 else
1162 return POLLERR;
1164 /*****************************************************************************/
1165 /*---------------------------------------------------------------------------*/
1167 * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
1169 /*---------------------------------------------------------------------------*/
1171 easycap_dqbuf(struct easycap *peasycap, int mode)
1173 int input, ifield, miss, rc;
1175 JOT(8, "\n");
1177 if (NULL == peasycap) {
1178 SAY("ERROR: peasycap is NULL\n");
1179 return -EFAULT;
1181 if (NULL == peasycap->pusb_device) {
1182 SAY("ERROR: peasycap->pusb_device is NULL\n");
1183 return -EFAULT;
1185 ifield = 0;
1186 JOM(8, "%i=ifield\n", ifield);
1187 /*---------------------------------------------------------------------------*/
1189 * CHECK FOR LOST INPUT SIGNAL.
1191 * FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
1192 * IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
1193 * RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
1194 * IS FLYWHEELING ON INPUT 0. THE UPSHOT IS:
1196 * INPUT 0 PLUGGED, INPUT 4 PLUGGED => SCREEN 0 OK, SCREEN 4 OK
1197 * INPUT 0 PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK, SCREEN 4 BLACK
1198 * INPUT 0 UNPLUGGED, INPUT 4 PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
1199 * INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
1201 /*---------------------------------------------------------------------------*/
1202 input = peasycap->input;
1203 if (0 <= input && INPUT_MANY > input) {
1204 rc = read_saa(peasycap->pusb_device, 0x1F);
1205 if (0 <= rc) {
1206 if (rc & 0x40)
1207 peasycap->lost[input] += 1;
1208 else
1209 peasycap->lost[input] -= 2;
1211 if (0 > peasycap->lost[input])
1212 peasycap->lost[input] = 0;
1213 else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
1214 peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
1217 /*---------------------------------------------------------------------------*/
1219 * WAIT FOR FIELD ifield (0 => TOP, 1 => BOTTOM)
1221 /*---------------------------------------------------------------------------*/
1222 miss = 0;
1223 while ((peasycap->field_read == peasycap->field_fill) ||
1224 (0 != (0xFF00 & peasycap->field_buffer
1225 [peasycap->field_read][0].kount)) ||
1226 (ifield != (0x00FF & peasycap->field_buffer
1227 [peasycap->field_read][0].kount))) {
1228 if (mode)
1229 return -EAGAIN;
1231 JOM(8, "first wait on wq_video, "
1232 "%i=field_read %i=field_fill\n",
1233 peasycap->field_read, peasycap->field_fill);
1235 if (0 != (wait_event_interruptible(peasycap->wq_video,
1236 (peasycap->video_idle || peasycap->video_eof ||
1237 ((peasycap->field_read != peasycap->field_fill) &&
1238 (0 == (0xFF00 & peasycap->field_buffer
1239 [peasycap->field_read][0].kount)) &&
1240 (ifield == (0x00FF & peasycap->field_buffer
1241 [peasycap->field_read][0].kount))))))) {
1242 SAM("aborted by signal\n");
1243 return -EIO;
1245 if (peasycap->video_idle) {
1246 JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n",
1247 peasycap->video_idle);
1248 return -EAGAIN;
1250 if (peasycap->video_eof) {
1251 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1252 #if defined(PERSEVERE)
1253 if (1 == peasycap->status) {
1254 JOM(8, "persevering ...\n");
1255 peasycap->video_eof = 0;
1256 peasycap->audio_eof = 0;
1257 if (0 != reset(peasycap)) {
1258 JOM(8, " ... failed ... returning -EIO\n");
1259 peasycap->video_eof = 1;
1260 peasycap->audio_eof = 1;
1261 kill_video_urbs(peasycap);
1262 return -EIO;
1264 peasycap->status = 0;
1265 JOM(8, " ... OK ... returning -EAGAIN\n");
1266 return -EAGAIN;
1268 #endif /*PERSEVERE*/
1269 peasycap->video_eof = 1;
1270 peasycap->audio_eof = 1;
1271 kill_video_urbs(peasycap);
1272 JOM(8, "returning -EIO\n");
1273 return -EIO;
1275 miss++;
1277 JOM(8, "first awakening on wq_video after %i waits\n", miss);
1279 rc = field2frame(peasycap);
1280 if (0 != rc)
1281 SAM("ERROR: field2frame() returned %i\n", rc);
1282 /*---------------------------------------------------------------------------*/
1284 * WAIT FOR THE OTHER FIELD
1286 /*---------------------------------------------------------------------------*/
1287 if (ifield)
1288 ifield = 0;
1289 else
1290 ifield = 1;
1291 miss = 0;
1292 while ((peasycap->field_read == peasycap->field_fill) ||
1293 (0 != (0xFF00 & peasycap->field_buffer
1294 [peasycap->field_read][0].kount)) ||
1295 (ifield != (0x00FF & peasycap->field_buffer
1296 [peasycap->field_read][0].kount))) {
1297 if (mode)
1298 return -EAGAIN;
1300 JOM(8, "second wait on wq_video, "
1301 "%i=field_read %i=field_fill\n",
1302 peasycap->field_read, peasycap->field_fill);
1303 if (0 != (wait_event_interruptible(peasycap->wq_video,
1304 (peasycap->video_idle || peasycap->video_eof ||
1305 ((peasycap->field_read != peasycap->field_fill) &&
1306 (0 == (0xFF00 & peasycap->field_buffer
1307 [peasycap->field_read][0].kount)) &&
1308 (ifield == (0x00FF & peasycap->field_buffer
1309 [peasycap->field_read][0].
1310 kount))))))) {
1311 SAM("aborted by signal\n");
1312 return -EIO;
1314 if (peasycap->video_idle) {
1315 JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n",
1316 peasycap->video_idle);
1317 return -EAGAIN;
1319 if (peasycap->video_eof) {
1320 JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
1321 #if defined(PERSEVERE)
1322 if (1 == peasycap->status) {
1323 JOM(8, "persevering ...\n");
1324 peasycap->video_eof = 0;
1325 peasycap->audio_eof = 0;
1326 if (0 != reset(peasycap)) {
1327 JOM(8, " ... failed ... returning -EIO\n");
1328 peasycap->video_eof = 1;
1329 peasycap->audio_eof = 1;
1330 kill_video_urbs(peasycap);
1331 return -EIO;
1333 peasycap->status = 0;
1334 JOM(8, " ... OK ... returning -EAGAIN\n");
1335 return -EAGAIN;
1337 #endif /*PERSEVERE*/
1338 peasycap->video_eof = 1;
1339 peasycap->audio_eof = 1;
1340 kill_video_urbs(peasycap);
1341 JOM(8, "returning -EIO\n");
1342 return -EIO;
1344 miss++;
1346 JOM(8, "second awakening on wq_video after %i waits\n", miss);
1348 rc = field2frame(peasycap);
1349 if (0 != rc)
1350 SAM("ERROR: field2frame() returned %i\n", rc);
1351 /*---------------------------------------------------------------------------*/
1353 * WASTE THIS FRAME
1355 /*---------------------------------------------------------------------------*/
1356 if (0 != peasycap->skip) {
1357 peasycap->skipped++;
1358 if (peasycap->skip != peasycap->skipped)
1359 return peasycap->skip - peasycap->skipped;
1360 peasycap->skipped = 0;
1362 /*---------------------------------------------------------------------------*/
1363 peasycap->frame_read = peasycap->frame_fill;
1364 peasycap->queued[peasycap->frame_read] = 0;
1365 peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE;
1367 (peasycap->frame_fill)++;
1368 if (peasycap->frame_buffer_many <= peasycap->frame_fill)
1369 peasycap->frame_fill = 0;
1371 if (0x01 & easycap_standard[peasycap->standard_offset].mask) {
1372 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1373 V4L2_FIELD_TOP;
1374 } else {
1375 peasycap->frame_buffer[peasycap->frame_read][0].kount =
1376 V4L2_FIELD_BOTTOM;
1379 JOM(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read);
1380 JOM(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill);
1382 return 0;
1384 /*****************************************************************************/
1385 /*---------------------------------------------------------------------------*/
1387 * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
1388 * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
1390 * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
1391 * odd==false IS TRANSFERRED TO THE FRAME BUFFER.
1393 * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM
1394 * CHOOSES THE OPTION V4L2_FIELD_INTERLACED.
1396 /*---------------------------------------------------------------------------*/
1398 field2frame(struct easycap *peasycap)
1400 struct timeval timeval;
1401 long long int above, below;
1402 __u32 remainder;
1403 struct signed_div_result sdr;
1405 void *pex, *pad;
1406 int kex, kad, mex, mad, rex, rad, rad2;
1407 int c2, c3, w2, w3, cz, wz;
1408 int rc, bytesperpixel, multiplier, much, more, over, rump, caches, input;
1409 __u8 mask, margin;
1410 bool odd, isuy, decimatepixel, offerfields, badinput;
1412 if (NULL == peasycap) {
1413 SAY("ERROR: peasycap is NULL\n");
1414 return -EFAULT;
1417 badinput = false;
1418 input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
1420 JOM(8, "===== parity %i, input 0x%02X, field buffer %i --> "
1421 "frame buffer %i\n",
1422 peasycap->field_buffer[peasycap->field_read][0].kount,
1423 peasycap->field_buffer[peasycap->field_read][0].input,
1424 peasycap->field_read, peasycap->frame_fill);
1425 JOM(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel);
1426 if (true == peasycap->offerfields)
1427 JOM(8, "===== offerfields\n");
1429 /*---------------------------------------------------------------------------*/
1431 * REJECT OR CLEAN BAD FIELDS
1433 /*---------------------------------------------------------------------------*/
1434 if (peasycap->field_read == peasycap->field_fill) {
1435 SAM("ERROR: on entry, still filling field buffer %i\n",
1436 peasycap->field_read);
1437 return 0;
1439 #if defined(EASYCAP_TESTCARD)
1440 easycap_testcard(peasycap, peasycap->field_read);
1441 #else
1442 if (0 <= input && INPUT_MANY > input) {
1443 if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
1444 easycap_testcard(peasycap, peasycap->field_read);
1446 #endif /*EASYCAP_TESTCARD*/
1447 /*---------------------------------------------------------------------------*/
1449 offerfields = peasycap->offerfields;
1450 bytesperpixel = peasycap->bytesperpixel;
1451 decimatepixel = peasycap->decimatepixel;
1453 if ((2 != bytesperpixel) &&
1454 (3 != bytesperpixel) &&
1455 (4 != bytesperpixel)) {
1456 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
1457 return -EFAULT;
1459 if (true == decimatepixel)
1460 multiplier = 2;
1461 else
1462 multiplier = 1;
1464 w2 = 2 * multiplier * (peasycap->width);
1465 w3 = bytesperpixel *
1466 multiplier *
1467 (peasycap->width);
1468 wz = multiplier *
1469 (peasycap->height) *
1470 multiplier *
1471 (peasycap->width);
1473 kex = peasycap->field_read; mex = 0;
1474 kad = peasycap->frame_fill; mad = 0;
1476 pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE;
1477 pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE;
1478 if (peasycap->field_buffer[kex][0].kount)
1479 odd = true;
1480 else
1481 odd = false;
1483 if ((true == odd) && (false == decimatepixel)) {
1484 JOM(8, " initial skipping %4i bytes p.%4i\n",
1485 w3/multiplier, mad);
1486 pad += (w3 / multiplier); rad -= (w3 / multiplier);
1488 isuy = true;
1489 mask = 0; rump = 0; caches = 0;
1491 cz = 0;
1492 while (cz < wz) {
1493 /*-------------------------------------------------------------------*/
1495 ** PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
1496 ** READ w2 BYTES FROM FIELD BUFFER,
1497 ** WRITE w3 BYTES TO FRAME BUFFER
1499 /*-------------------------------------------------------------------*/
1500 if (false == decimatepixel) {
1501 over = w2;
1502 do {
1503 much = over; more = 0; margin = 0; mask = 0x00;
1504 if (rex < much)
1505 much = rex;
1506 rump = 0;
1508 if (much % 2) {
1509 SAM("MISTAKE: much is odd\n");
1510 return -EFAULT;
1513 more = (bytesperpixel *
1514 much) / 2;
1515 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1516 if (1 < bytesperpixel) {
1517 if (rad * 2 < much * bytesperpixel) {
1519 ** INJUDICIOUS ALTERATION OF THIS
1520 ** STATEMENT BLOCK WILL CAUSE
1521 ** BREAKAGE. BEWARE.
1523 rad2 = rad + bytesperpixel - 1;
1524 much = ((((2 *
1525 rad2)/bytesperpixel)/2) * 2);
1526 rump = ((bytesperpixel *
1527 much) / 2) - rad;
1528 more = rad;
1530 mask = (__u8)rump;
1531 margin = 0;
1532 if (much == rex) {
1533 mask |= 0x04;
1534 if ((mex + 1) < FIELD_BUFFER_SIZE/
1535 PAGE_SIZE) {
1536 margin = *((__u8 *)(peasycap->
1537 field_buffer
1538 [kex][mex + 1].pgo));
1539 } else
1540 mask |= 0x08;
1542 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1543 } else {
1544 SAM("MISTAKE: %i=bytesperpixel\n",
1545 bytesperpixel);
1546 return -EFAULT;
1548 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1549 if (rump)
1550 caches++;
1551 if (true == badinput) {
1552 JOM(8, "ERROR: 0x%02X=->field_buffer"
1553 "[%i][%i].input, "
1554 "0x%02X=(0x08|->input)\n",
1555 peasycap->field_buffer
1556 [kex][mex].input, kex, mex,
1557 (0x08|peasycap->input));
1559 rc = redaub(peasycap, pad, pex, much, more,
1560 mask, margin, isuy);
1561 if (0 > rc) {
1562 SAM("ERROR: redaub() failed\n");
1563 return -EFAULT;
1565 if (much % 4) {
1566 if (isuy)
1567 isuy = false;
1568 else
1569 isuy = true;
1571 over -= much; cz += much;
1572 pex += much; rex -= much;
1573 if (!rex) {
1574 mex++;
1575 pex = peasycap->field_buffer[kex][mex].pgo;
1576 rex = PAGE_SIZE;
1577 if (peasycap->field_buffer[kex][mex].input !=
1578 (0x08|peasycap->input))
1579 badinput = true;
1581 pad += more;
1582 rad -= more;
1583 if (!rad) {
1584 mad++;
1585 pad = peasycap->frame_buffer[kad][mad].pgo;
1586 rad = PAGE_SIZE;
1587 if (rump) {
1588 pad += rump;
1589 rad -= rump;
1592 } while (over);
1593 /*---------------------------------------------------------------------------*/
1595 * SKIP w3 BYTES IN TARGET FRAME BUFFER,
1596 * UNLESS IT IS THE LAST LINE OF AN ODD FRAME
1598 /*---------------------------------------------------------------------------*/
1599 if ((false == odd) || (cz != wz)) {
1600 over = w3;
1601 do {
1602 if (!rad) {
1603 mad++;
1604 pad = peasycap->frame_buffer
1605 [kad][mad].pgo;
1606 rad = PAGE_SIZE;
1608 more = over;
1609 if (rad < more)
1610 more = rad;
1611 over -= more;
1612 pad += more;
1613 rad -= more;
1614 } while (over);
1616 /*---------------------------------------------------------------------------*/
1618 * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
1619 * ONLY IF false==odd,
1620 * READ w2 BYTES FROM FIELD BUFFER,
1621 * WRITE w3 / 2 BYTES TO FRAME BUFFER
1623 /*---------------------------------------------------------------------------*/
1624 } else if (false == odd) {
1625 over = w2;
1626 do {
1627 much = over; more = 0; margin = 0; mask = 0x00;
1628 if (rex < much)
1629 much = rex;
1630 rump = 0;
1632 if (much % 2) {
1633 SAM("MISTAKE: much is odd\n");
1634 return -EFAULT;
1637 more = (bytesperpixel *
1638 much) / 4;
1639 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1640 if (1 < bytesperpixel) {
1641 if (rad * 4 < much * bytesperpixel) {
1643 ** INJUDICIOUS ALTERATION OF THIS
1644 ** STATEMENT BLOCK WILL CAUSE
1645 ** BREAKAGE. BEWARE.
1647 rad2 = rad + bytesperpixel - 1;
1648 much = ((((2 * rad2)/bytesperpixel)/2)
1649 * 4);
1650 rump = ((bytesperpixel *
1651 much) / 4) - rad;
1652 more = rad;
1654 mask = (__u8)rump;
1655 margin = 0;
1656 if (much == rex) {
1657 mask |= 0x04;
1658 if ((mex + 1) < FIELD_BUFFER_SIZE/
1659 PAGE_SIZE) {
1660 margin = *((__u8 *)(peasycap->
1661 field_buffer
1662 [kex][mex + 1].pgo));
1664 else
1665 mask |= 0x08;
1667 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1668 } else {
1669 SAM("MISTAKE: %i=bytesperpixel\n",
1670 bytesperpixel);
1671 return -EFAULT;
1673 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1674 if (rump)
1675 caches++;
1677 if (true == badinput) {
1678 JOM(8, "ERROR: 0x%02X=->field_buffer"
1679 "[%i][%i].input, "
1680 "0x%02X=(0x08|->input)\n",
1681 peasycap->field_buffer
1682 [kex][mex].input, kex, mex,
1683 (0x08|peasycap->input));
1685 rc = redaub(peasycap, pad, pex, much, more,
1686 mask, margin, isuy);
1687 if (0 > rc) {
1688 SAM("ERROR: redaub() failed\n");
1689 return -EFAULT;
1691 over -= much; cz += much;
1692 pex += much; rex -= much;
1693 if (!rex) {
1694 mex++;
1695 pex = peasycap->field_buffer[kex][mex].pgo;
1696 rex = PAGE_SIZE;
1697 if (peasycap->field_buffer[kex][mex].input !=
1698 (0x08|peasycap->input))
1699 badinput = true;
1701 pad += more;
1702 rad -= more;
1703 if (!rad) {
1704 mad++;
1705 pad = peasycap->frame_buffer[kad][mad].pgo;
1706 rad = PAGE_SIZE;
1707 if (rump) {
1708 pad += rump;
1709 rad -= rump;
1712 } while (over);
1713 /*---------------------------------------------------------------------------*/
1715 * OTHERWISE JUST
1716 * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM
1718 /*---------------------------------------------------------------------------*/
1719 } else {
1720 over = w2;
1721 do {
1722 if (!rex) {
1723 mex++;
1724 pex = peasycap->field_buffer[kex][mex].pgo;
1725 rex = PAGE_SIZE;
1726 if (peasycap->field_buffer[kex][mex].input !=
1727 (0x08|peasycap->input)) {
1728 JOM(8, "ERROR: 0x%02X=->field_buffer"
1729 "[%i][%i].input, "
1730 "0x%02X=(0x08|->input)\n",
1731 peasycap->field_buffer
1732 [kex][mex].input, kex, mex,
1733 (0x08|peasycap->input));
1734 badinput = true;
1737 much = over;
1738 if (rex < much)
1739 much = rex;
1740 over -= much;
1741 cz += much;
1742 pex += much;
1743 rex -= much;
1744 } while (over);
1747 /*---------------------------------------------------------------------------*/
1749 * SANITY CHECKS
1751 /*---------------------------------------------------------------------------*/
1752 c2 = (mex + 1)*PAGE_SIZE - rex;
1753 if (cz != c2)
1754 SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
1755 c3 = (mad + 1)*PAGE_SIZE - rad;
1757 if (false == decimatepixel) {
1758 if (bytesperpixel *
1759 cz != c3)
1760 SAM("ERROR: discrepancy %i in bytes written\n",
1761 c3 - (bytesperpixel *
1762 cz));
1763 } else {
1764 if (false == odd) {
1765 if (bytesperpixel *
1766 cz != (4 * c3))
1767 SAM("ERROR: discrepancy %i in bytes written\n",
1768 (2*c3)-(bytesperpixel *
1769 cz));
1770 } else {
1771 if (0 != c3)
1772 SAM("ERROR: discrepancy %i "
1773 "in bytes written\n", c3);
1776 if (rump)
1777 SAM("WORRY: undischarged cache at end of line in frame buffer\n");
1779 JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
1780 JOM(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad);
1782 if (true == odd)
1783 JOM(8, "+++++ field2frame(): frame buffer %i is full\n", kad);
1785 if (peasycap->field_read == peasycap->field_fill)
1786 SAM("WARNING: on exit, filling field buffer %i\n",
1787 peasycap->field_read);
1788 /*---------------------------------------------------------------------------*/
1790 * CALCULATE VIDEO STREAMING RATE
1792 /*---------------------------------------------------------------------------*/
1793 do_gettimeofday(&timeval);
1794 if (peasycap->timeval6.tv_sec) {
1795 below = ((long long int)(1000000)) *
1796 ((long long int)(timeval.tv_sec -
1797 peasycap->timeval6.tv_sec)) +
1798 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
1799 above = (long long int)1000000;
1801 sdr = signed_div(above, below);
1802 above = sdr.quotient;
1803 remainder = (__u32)sdr.remainder;
1805 JOM(8, "video streaming at %3lli.%03i fields per second\n", above,
1806 (remainder/1000));
1808 peasycap->timeval6 = timeval;
1810 if (caches)
1811 JOM(8, "%i=caches\n", caches);
1812 return 0;
1814 /*****************************************************************************/
1815 struct signed_div_result
1816 signed_div(long long int above, long long int below)
1818 struct signed_div_result sdr;
1820 if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) {
1821 sdr.remainder = (unsigned long long int) do_div(above, below);
1822 sdr.quotient = (long long int) above;
1823 } else {
1824 if (0 > above)
1825 above = -above;
1826 if (0 > below)
1827 below = -below;
1828 sdr.remainder = (unsigned long long int) do_div(above, below);
1829 sdr.quotient = -((long long int) above);
1831 return sdr;
1833 /*****************************************************************************/
1834 /*---------------------------------------------------------------------------*/
1836 * DECIMATION AND COLOURSPACE CONVERSION.
1838 * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
1839 * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
1840 * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
1841 * ALSO ENSURE THAT much IS EVEN.
1843 * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
1844 * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
1846 * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
1847 * 0x03 & mask = number of bytes to be written to cache instead of to
1848 * frame buffer
1849 * 0x04 & mask => use argument margin to set the chrominance for last pixel
1850 * 0x08 & mask => do not set the chrominance for last pixel
1852 * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
1854 * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
1855 * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO
1856 * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE.
1858 /*---------------------------------------------------------------------------*/
1860 redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
1861 __u8 mask, __u8 margin, bool isuy)
1863 static __s32 ay[256], bu[256], rv[256], gu[256], gv[256];
1864 __u8 *pcache;
1865 __u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
1866 int bytesperpixel;
1867 bool byteswaporder, decimatepixel, last;
1868 int j, rump;
1869 __s32 s32;
1871 if (much % 2) {
1872 SAM("MISTAKE: much is odd\n");
1873 return -EFAULT;
1875 bytesperpixel = peasycap->bytesperpixel;
1876 byteswaporder = peasycap->byteswaporder;
1877 decimatepixel = peasycap->decimatepixel;
1879 /*---------------------------------------------------------------------------*/
1880 if (!bu[255]) {
1881 for (j = 0; j < 112; j++) {
1882 s32 = (0xFF00 & (453 * j)) >> 8;
1883 bu[j + 128] = s32; bu[127 - j] = -s32;
1884 s32 = (0xFF00 & (359 * j)) >> 8;
1885 rv[j + 128] = s32; rv[127 - j] = -s32;
1886 s32 = (0xFF00 & (88 * j)) >> 8;
1887 gu[j + 128] = s32; gu[127 - j] = -s32;
1888 s32 = (0xFF00 & (183 * j)) >> 8;
1889 gv[j + 128] = s32; gv[127 - j] = -s32;
1891 for (j = 0; j < 16; j++) {
1892 bu[j] = bu[16]; rv[j] = rv[16];
1893 gu[j] = gu[16]; gv[j] = gv[16];
1895 for (j = 240; j < 256; j++) {
1896 bu[j] = bu[239]; rv[j] = rv[239];
1897 gu[j] = gu[239]; gv[j] = gv[239];
1899 for (j = 16; j < 236; j++)
1900 ay[j] = j;
1901 for (j = 0; j < 16; j++)
1902 ay[j] = ay[16];
1903 for (j = 236; j < 256; j++)
1904 ay[j] = ay[235];
1905 JOM(8, "lookup tables are prepared\n");
1907 pcache = peasycap->pcache;
1908 if (NULL == pcache)
1909 pcache = &peasycap->cache[0];
1910 /*---------------------------------------------------------------------------*/
1912 * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
1914 /*---------------------------------------------------------------------------*/
1915 if (!pcache) {
1916 SAM("MISTAKE: pcache is NULL\n");
1917 return -EFAULT;
1920 if (pcache != &peasycap->cache[0])
1921 JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
1922 p2 = &peasycap->cache[0];
1923 p3 = (__u8 *)pad - (int)(pcache - &peasycap->cache[0]);
1924 while (p2 < pcache) {
1925 *p3++ = *p2; p2++;
1927 pcache = &peasycap->cache[0];
1928 if (p3 != pad) {
1929 SAM("MISTAKE: pointer misalignment\n");
1930 return -EFAULT;
1932 /*---------------------------------------------------------------------------*/
1933 rump = (int)(0x03 & mask);
1934 u = 0; v = 0;
1935 p2 = (__u8 *)pex; pz = p2 + much; pr = p3 + more; last = false;
1936 p2++;
1938 if (true == isuy)
1939 u = *(p2 - 1);
1940 else
1941 v = *(p2 - 1);
1943 if (rump)
1944 JOM(16, "%4i=much %4i=more %i=rump\n", much, more, rump);
1946 /*---------------------------------------------------------------------------*/
1947 switch (bytesperpixel) {
1948 case 2: {
1949 if (false == decimatepixel) {
1950 memcpy(pad, pex, (size_t)much);
1951 if (false == byteswaporder)
1952 /*---------------------------------------------------*/
1954 ** UYVY
1956 /*---------------------------------------------------*/
1957 return 0;
1958 else {
1959 /*---------------------------------------------------*/
1961 ** YUYV
1963 /*---------------------------------------------------*/
1964 p3 = (__u8 *)pad; pz = p3 + much;
1965 while (pz > p3) {
1966 c = *p3;
1967 *p3 = *(p3 + 1);
1968 *(p3 + 1) = c;
1969 p3 += 2;
1971 return 0;
1973 } else {
1974 if (false == byteswaporder) {
1975 /*---------------------------------------------------*/
1977 ** UYVY DECIMATED
1979 /*---------------------------------------------------*/
1980 p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much;
1981 while (pz > p2) {
1982 *p3 = *p2;
1983 *(p3 + 1) = *(p2 + 1);
1984 *(p3 + 2) = *(p2 + 2);
1985 *(p3 + 3) = *(p2 + 3);
1986 p3 += 4; p2 += 8;
1988 return 0;
1989 } else {
1990 /*---------------------------------------------------*/
1992 ** YUYV DECIMATED
1994 /*---------------------------------------------------*/
1995 p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much;
1996 while (pz > p2) {
1997 *p3 = *(p2 + 1);
1998 *(p3 + 1) = *p2;
1999 *(p3 + 2) = *(p2 + 3);
2000 *(p3 + 3) = *(p2 + 2);
2001 p3 += 4; p2 += 8;
2003 return 0;
2006 break;
2008 case 3:
2010 if (false == decimatepixel) {
2011 if (false == byteswaporder) {
2012 /*---------------------------------------------------*/
2014 ** RGB
2016 /*---------------------------------------------------*/
2017 while (pz > p2) {
2018 if (pr <= (p3 + bytesperpixel))
2019 last = true;
2020 else
2021 last = false;
2022 y = *p2;
2023 if ((true == last) && (0x0C & mask)) {
2024 if (0x04 & mask) {
2025 if (true == isuy)
2026 v = margin;
2027 else
2028 u = margin;
2029 } else
2030 if (0x08 & mask)
2032 } else {
2033 if (true == isuy)
2034 v = *(p2 + 1);
2035 else
2036 u = *(p2 + 1);
2039 s32 = ay[(int)y] + rv[(int)v];
2040 r = (255 < s32) ? 255 : ((0 > s32) ?
2041 0 : (__u8)s32);
2042 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
2043 g = (255 < s32) ? 255 : ((0 > s32) ?
2044 0 : (__u8)s32);
2045 s32 = ay[(int)y] + bu[(int)u];
2046 b = (255 < s32) ? 255 : ((0 > s32) ?
2047 0 : (__u8)s32);
2049 if ((true == last) && rump) {
2050 pcache = &peasycap->cache[0];
2051 switch (bytesperpixel - rump) {
2052 case 1: {
2053 *p3 = r;
2054 *pcache++ = g;
2055 *pcache++ = b;
2056 break;
2058 case 2: {
2059 *p3 = r;
2060 *(p3 + 1) = g;
2061 *pcache++ = b;
2062 break;
2064 default: {
2065 SAM("MISTAKE: %i=rump\n",
2066 bytesperpixel - rump);
2067 return -EFAULT;
2070 } else {
2071 *p3 = r;
2072 *(p3 + 1) = g;
2073 *(p3 + 2) = b;
2075 p2 += 2;
2076 if (true == isuy)
2077 isuy = false;
2078 else
2079 isuy = true;
2080 p3 += bytesperpixel;
2082 return 0;
2083 } else {
2084 /*---------------------------------------------------*/
2086 ** BGR
2088 /*---------------------------------------------------*/
2089 while (pz > p2) {
2090 if (pr <= (p3 + bytesperpixel))
2091 last = true;
2092 else
2093 last = false;
2094 y = *p2;
2095 if ((true == last) && (0x0C & mask)) {
2096 if (0x04 & mask) {
2097 if (true == isuy)
2098 v = margin;
2099 else
2100 u = margin;
2102 else
2103 if (0x08 & mask)
2105 } else {
2106 if (true == isuy)
2107 v = *(p2 + 1);
2108 else
2109 u = *(p2 + 1);
2112 s32 = ay[(int)y] + rv[(int)v];
2113 r = (255 < s32) ? 255 : ((0 > s32) ?
2114 0 : (__u8)s32);
2115 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
2116 g = (255 < s32) ? 255 : ((0 > s32) ?
2117 0 : (__u8)s32);
2118 s32 = ay[(int)y] + bu[(int)u];
2119 b = (255 < s32) ? 255 : ((0 > s32) ?
2120 0 : (__u8)s32);
2122 if ((true == last) && rump) {
2123 pcache = &peasycap->cache[0];
2124 switch (bytesperpixel - rump) {
2125 case 1: {
2126 *p3 = b;
2127 *pcache++ = g;
2128 *pcache++ = r;
2129 break;
2131 case 2: {
2132 *p3 = b;
2133 *(p3 + 1) = g;
2134 *pcache++ = r;
2135 break;
2137 default: {
2138 SAM("MISTAKE: %i=rump\n",
2139 bytesperpixel - rump);
2140 return -EFAULT;
2143 } else {
2144 *p3 = b;
2145 *(p3 + 1) = g;
2146 *(p3 + 2) = r;
2148 p2 += 2;
2149 if (true == isuy)
2150 isuy = false;
2151 else
2152 isuy = true;
2153 p3 += bytesperpixel;
2156 return 0;
2157 } else {
2158 if (false == byteswaporder) {
2159 /*---------------------------------------------------*/
2161 ** RGB DECIMATED
2163 /*---------------------------------------------------*/
2164 while (pz > p2) {
2165 if (pr <= (p3 + bytesperpixel))
2166 last = true;
2167 else
2168 last = false;
2169 y = *p2;
2170 if ((true == last) && (0x0C & mask)) {
2171 if (0x04 & mask) {
2172 if (true == isuy)
2173 v = margin;
2174 else
2175 u = margin;
2176 } else
2177 if (0x08 & mask)
2179 } else {
2180 if (true == isuy)
2181 v = *(p2 + 1);
2182 else
2183 u = *(p2 + 1);
2186 if (true == isuy) {
2187 s32 = ay[(int)y] + rv[(int)v];
2188 r = (255 < s32) ? 255 : ((0 > s32) ?
2189 0 : (__u8)s32);
2190 s32 = ay[(int)y] - gu[(int)u] -
2191 gv[(int)v];
2192 g = (255 < s32) ? 255 : ((0 > s32) ?
2193 0 : (__u8)s32);
2194 s32 = ay[(int)y] + bu[(int)u];
2195 b = (255 < s32) ? 255 : ((0 > s32) ?
2196 0 : (__u8)s32);
2198 if ((true == last) && rump) {
2199 pcache = &peasycap->cache[0];
2200 switch (bytesperpixel - rump) {
2201 case 1: {
2202 *p3 = r;
2203 *pcache++ = g;
2204 *pcache++ = b;
2205 break;
2207 case 2: {
2208 *p3 = r;
2209 *(p3 + 1) = g;
2210 *pcache++ = b;
2211 break;
2213 default: {
2214 SAM("MISTAKE: "
2215 "%i=rump\n",
2216 bytesperpixel - rump);
2217 return -EFAULT;
2220 } else {
2221 *p3 = r;
2222 *(p3 + 1) = g;
2223 *(p3 + 2) = b;
2225 isuy = false;
2226 p3 += bytesperpixel;
2227 } else {
2228 isuy = true;
2230 p2 += 2;
2232 return 0;
2233 } else {
2234 /*---------------------------------------------------*/
2236 * BGR DECIMATED
2238 /*---------------------------------------------------*/
2239 while (pz > p2) {
2240 if (pr <= (p3 + bytesperpixel))
2241 last = true;
2242 else
2243 last = false;
2244 y = *p2;
2245 if ((true == last) && (0x0C & mask)) {
2246 if (0x04 & mask) {
2247 if (true == isuy)
2248 v = margin;
2249 else
2250 u = margin;
2251 } else
2252 if (0x08 & mask)
2254 } else {
2255 if (true == isuy)
2256 v = *(p2 + 1);
2257 else
2258 u = *(p2 + 1);
2261 if (true == isuy) {
2263 s32 = ay[(int)y] + rv[(int)v];
2264 r = (255 < s32) ? 255 : ((0 > s32) ?
2265 0 : (__u8)s32);
2266 s32 = ay[(int)y] - gu[(int)u] -
2267 gv[(int)v];
2268 g = (255 < s32) ? 255 : ((0 > s32) ?
2269 0 : (__u8)s32);
2270 s32 = ay[(int)y] + bu[(int)u];
2271 b = (255 < s32) ? 255 : ((0 > s32) ?
2272 0 : (__u8)s32);
2274 if ((true == last) && rump) {
2275 pcache = &peasycap->cache[0];
2276 switch (bytesperpixel - rump) {
2277 case 1: {
2278 *p3 = b;
2279 *pcache++ = g;
2280 *pcache++ = r;
2281 break;
2283 case 2: {
2284 *p3 = b;
2285 *(p3 + 1) = g;
2286 *pcache++ = r;
2287 break;
2289 default: {
2290 SAM("MISTAKE: "
2291 "%i=rump\n",
2292 bytesperpixel - rump);
2293 return -EFAULT;
2296 } else {
2297 *p3 = b;
2298 *(p3 + 1) = g;
2299 *(p3 + 2) = r;
2301 isuy = false;
2302 p3 += bytesperpixel;
2304 else
2305 isuy = true;
2306 p2 += 2;
2308 return 0;
2311 break;
2313 case 4:
2315 if (false == decimatepixel) {
2316 if (false == byteswaporder) {
2317 /*---------------------------------------------------*/
2319 ** RGBA
2321 /*---------------------------------------------------*/
2322 while (pz > p2) {
2323 if (pr <= (p3 + bytesperpixel))
2324 last = true;
2325 else
2326 last = false;
2327 y = *p2;
2328 if ((true == last) && (0x0C & mask)) {
2329 if (0x04 & mask) {
2330 if (true == isuy)
2331 v = margin;
2332 else
2333 u = margin;
2334 } else
2335 if (0x08 & mask)
2337 } else {
2338 if (true == isuy)
2339 v = *(p2 + 1);
2340 else
2341 u = *(p2 + 1);
2344 s32 = ay[(int)y] + rv[(int)v];
2345 r = (255 < s32) ? 255 : ((0 > s32) ?
2346 0 : (__u8)s32);
2347 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
2348 g = (255 < s32) ? 255 : ((0 > s32) ?
2349 0 : (__u8)s32);
2350 s32 = ay[(int)y] + bu[(int)u];
2351 b = (255 < s32) ? 255 : ((0 > s32) ?
2352 0 : (__u8)s32);
2354 if ((true == last) && rump) {
2355 pcache = &peasycap->cache[0];
2356 switch (bytesperpixel - rump) {
2357 case 1: {
2358 *p3 = r;
2359 *pcache++ = g;
2360 *pcache++ = b;
2361 *pcache++ = 0;
2362 break;
2364 case 2: {
2365 *p3 = r;
2366 *(p3 + 1) = g;
2367 *pcache++ = b;
2368 *pcache++ = 0;
2369 break;
2371 case 3: {
2372 *p3 = r;
2373 *(p3 + 1) = g;
2374 *(p3 + 2) = b;
2375 *pcache++ = 0;
2376 break;
2378 default: {
2379 SAM("MISTAKE: %i=rump\n",
2380 bytesperpixel - rump);
2381 return -EFAULT;
2384 } else {
2385 *p3 = r;
2386 *(p3 + 1) = g;
2387 *(p3 + 2) = b;
2388 *(p3 + 3) = 0;
2390 p2 += 2;
2391 if (true == isuy)
2392 isuy = false;
2393 else
2394 isuy = true;
2395 p3 += bytesperpixel;
2397 return 0;
2398 } else {
2399 /*---------------------------------------------------*/
2401 ** BGRA
2403 /*---------------------------------------------------*/
2404 while (pz > p2) {
2405 if (pr <= (p3 + bytesperpixel))
2406 last = true;
2407 else
2408 last = false;
2409 y = *p2;
2410 if ((true == last) && (0x0C & mask)) {
2411 if (0x04 & mask) {
2412 if (true == isuy)
2413 v = margin;
2414 else
2415 u = margin;
2416 } else
2417 if (0x08 & mask)
2419 } else {
2420 if (true == isuy)
2421 v = *(p2 + 1);
2422 else
2423 u = *(p2 + 1);
2426 s32 = ay[(int)y] + rv[(int)v];
2427 r = (255 < s32) ? 255 : ((0 > s32) ?
2428 0 : (__u8)s32);
2429 s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
2430 g = (255 < s32) ? 255 : ((0 > s32) ?
2431 0 : (__u8)s32);
2432 s32 = ay[(int)y] + bu[(int)u];
2433 b = (255 < s32) ? 255 : ((0 > s32) ?
2434 0 : (__u8)s32);
2436 if ((true == last) && rump) {
2437 pcache = &peasycap->cache[0];
2438 switch (bytesperpixel - rump) {
2439 case 1: {
2440 *p3 = b;
2441 *pcache++ = g;
2442 *pcache++ = r;
2443 *pcache++ = 0;
2444 break;
2446 case 2: {
2447 *p3 = b;
2448 *(p3 + 1) = g;
2449 *pcache++ = r;
2450 *pcache++ = 0;
2451 break;
2453 case 3: {
2454 *p3 = b;
2455 *(p3 + 1) = g;
2456 *(p3 + 2) = r;
2457 *pcache++ = 0;
2458 break;
2460 default: {
2461 SAM("MISTAKE: %i=rump\n",
2462 bytesperpixel - rump);
2463 return -EFAULT;
2466 } else {
2467 *p3 = b;
2468 *(p3 + 1) = g;
2469 *(p3 + 2) = r;
2470 *(p3 + 3) = 0;
2472 p2 += 2;
2473 if (true == isuy)
2474 isuy = false;
2475 else
2476 isuy = true;
2477 p3 += bytesperpixel;
2480 return 0;
2481 } else {
2482 if (false == byteswaporder) {
2483 /*---------------------------------------------------*/
2485 ** RGBA DECIMATED
2487 /*---------------------------------------------------*/
2488 while (pz > p2) {
2489 if (pr <= (p3 + bytesperpixel))
2490 last = true;
2491 else
2492 last = false;
2493 y = *p2;
2494 if ((true == last) && (0x0C & mask)) {
2495 if (0x04 & mask) {
2496 if (true == isuy)
2497 v = margin;
2498 else
2499 u = margin;
2500 } else
2501 if (0x08 & mask)
2503 } else {
2504 if (true == isuy)
2505 v = *(p2 + 1);
2506 else
2507 u = *(p2 + 1);
2510 if (true == isuy) {
2512 s32 = ay[(int)y] + rv[(int)v];
2513 r = (255 < s32) ? 255 : ((0 > s32) ?
2514 0 : (__u8)s32);
2515 s32 = ay[(int)y] - gu[(int)u] -
2516 gv[(int)v];
2517 g = (255 < s32) ? 255 : ((0 > s32) ?
2518 0 : (__u8)s32);
2519 s32 = ay[(int)y] + bu[(int)u];
2520 b = (255 < s32) ? 255 : ((0 > s32) ?
2521 0 : (__u8)s32);
2523 if ((true == last) && rump) {
2524 pcache = &peasycap->cache[0];
2525 switch (bytesperpixel - rump) {
2526 case 1: {
2527 *p3 = r;
2528 *pcache++ = g;
2529 *pcache++ = b;
2530 *pcache++ = 0;
2531 break;
2533 case 2: {
2534 *p3 = r;
2535 *(p3 + 1) = g;
2536 *pcache++ = b;
2537 *pcache++ = 0;
2538 break;
2540 case 3: {
2541 *p3 = r;
2542 *(p3 + 1) = g;
2543 *(p3 + 2) = b;
2544 *pcache++ = 0;
2545 break;
2547 default: {
2548 SAM("MISTAKE: "
2549 "%i=rump\n",
2550 bytesperpixel -
2551 rump);
2552 return -EFAULT;
2555 } else {
2556 *p3 = r;
2557 *(p3 + 1) = g;
2558 *(p3 + 2) = b;
2559 *(p3 + 3) = 0;
2561 isuy = false;
2562 p3 += bytesperpixel;
2563 } else
2564 isuy = true;
2565 p2 += 2;
2567 return 0;
2568 } else {
2569 /*---------------------------------------------------*/
2571 ** BGRA DECIMATED
2573 /*---------------------------------------------------*/
2574 while (pz > p2) {
2575 if (pr <= (p3 + bytesperpixel))
2576 last = true;
2577 else
2578 last = false;
2579 y = *p2;
2580 if ((true == last) && (0x0C & mask)) {
2581 if (0x04 & mask) {
2582 if (true == isuy)
2583 v = margin;
2584 else
2585 u = margin;
2586 } else
2587 if (0x08 & mask)
2589 } else {
2590 if (true == isuy)
2591 v = *(p2 + 1);
2592 else
2593 u = *(p2 + 1);
2596 if (true == isuy) {
2597 s32 = ay[(int)y] + rv[(int)v];
2598 r = (255 < s32) ? 255 : ((0 > s32) ?
2599 0 : (__u8)s32);
2600 s32 = ay[(int)y] - gu[(int)u] -
2601 gv[(int)v];
2602 g = (255 < s32) ? 255 : ((0 > s32) ?
2603 0 : (__u8)s32);
2604 s32 = ay[(int)y] + bu[(int)u];
2605 b = (255 < s32) ? 255 : ((0 > s32) ?
2606 0 : (__u8)s32);
2608 if ((true == last) && rump) {
2609 pcache = &peasycap->cache[0];
2610 switch (bytesperpixel - rump) {
2611 case 1: {
2612 *p3 = b;
2613 *pcache++ = g;
2614 *pcache++ = r;
2615 *pcache++ = 0;
2616 break;
2618 case 2: {
2619 *p3 = b;
2620 *(p3 + 1) = g;
2621 *pcache++ = r;
2622 *pcache++ = 0;
2623 break;
2625 case 3: {
2626 *p3 = b;
2627 *(p3 + 1) = g;
2628 *(p3 + 2) = r;
2629 *pcache++ = 0;
2630 break;
2632 default: {
2633 SAM("MISTAKE: "
2634 "%i=rump\n",
2635 bytesperpixel - rump);
2636 return -EFAULT;
2639 } else {
2640 *p3 = b;
2641 *(p3 + 1) = g;
2642 *(p3 + 2) = r;
2643 *(p3 + 3) = 0;
2645 isuy = false;
2646 p3 += bytesperpixel;
2647 } else
2648 isuy = true;
2649 p2 += 2;
2651 return 0;
2654 break;
2656 default: {
2657 SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
2658 return -EFAULT;
2661 return 0;
2663 /*****************************************************************************/
2664 /*---------------------------------------------------------------------------*/
2666 * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
2668 /*---------------------------------------------------------------------------*/
2669 int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
2672 JOT(8, "\n");
2674 pvma->vm_ops = &easycap_vm_ops;
2675 pvma->vm_flags |= VM_RESERVED;
2676 if (NULL != file)
2677 pvma->vm_private_data = file->private_data;
2678 easycap_vma_open(pvma);
2679 return 0;
2681 /*****************************************************************************/
2682 void
2683 easycap_vma_open(struct vm_area_struct *pvma)
2685 struct easycap *peasycap;
2687 peasycap = pvma->vm_private_data;
2688 if (NULL == peasycap) {
2689 SAY("ERROR: peasycap is NULL\n");
2690 return;
2692 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2693 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
2694 return;
2696 peasycap->vma_many++;
2697 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2698 return;
2700 /*****************************************************************************/
2701 void
2702 easycap_vma_close(struct vm_area_struct *pvma)
2704 struct easycap *peasycap;
2706 peasycap = pvma->vm_private_data;
2707 if (NULL == peasycap) {
2708 SAY("ERROR: peasycap is NULL\n");
2709 return;
2711 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2712 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
2713 return;
2715 peasycap->vma_many--;
2716 JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
2717 return;
2719 /*****************************************************************************/
2721 easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
2723 int k, m, retcode;
2724 void *pbuf;
2725 struct page *page;
2726 struct easycap *peasycap;
2728 retcode = VM_FAULT_NOPAGE;
2729 pbuf = (void *)NULL;
2730 page = (struct page *)NULL;
2732 if (NULL == pvma) {
2733 SAY("pvma is NULL\n");
2734 return retcode;
2736 if (NULL == pvmf) {
2737 SAY("pvmf is NULL\n");
2738 return retcode;
2741 k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
2742 m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
2744 if (!m)
2745 JOT(4, "%4i=k, %4i=m\n", k, m);
2746 else
2747 JOT(16, "%4i=k, %4i=m\n", k, m);
2749 if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
2750 SAY("ERROR: buffer index %i out of range\n", k);
2751 return retcode;
2753 if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
2754 SAY("ERROR: page number %i out of range\n", m);
2755 return retcode;
2757 peasycap = pvma->vm_private_data;
2758 if (NULL == peasycap) {
2759 SAY("ERROR: peasycap is NULL\n");
2760 return retcode;
2762 /*---------------------------------------------------------------------------*/
2763 pbuf = peasycap->frame_buffer[k][m].pgo;
2764 if (NULL == pbuf) {
2765 SAM("ERROR: pbuf is NULL\n");
2766 goto finish;
2768 page = virt_to_page(pbuf);
2769 if (NULL == page) {
2770 SAM("ERROR: page is NULL\n");
2771 goto finish;
2773 get_page(page);
2774 /*---------------------------------------------------------------------------*/
2775 finish:
2776 if (NULL == page) {
2777 SAM("ERROR: page is NULL after get_page(page)\n");
2778 } else {
2779 pvmf->page = page;
2780 retcode = VM_FAULT_MINOR;
2782 return retcode;
2784 /*****************************************************************************/
2785 /*---------------------------------------------------------------------------*/
2787 * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
2788 * PROVIDED peasycap->video_idle IS ZERO. REGARDLESS OF THIS BEING TRUE,
2789 * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
2791 * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
2793 * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
2794 * STORED IN THE TWO-BYTE STATUS PARAMETER
2795 * peasycap->field_buffer[peasycap->field_fill][0].kount
2796 * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
2798 * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
2799 * CHIP.
2801 * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
2802 * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS
2803 * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA
2804 * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA
2805 * 0 != (kount & 0x1000) => BUFFER HAS DATA FROM DISPARATE INPUTS
2806 * 0 != (kount & 0x0400) => RESERVED
2807 * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED
2808 * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY?
2810 /*---------------------------------------------------------------------------*/
2811 void
2812 easycap_complete(struct urb *purb)
2814 struct easycap *peasycap;
2815 struct data_buffer *pfield_buffer;
2816 char errbuf[16];
2817 int i, more, much, leap, rc, last;
2818 int videofieldamount;
2819 unsigned int override, bad;
2820 int framestatus, framelength, frameactual, frameoffset;
2821 __u8 *pu;
2823 if (NULL == purb) {
2824 SAY("ERROR: easycap_complete(): purb is NULL\n");
2825 return;
2827 peasycap = purb->context;
2828 if (NULL == peasycap) {
2829 SAY("ERROR: easycap_complete(): peasycap is NULL\n");
2830 return;
2832 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2833 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
2834 return;
2836 if (peasycap->video_eof)
2837 return;
2838 for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
2839 if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
2840 break;
2841 JOM(16, "%2i=urb\n", i);
2842 last = peasycap->video_isoc_sequence;
2843 if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) &&
2844 (0 != i)) ||
2845 (((VIDEO_ISOC_BUFFER_MANY - 1) != last) &&
2846 ((last + 1) != i))) {
2847 JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
2849 peasycap->video_isoc_sequence = i;
2851 if (peasycap->video_idle) {
2852 JOM(16, "%i=video_idle %i=video_isoc_streaming\n",
2853 peasycap->video_idle, peasycap->video_isoc_streaming);
2854 if (peasycap->video_isoc_streaming) {
2855 rc = usb_submit_urb(purb, GFP_ATOMIC);
2856 if (0 != rc) {
2857 switch (rc) {
2858 case -ENOMEM: {
2859 SAM("ENOMEM\n");
2860 break;
2862 case -ENODEV: {
2863 SAM("ENODEV\n");
2864 break;
2866 case -ENXIO: {
2867 SAM("ENXIO\n");
2868 break;
2870 case -EINVAL: {
2871 SAM("EINVAL\n");
2872 break;
2874 case -EAGAIN: {
2875 SAM("EAGAIN\n");
2876 break;
2878 case -EFBIG: {
2879 SAM("EFBIG\n");
2880 break;
2882 case -EPIPE: {
2883 SAM("EPIPE\n");
2884 break;
2886 case -EMSGSIZE: {
2887 SAM("EMSGSIZE\n");
2888 break;
2890 case -ENOSPC: {
2891 SAM("ENOSPC\n");
2892 break;
2894 default: {
2895 SAM("0x%08X\n", rc);
2896 break;
2899 if (-ENODEV != rc)
2900 SAM("ERROR: while %i=video_idle, "
2901 "usb_submit_urb() "
2902 "failed with rc:\n",
2903 peasycap->video_idle);
2906 return;
2908 override = 0;
2909 /*---------------------------------------------------------------------------*/
2910 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
2911 SAM("ERROR: bad peasycap->field_fill\n");
2912 return;
2914 if (purb->status) {
2915 if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
2916 JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
2917 return;
2920 (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
2921 SAM("ERROR: bad urb status:\n");
2922 switch (purb->status) {
2923 case -EINPROGRESS: {
2924 SAM("-EINPROGRESS\n"); break;
2926 case -ENOSR: {
2927 SAM("-ENOSR\n"); break;
2929 case -EPIPE: {
2930 SAM("-EPIPE\n"); break;
2932 case -EOVERFLOW: {
2933 SAM("-EOVERFLOW\n"); break;
2935 case -EPROTO: {
2936 SAM("-EPROTO\n"); break;
2938 case -EILSEQ: {
2939 SAM("-EILSEQ\n"); break;
2941 case -ETIMEDOUT: {
2942 SAM("-ETIMEDOUT\n"); break;
2944 case -EMSGSIZE: {
2945 SAM("-EMSGSIZE\n"); break;
2947 case -EOPNOTSUPP: {
2948 SAM("-EOPNOTSUPP\n"); break;
2950 case -EPFNOSUPPORT: {
2951 SAM("-EPFNOSUPPORT\n"); break;
2953 case -EAFNOSUPPORT: {
2954 SAM("-EAFNOSUPPORT\n"); break;
2956 case -EADDRINUSE: {
2957 SAM("-EADDRINUSE\n"); break;
2959 case -EADDRNOTAVAIL: {
2960 SAM("-EADDRNOTAVAIL\n"); break;
2962 case -ENOBUFS: {
2963 SAM("-ENOBUFS\n"); break;
2965 case -EISCONN: {
2966 SAM("-EISCONN\n"); break;
2968 case -ENOTCONN: {
2969 SAM("-ENOTCONN\n"); break;
2971 case -ESHUTDOWN: {
2972 SAM("-ESHUTDOWN\n"); break;
2974 case -ENOENT: {
2975 SAM("-ENOENT\n"); break;
2977 case -ECONNRESET: {
2978 SAM("-ECONNRESET\n"); break;
2980 case -ENOSPC: {
2981 SAM("ENOSPC\n"); break;
2983 default: {
2984 SAM("unknown error code 0x%08X\n", purb->status); break;
2987 /*---------------------------------------------------------------------------*/
2988 } else {
2989 for (i = 0; i < purb->number_of_packets; i++) {
2990 if (0 != purb->iso_frame_desc[i].status) {
2991 (peasycap->field_buffer
2992 [peasycap->field_fill][0].kount) |= 0x8000 ;
2993 switch (purb->iso_frame_desc[i].status) {
2994 case 0: {
2995 strcpy(&errbuf[0], "OK"); break;
2997 case -ENOENT: {
2998 strcpy(&errbuf[0], "-ENOENT"); break;
3000 case -EINPROGRESS: {
3001 strcpy(&errbuf[0], "-EINPROGRESS"); break;
3003 case -EPROTO: {
3004 strcpy(&errbuf[0], "-EPROTO"); break;
3006 case -EILSEQ: {
3007 strcpy(&errbuf[0], "-EILSEQ"); break;
3009 case -ETIME: {
3010 strcpy(&errbuf[0], "-ETIME"); break;
3012 case -ETIMEDOUT: {
3013 strcpy(&errbuf[0], "-ETIMEDOUT"); break;
3015 case -EPIPE: {
3016 strcpy(&errbuf[0], "-EPIPE"); break;
3018 case -ECOMM: {
3019 strcpy(&errbuf[0], "-ECOMM"); break;
3021 case -ENOSR: {
3022 strcpy(&errbuf[0], "-ENOSR"); break;
3024 case -EOVERFLOW: {
3025 strcpy(&errbuf[0], "-EOVERFLOW"); break;
3027 case -EREMOTEIO: {
3028 strcpy(&errbuf[0], "-EREMOTEIO"); break;
3030 case -ENODEV: {
3031 strcpy(&errbuf[0], "-ENODEV"); break;
3033 case -EXDEV: {
3034 strcpy(&errbuf[0], "-EXDEV"); break;
3036 case -EINVAL: {
3037 strcpy(&errbuf[0], "-EINVAL"); break;
3039 case -ECONNRESET: {
3040 strcpy(&errbuf[0], "-ECONNRESET"); break;
3042 case -ENOSPC: {
3043 SAM("ENOSPC\n"); break;
3045 case -ESHUTDOWN: {
3046 strcpy(&errbuf[0], "-ESHUTDOWN"); break;
3048 default: {
3049 strcpy(&errbuf[0], "unknown error"); break;
3053 framestatus = purb->iso_frame_desc[i].status;
3054 framelength = purb->iso_frame_desc[i].length;
3055 frameactual = purb->iso_frame_desc[i].actual_length;
3056 frameoffset = purb->iso_frame_desc[i].offset;
3058 JOM(16, "frame[%2i]:"
3059 "%4i=status "
3060 "%4i=actual "
3061 "%4i=length "
3062 "%5i=offset\n",
3063 i, framestatus, frameactual, framelength, frameoffset);
3064 if (!purb->iso_frame_desc[i].status) {
3065 more = purb->iso_frame_desc[i].actual_length;
3066 pfield_buffer = &peasycap->field_buffer
3067 [peasycap->field_fill][peasycap->field_page];
3068 videofieldamount = (peasycap->field_page *
3069 PAGE_SIZE) +
3070 (int)(pfield_buffer->pto - pfield_buffer->pgo);
3071 if (4 == more)
3072 peasycap->video_mt++;
3073 if (4 < more) {
3074 if (peasycap->video_mt) {
3075 JOM(8, "%4i empty video urb frames\n",
3076 peasycap->video_mt);
3077 peasycap->video_mt = 0;
3079 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
3080 SAM("ERROR: bad peasycap->field_fill\n");
3081 return;
3083 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
3084 peasycap->field_page) {
3085 SAM("ERROR: bad peasycap->field_page\n");
3086 return;
3088 pfield_buffer = &peasycap->field_buffer
3089 [peasycap->field_fill][peasycap->field_page];
3090 pu = (__u8 *)(purb->transfer_buffer +
3091 purb->iso_frame_desc[i].offset);
3092 if (0x80 & *pu)
3093 leap = 8;
3094 else
3095 leap = 4;
3096 /*--------------------------------------------------------------------------*/
3098 * EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
3099 * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
3100 * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
3102 * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
3103 * BYTE OF
3104 * peasycap->field_buffer[peasycap->field_fill][0].kount
3105 * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
3106 * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA
3107 * NOTHING IS OFFERED TO dqbuf().
3109 * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
3110 * RESTS WITH dqbuf().
3112 /*---------------------------------------------------------------------------*/
3113 if ((8 == more) || override) {
3114 if (videofieldamount >
3115 peasycap->videofieldamount) {
3116 if (2 == videofieldamount -
3117 peasycap->
3118 videofieldamount) {
3119 (peasycap->field_buffer
3120 [peasycap->field_fill]
3121 [0].kount) |= 0x0100;
3122 peasycap->video_junk += (1 +
3123 VIDEO_JUNK_TOLERATE);
3124 } else
3125 (peasycap->field_buffer
3126 [peasycap->field_fill]
3127 [0].kount) |= 0x4000;
3128 } else if (videofieldamount <
3129 peasycap->
3130 videofieldamount) {
3131 (peasycap->field_buffer
3132 [peasycap->field_fill]
3133 [0].kount) |= 0x2000;
3135 bad = 0xFF00 & peasycap->field_buffer
3136 [peasycap->field_fill]
3137 [0].kount;
3138 if (!bad) {
3139 (peasycap->video_junk)--;
3140 if (-VIDEO_JUNK_TOLERATE >
3141 peasycap->video_junk)
3142 peasycap->video_junk =
3143 -VIDEO_JUNK_TOLERATE;
3144 peasycap->field_read =
3145 (peasycap->
3146 field_fill)++;
3147 if (FIELD_BUFFER_MANY <=
3148 peasycap->
3149 field_fill)
3150 peasycap->
3151 field_fill = 0;
3152 peasycap->field_page = 0;
3153 pfield_buffer = &peasycap->
3154 field_buffer
3155 [peasycap->
3156 field_fill]
3157 [peasycap->
3158 field_page];
3159 pfield_buffer->pto =
3160 pfield_buffer->pgo;
3161 JOM(8, "bumped to: %i="
3162 "peasycap->"
3163 "field_fill %i="
3164 "parity\n",
3165 peasycap->field_fill,
3166 0x00FF &
3167 pfield_buffer->kount);
3168 JOM(8, "field buffer %i has "
3169 "%i bytes fit to be "
3170 "read\n",
3171 peasycap->field_read,
3172 videofieldamount);
3173 JOM(8, "wakeup call to "
3174 "wq_video, "
3175 "%i=field_read "
3176 "%i=field_fill "
3177 "%i=parity\n",
3178 peasycap->field_read,
3179 peasycap->field_fill,
3180 0x00FF & peasycap->
3181 field_buffer
3182 [peasycap->
3183 field_read][0].kount);
3184 wake_up_interruptible
3185 (&(peasycap->
3186 wq_video));
3187 do_gettimeofday
3188 (&peasycap->timeval7);
3189 } else {
3190 peasycap->video_junk++;
3191 if (bad & 0x0010)
3192 peasycap->video_junk +=
3193 (1 + VIDEO_JUNK_TOLERATE/2);
3194 JOM(8, "field buffer %i had %i "
3195 "bytes, now discarded: "
3196 "0x%04X\n",
3197 peasycap->field_fill,
3198 videofieldamount,
3199 (0xFF00 &
3200 peasycap->field_buffer
3201 [peasycap->field_fill][0].
3202 kount));
3203 (peasycap->field_fill)++;
3205 if (FIELD_BUFFER_MANY <=
3206 peasycap->field_fill)
3207 peasycap->field_fill = 0;
3208 peasycap->field_page = 0;
3209 pfield_buffer =
3210 &peasycap->field_buffer
3211 [peasycap->field_fill]
3212 [peasycap->field_page];
3213 pfield_buffer->pto =
3214 pfield_buffer->pgo;
3216 JOM(8, "bumped to: %i=peasycap->"
3217 "field_fill %i=parity\n",
3218 peasycap->field_fill,
3219 0x00FF & pfield_buffer->kount);
3221 if (8 == more) {
3222 JOM(8, "end-of-field: received "
3223 "parity byte 0x%02X\n",
3224 (0xFF & *pu));
3225 if (0x40 & *pu)
3226 pfield_buffer->kount = 0x0000;
3227 else
3228 pfield_buffer->kount = 0x0001;
3229 pfield_buffer->input = 0x08 |
3230 (0x07 & peasycap->input);
3231 JOM(8, "end-of-field: 0x%02X=kount\n",
3232 0xFF & pfield_buffer->kount);
3235 /*---------------------------------------------------------------------------*/
3237 * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
3239 /*---------------------------------------------------------------------------*/
3240 pu += leap;
3241 more -= leap;
3243 if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
3244 SAM("ERROR: bad peasycap->field_fill\n");
3245 return;
3247 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
3248 peasycap->field_page) {
3249 SAM("ERROR: bad peasycap->field_page\n");
3250 return;
3252 pfield_buffer = &peasycap->field_buffer
3253 [peasycap->field_fill][peasycap->field_page];
3254 while (more) {
3255 pfield_buffer = &peasycap->field_buffer
3256 [peasycap->field_fill]
3257 [peasycap->field_page];
3258 if (PAGE_SIZE < (pfield_buffer->pto -
3259 pfield_buffer->pgo)) {
3260 SAM("ERROR: bad pfield_buffer->pto\n");
3261 return;
3263 if (PAGE_SIZE == (pfield_buffer->pto -
3264 pfield_buffer->pgo)) {
3265 (peasycap->field_page)++;
3266 if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
3267 peasycap->field_page) {
3268 JOM(16, "wrapping peasycap->"
3269 "field_page\n");
3270 peasycap->field_page = 0;
3272 pfield_buffer = &peasycap->
3273 field_buffer
3274 [peasycap->field_fill]
3275 [peasycap->field_page];
3276 pfield_buffer->pto =
3277 pfield_buffer->pgo;
3278 pfield_buffer->input = 0x08 |
3279 (0x07 & peasycap->input);
3280 if ((peasycap->field_buffer[peasycap->
3281 field_fill][0]).
3282 input !=
3283 pfield_buffer->input)
3284 (peasycap->field_buffer
3285 [peasycap->field_fill]
3286 [0]).kount |= 0x1000;
3289 much = PAGE_SIZE - (int)(pfield_buffer->pto -
3290 pfield_buffer->pgo);
3292 if (much > more)
3293 much = more;
3294 memcpy(pfield_buffer->pto, pu, much);
3295 pu += much;
3296 (pfield_buffer->pto) += much;
3297 more -= much;
3303 /*---------------------------------------------------------------------------*/
3305 * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
3307 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
3308 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
3310 /*---------------------------------------------------------------------------*/
3311 if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
3312 SAM("easycap driver shutting down on condition green\n");
3313 peasycap->status = 1;
3314 peasycap->video_eof = 1;
3315 peasycap->video_junk = 0;
3316 wake_up_interruptible(&peasycap->wq_video);
3317 #if !defined(PERSEVERE)
3318 peasycap->audio_eof = 1;
3319 wake_up_interruptible(&peasycap->wq_audio);
3320 #endif /*PERSEVERE*/
3321 return;
3323 if (peasycap->video_isoc_streaming) {
3324 rc = usb_submit_urb(purb, GFP_ATOMIC);
3325 if (0 != rc) {
3326 switch (rc) {
3327 case -ENOMEM: {
3328 SAM("ENOMEM\n"); break;
3330 case -ENODEV: {
3331 SAM("ENODEV\n"); break;
3333 case -ENXIO: {
3334 SAM("ENXIO\n"); break;
3336 case -EINVAL: {
3337 SAM("EINVAL\n"); break;
3339 case -EAGAIN: {
3340 SAM("EAGAIN\n"); break;
3342 case -EFBIG: {
3343 SAM("EFBIG\n"); break;
3345 case -EPIPE: {
3346 SAM("EPIPE\n"); break;
3348 case -EMSGSIZE: {
3349 SAM("EMSGSIZE\n"); break;
3351 case -ENOSPC: {
3352 SAM("ENOSPC\n"); break;
3354 default: {
3355 SAM("0x%08X\n", rc); break;
3358 if (-ENODEV != rc)
3359 SAM("ERROR: while %i=video_idle, "
3360 "usb_submit_urb() "
3361 "failed with rc:\n",
3362 peasycap->video_idle);
3365 return;
3367 /*****************************************************************************/
3368 /*---------------------------------------------------------------------------*/
3370 * WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
3371 * TIMES, ONCE FOR EACH OF THE THREE INTERFACES. BEWARE.
3373 /*---------------------------------------------------------------------------*/
3375 easycap_usb_probe(struct usb_interface *pusb_interface,
3376 const struct usb_device_id *pusb_device_id)
3378 struct usb_device *pusb_device, *pusb_device1;
3379 struct usb_host_interface *pusb_host_interface;
3380 struct usb_endpoint_descriptor *pepd;
3381 struct usb_interface_descriptor *pusb_interface_descriptor;
3382 struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
3383 struct urb *purb;
3384 struct easycap *peasycap;
3385 int ndong;
3386 struct data_urb *pdata_urb;
3387 size_t wMaxPacketSize;
3388 int ISOCwMaxPacketSize;
3389 int BULKwMaxPacketSize;
3390 int INTwMaxPacketSize;
3391 int CTRLwMaxPacketSize;
3392 __u8 bEndpointAddress;
3393 __u8 ISOCbEndpointAddress;
3394 __u8 INTbEndpointAddress;
3395 int isin, i, j, k, m, rc;
3396 __u8 bInterfaceNumber;
3397 __u8 bInterfaceClass;
3398 __u8 bInterfaceSubClass;
3399 void *pbuf;
3400 int okalt[8], isokalt;
3401 int okepn[8];
3402 int okmps[8];
3403 int maxpacketsize;
3404 __u16 mask;
3405 __s32 value;
3406 struct easycap_format *peasycap_format;
3407 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3408 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
3409 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
3410 struct v4l2_device *pv4l2_device;
3411 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
3412 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3413 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3415 /* setup modules params */
3417 if ((struct usb_interface *)NULL == pusb_interface) {
3418 SAY("ERROR: pusb_interface is NULL\n");
3419 return -EFAULT;
3421 peasycap = (struct easycap *)NULL;
3422 /*---------------------------------------------------------------------------*/
3424 * GET POINTER TO STRUCTURE usb_device
3426 /*---------------------------------------------------------------------------*/
3427 pusb_device1 = container_of(pusb_interface->dev.parent,
3428 struct usb_device, dev);
3429 if ((struct usb_device *)NULL == pusb_device1) {
3430 SAY("ERROR: pusb_device1 is NULL\n");
3431 return -EFAULT;
3433 pusb_device = usb_get_dev(pusb_device1);
3434 if ((struct usb_device *)NULL == pusb_device) {
3435 SAY("ERROR: pusb_device is NULL\n");
3436 return -EFAULT;
3438 if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) {
3439 JOT(4, "ERROR: pusb_device1 != pusb_device\n");
3440 return -EFAULT;
3442 JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
3443 /*---------------------------------------------------------------------------*/
3444 pusb_host_interface = pusb_interface->cur_altsetting;
3445 if (NULL == pusb_host_interface) {
3446 SAY("ERROR: pusb_host_interface is NULL\n");
3447 return -EFAULT;
3449 pusb_interface_descriptor = &(pusb_host_interface->desc);
3450 if (NULL == pusb_interface_descriptor) {
3451 SAY("ERROR: pusb_interface_descriptor is NULL\n");
3452 return -EFAULT;
3454 /*---------------------------------------------------------------------------*/
3456 * GET PROPERTIES OF PROBED INTERFACE
3458 /*---------------------------------------------------------------------------*/
3459 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
3460 bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
3461 bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
3463 JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n",
3464 bInterfaceNumber, pusb_interface->num_altsetting);
3465 JOT(4, "intf[%i]: pusb_interface->cur_altsetting - "
3466 "pusb_interface->altsetting=%li\n", bInterfaceNumber,
3467 (long int)(pusb_interface->cur_altsetting -
3468 pusb_interface->altsetting));
3469 switch (bInterfaceClass) {
3470 case USB_CLASS_AUDIO: {
3471 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n",
3472 bInterfaceNumber, bInterfaceClass); break;
3474 case USB_CLASS_VIDEO: {
3475 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n",
3476 bInterfaceNumber, bInterfaceClass); break;
3478 case USB_CLASS_VENDOR_SPEC: {
3479 JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n",
3480 bInterfaceNumber, bInterfaceClass); break;
3482 default:
3483 break;
3485 switch (bInterfaceSubClass) {
3486 case 0x01: {
3487 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n",
3488 bInterfaceNumber, bInterfaceSubClass); break;
3490 case 0x02: {
3491 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n",
3492 bInterfaceNumber, bInterfaceSubClass); break;
3494 case 0x03: {
3495 JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n",
3496 bInterfaceNumber, bInterfaceSubClass); break;
3498 default:
3499 break;
3501 /*---------------------------------------------------------------------------*/
3502 pusb_interface_assoc_descriptor = pusb_interface->intf_assoc;
3503 if (NULL != pusb_interface_assoc_descriptor) {
3504 JOT(4, "intf[%i]: bFirstInterface=0x%02X bInterfaceCount=0x%02X\n",
3505 bInterfaceNumber,
3506 pusb_interface_assoc_descriptor->bFirstInterface,
3507 pusb_interface_assoc_descriptor->bInterfaceCount);
3508 } else {
3509 JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n",
3510 bInterfaceNumber);
3512 /*---------------------------------------------------------------------------*/
3514 * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
3515 * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS
3516 * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE EasyCAP WAS
3517 * PHYSICALLY UNPLUGGED.
3519 * THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
3520 * INTERFACES 1 AND 2 ARE PROBED.
3522 /*---------------------------------------------------------------------------*/
3523 if (0 == bInterfaceNumber) {
3524 peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
3525 if (NULL == peasycap) {
3526 SAY("ERROR: Could not allocate peasycap\n");
3527 return -ENOMEM;
3529 SAM("allocated 0x%08lX=peasycap\n", (unsigned long int) peasycap);
3530 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3531 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
3532 SAM("where 0x%08lX=&peasycap->video_device\n",
3533 (unsigned long int) &peasycap->video_device);
3534 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
3535 SAM("and 0x%08lX=&peasycap->v4l2_device\n",
3536 (unsigned long int) &peasycap->v4l2_device);
3537 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
3538 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3539 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
3540 /*---------------------------------------------------------------------------*/
3542 * PERFORM URGENT INTIALIZATIONS ...
3544 /*---------------------------------------------------------------------------*/
3545 peasycap->minor = -1;
3546 strcpy(&peasycap->telltale[0], TELLTALE);
3547 kref_init(&peasycap->kref);
3548 JOM(8, "intf[%i]: after kref_init(..._video) "
3549 "%i=peasycap->kref.refcount.counter\n",
3550 bInterfaceNumber, peasycap->kref.refcount.counter);
3552 /* module params */
3553 peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
3555 init_waitqueue_head(&peasycap->wq_video);
3556 init_waitqueue_head(&peasycap->wq_audio);
3557 init_waitqueue_head(&peasycap->wq_trigger);
3559 if (mutex_lock_interruptible(&mutex_dongle)) {
3560 SAY("ERROR: cannot down mutex_dongle\n");
3561 return -ERESTARTSYS;
3562 } else {
3563 /*---------------------------------------------------------------------------*/
3565 * FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
3566 * TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
3568 * NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
3569 * PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
3570 * EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
3572 /*---------------------------------------------------------------------------*/
3573 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3574 if ((NULL == easycapdc60_dongle[ndong].peasycap) &&
3575 (!mutex_is_locked(&easycapdc60_dongle
3576 [ndong].mutex_video)) &&
3577 (!mutex_is_locked(&easycapdc60_dongle
3578 [ndong].mutex_audio))) {
3579 easycapdc60_dongle[ndong].peasycap = peasycap;
3580 peasycap->isdongle = ndong;
3581 JOM(8, "intf[%i]: peasycap-->easycap"
3582 "_dongle[%i].peasycap\n",
3583 bInterfaceNumber, ndong);
3584 break;
3587 if (DONGLE_MANY <= ndong) {
3588 SAM("ERROR: too many dongles\n");
3589 mutex_unlock(&mutex_dongle);
3590 return -ENOMEM;
3592 mutex_unlock(&mutex_dongle);
3594 peasycap->allocation_video_struct = sizeof(struct easycap);
3595 peasycap->allocation_video_page = 0;
3596 peasycap->allocation_video_urb = 0;
3597 peasycap->allocation_audio_struct = 0;
3598 peasycap->allocation_audio_page = 0;
3599 peasycap->allocation_audio_urb = 0;
3601 /*---------------------------------------------------------------------------*/
3603 * ... AND FURTHER INITIALIZE THE STRUCTURE
3605 /*---------------------------------------------------------------------------*/
3606 peasycap->pusb_device = pusb_device;
3607 peasycap->pusb_interface = pusb_interface;
3609 peasycap->ilk = 0;
3610 peasycap->microphone = false;
3612 peasycap->video_interface = -1;
3613 peasycap->video_altsetting_on = -1;
3614 peasycap->video_altsetting_off = -1;
3615 peasycap->video_endpointnumber = -1;
3616 peasycap->video_isoc_maxframesize = -1;
3617 peasycap->video_isoc_buffer_size = -1;
3619 peasycap->audio_interface = -1;
3620 peasycap->audio_altsetting_on = -1;
3621 peasycap->audio_altsetting_off = -1;
3622 peasycap->audio_endpointnumber = -1;
3623 peasycap->audio_isoc_maxframesize = -1;
3624 peasycap->audio_isoc_buffer_size = -1;
3626 peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
3628 for (k = 0; k < INPUT_MANY; k++)
3629 peasycap->lost[k] = 0;
3630 peasycap->skip = 0;
3631 peasycap->skipped = 0;
3632 peasycap->offerfields = 0;
3633 /*---------------------------------------------------------------------------*/
3635 * DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
3637 /*---------------------------------------------------------------------------*/
3638 rc = fillin_formats();
3639 if (0 > rc) {
3640 SAM("ERROR: fillin_formats() returned %i\n", rc);
3641 return -EFAULT;
3643 JOM(4, "%i formats available\n", rc);
3644 /*---------------------------------------------------------------------------*/
3646 * ... AND POPULATE easycap.inputset[]
3648 /*---------------------------------------------------------------------------*/
3649 for (k = 0; k < INPUT_MANY; k++) {
3650 peasycap->inputset[k].input_ok = 0;
3651 peasycap->inputset[k].standard_offset_ok = 0;
3652 peasycap->inputset[k].format_offset_ok = 0;
3653 peasycap->inputset[k].brightness_ok = 0;
3654 peasycap->inputset[k].contrast_ok = 0;
3655 peasycap->inputset[k].saturation_ok = 0;
3656 peasycap->inputset[k].hue_ok = 0;
3658 if (true == peasycap->ntsc) {
3659 i = 0;
3660 m = 0;
3661 mask = 0;
3662 while (0xFFFF != easycap_standard[i].mask) {
3663 if (NTSC_M == easycap_standard[i].
3664 v4l2_standard.index) {
3665 m++;
3666 for (k = 0; k < INPUT_MANY; k++) {
3667 peasycap->inputset[k].
3668 standard_offset = i;
3670 mask = easycap_standard[i].mask;
3672 i++;
3674 } else {
3675 i = 0;
3676 m = 0;
3677 mask = 0;
3678 while (0xFFFF != easycap_standard[i].mask) {
3679 if (PAL_BGHIN == easycap_standard[i].
3680 v4l2_standard.index) {
3681 m++;
3682 for (k = 0; k < INPUT_MANY; k++) {
3683 peasycap->inputset[k].
3684 standard_offset = i;
3686 mask = easycap_standard[i].mask;
3688 i++;
3692 if (1 != m) {
3693 SAM("MISTAKE: easycap.inputset[].standard_offset "
3694 "unpopulated, %i=m\n", m);
3695 return -ENOENT;
3698 peasycap_format = &easycap_format[0];
3699 i = 0;
3700 m = 0;
3701 while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
3702 if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
3703 (peasycap_format->
3704 v4l2_format.fmt.pix.field ==
3705 V4L2_FIELD_NONE) &&
3706 (peasycap_format->
3707 v4l2_format.fmt.pix.pixelformat ==
3708 V4L2_PIX_FMT_UYVY) &&
3709 (peasycap_format->
3710 v4l2_format.fmt.pix.width ==
3711 640) &&
3712 (peasycap_format->
3713 v4l2_format.fmt.pix.height == 480)) {
3714 m++;
3715 for (k = 0; k < INPUT_MANY; k++)
3716 peasycap->inputset[k].format_offset = i;
3717 break;
3719 peasycap_format++;
3720 i++;
3722 if (1 != m) {
3723 SAM("MISTAKE: easycap.inputset[].format_offset unpopulated\n");
3724 return -ENOENT;
3727 i = 0;
3728 m = 0;
3729 while (0xFFFFFFFF != easycap_control[i].id) {
3730 value = easycap_control[i].default_value;
3731 if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
3732 m++;
3733 for (k = 0; k < INPUT_MANY; k++)
3734 peasycap->inputset[k].brightness = value;
3735 } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
3736 m++;
3737 for (k = 0; k < INPUT_MANY; k++)
3738 peasycap->inputset[k].contrast = value;
3739 } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
3740 m++;
3741 for (k = 0; k < INPUT_MANY; k++)
3742 peasycap->inputset[k].saturation = value;
3743 } else if (V4L2_CID_HUE == easycap_control[i].id) {
3744 m++;
3745 for (k = 0; k < INPUT_MANY; k++)
3746 peasycap->inputset[k].hue = value;
3748 i++;
3750 if (4 != m) {
3751 SAM("MISTAKE: easycap.inputset[].brightness,... "
3752 "underpopulated\n");
3753 return -ENOENT;
3755 for (k = 0; k < INPUT_MANY; k++)
3756 peasycap->inputset[k].input = k;
3757 JOM(4, "populated easycap.inputset[]\n");
3758 JOM(4, "finished initialization\n");
3759 } else {
3760 /*---------------------------------------------------------------------------*/
3762 * FIXME
3764 * IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
3765 * THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
3767 /*---------------------------------------------------------------------------*/
3768 for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
3769 if (pusb_device == easycapdc60_dongle[ndong].peasycap->
3770 pusb_device) {
3771 peasycap = easycapdc60_dongle[ndong].peasycap;
3772 JOT(8, "intf[%i]: easycapdc60_dongle[%i].peasycap-->"
3773 "peasycap\n", bInterfaceNumber, ndong);
3774 break;
3777 if (DONGLE_MANY <= ndong) {
3778 SAY("ERROR: peasycap is unknown when probing interface %i\n",
3779 bInterfaceNumber);
3780 return -ENODEV;
3782 if (NULL == peasycap) {
3783 SAY("ERROR: peasycap is NULL when probing interface %i\n",
3784 bInterfaceNumber);
3785 return -ENODEV;
3787 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
3789 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
3790 #else
3791 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
3792 /*---------------------------------------------------------------------------*/
3794 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
3795 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
3796 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
3797 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
3799 /*---------------------------------------------------------------------------*/
3800 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
3801 pv4l2_device = usb_get_intfdata(pusb_interface);
3802 if ((struct v4l2_device *)NULL == pv4l2_device) {
3803 SAY("ERROR: pv4l2_device is NULL\n");
3804 return -ENODEV;
3806 peasycap = (struct easycap *)
3807 container_of(pv4l2_device, struct easycap, v4l2_device);
3809 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
3810 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
3812 /*---------------------------------------------------------------------------*/
3813 if ((USB_CLASS_VIDEO == bInterfaceClass) ||
3814 (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
3815 if (-1 == peasycap->video_interface) {
3816 peasycap->video_interface = bInterfaceNumber;
3817 JOM(4, "setting peasycap->video_interface=%i\n",
3818 peasycap->video_interface);
3819 } else {
3820 if (peasycap->video_interface != bInterfaceNumber) {
3821 SAM("ERROR: attempting to reset "
3822 "peasycap->video_interface\n");
3823 SAM("...... continuing with "
3824 "%i=peasycap->video_interface\n",
3825 peasycap->video_interface);
3828 } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
3829 (0x02 == bInterfaceSubClass)) {
3830 if (-1 == peasycap->audio_interface) {
3831 peasycap->audio_interface = bInterfaceNumber;
3832 JOM(4, "setting peasycap->audio_interface=%i\n",
3833 peasycap->audio_interface);
3834 } else {
3835 if (peasycap->audio_interface != bInterfaceNumber) {
3836 SAM("ERROR: attempting to reset "
3837 "peasycap->audio_interface\n");
3838 SAM("...... continuing with "
3839 "%i=peasycap->audio_interface\n",
3840 peasycap->audio_interface);
3844 /*---------------------------------------------------------------------------*/
3846 * INVESTIGATE ALL ALTSETTINGS.
3847 * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
3849 /*---------------------------------------------------------------------------*/
3850 isokalt = 0;
3852 for (i = 0; i < pusb_interface->num_altsetting; i++) {
3853 pusb_host_interface = &(pusb_interface->altsetting[i]);
3854 if ((struct usb_host_interface *)NULL == pusb_host_interface) {
3855 SAM("ERROR: pusb_host_interface is NULL\n");
3856 return -EFAULT;
3858 pusb_interface_descriptor = &(pusb_host_interface->desc);
3859 if ((struct usb_interface_descriptor *)NULL ==
3860 pusb_interface_descriptor) {
3861 SAM("ERROR: pusb_interface_descriptor is NULL\n");
3862 return -EFAULT;
3865 JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n",
3866 bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
3867 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n",
3868 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
3869 JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n",
3870 bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
3871 JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n",
3872 bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
3873 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n",
3874 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
3875 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n",
3876 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
3877 JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n",
3878 bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
3879 JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n",
3880 bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
3882 ISOCwMaxPacketSize = -1;
3883 BULKwMaxPacketSize = -1;
3884 INTwMaxPacketSize = -1;
3885 CTRLwMaxPacketSize = -1;
3886 ISOCbEndpointAddress = 0;
3887 INTbEndpointAddress = 0;
3889 if (0 == pusb_interface_descriptor->bNumEndpoints)
3890 JOM(4, "intf[%i]alt[%i] has no endpoints\n",
3891 bInterfaceNumber, i);
3892 /*---------------------------------------------------------------------------*/
3893 for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
3894 pepd = &(pusb_host_interface->endpoint[j].desc);
3895 if ((struct usb_endpoint_descriptor *)NULL == pepd) {
3896 SAM("ERROR: pepd is NULL.\n");
3897 SAM("...... skipping\n");
3898 continue;
3900 wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
3901 bEndpointAddress = pepd->bEndpointAddress;
3903 JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n",
3904 bInterfaceNumber, i, j,
3905 pepd->bEndpointAddress);
3906 JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n",
3907 bInterfaceNumber, i, j,
3908 pepd->bmAttributes);
3909 JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n",
3910 bInterfaceNumber, i, j,
3911 pepd->wMaxPacketSize);
3912 JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
3913 bInterfaceNumber, i, j,
3914 pepd->bInterval);
3916 if (pepd->bEndpointAddress & USB_DIR_IN) {
3917 JOM(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",
3918 bInterfaceNumber, i, j);
3919 isin = 1;
3920 } else {
3921 JOM(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",
3922 bInterfaceNumber, i, j);
3923 SAM("ERROR: OUT endpoint unexpected\n");
3924 SAM("...... continuing\n");
3925 isin = 0;
3927 if ((pepd->bmAttributes &
3928 USB_ENDPOINT_XFERTYPE_MASK) ==
3929 USB_ENDPOINT_XFER_ISOC) {
3930 JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",
3931 bInterfaceNumber, i, j);
3932 if (isin) {
3933 switch (bInterfaceClass) {
3934 case USB_CLASS_VIDEO:
3935 case USB_CLASS_VENDOR_SPEC: {
3936 if (!peasycap) {
3937 SAM("MISTAKE: "
3938 "peasycap is NULL\n");
3939 return -EFAULT;
3941 if (pepd->wMaxPacketSize) {
3942 if (8 > isokalt) {
3943 okalt[isokalt] = i;
3944 JOM(4,
3945 "%i=okalt[%i]\n",
3946 okalt[isokalt],
3947 isokalt);
3948 okepn[isokalt] =
3949 pepd->
3950 bEndpointAddress &
3951 0x0F;
3952 JOM(4,
3953 "%i=okepn[%i]\n",
3954 okepn[isokalt],
3955 isokalt);
3956 okmps[isokalt] =
3957 le16_to_cpu(pepd->
3958 wMaxPacketSize);
3959 JOM(4,
3960 "%i=okmps[%i]\n",
3961 okmps[isokalt],
3962 isokalt);
3963 isokalt++;
3965 } else {
3966 if (-1 == peasycap->
3967 video_altsetting_off) {
3968 peasycap->
3969 video_altsetting_off =
3971 JOM(4, "%i=video_"
3972 "altsetting_off "
3973 "<====\n",
3974 peasycap->
3975 video_altsetting_off);
3976 } else {
3977 SAM("ERROR: peasycap"
3978 "->video_altsetting_"
3979 "off already set\n");
3980 SAM("...... "
3981 "continuing with "
3982 "%i=peasycap->video_"
3983 "altsetting_off\n",
3984 peasycap->
3985 video_altsetting_off);
3988 break;
3990 case USB_CLASS_AUDIO: {
3991 if (0x02 != bInterfaceSubClass)
3992 break;
3993 if (!peasycap) {
3994 SAM("MISTAKE: "
3995 "peasycap is NULL\n");
3996 return -EFAULT;
3998 if (pepd->wMaxPacketSize) {
3999 if (8 > isokalt) {
4000 okalt[isokalt] = i ;
4001 JOM(4,
4002 "%i=okalt[%i]\n",
4003 okalt[isokalt],
4004 isokalt);
4005 okepn[isokalt] =
4006 pepd->
4007 bEndpointAddress &
4008 0x0F;
4009 JOM(4,
4010 "%i=okepn[%i]\n",
4011 okepn[isokalt],
4012 isokalt);
4013 okmps[isokalt] =
4014 le16_to_cpu(pepd->
4015 wMaxPacketSize);
4016 JOM(4,
4017 "%i=okmps[%i]\n",
4018 okmps[isokalt],
4019 isokalt);
4020 isokalt++;
4022 } else {
4023 if (-1 == peasycap->
4024 audio_altsetting_off) {
4025 peasycap->
4026 audio_altsetting_off =
4028 JOM(4, "%i=audio_"
4029 "altsetting_off "
4030 "<====\n",
4031 peasycap->
4032 audio_altsetting_off);
4033 } else {
4034 SAM("ERROR: peasycap"
4035 "->audio_altsetting_"
4036 "off already set\n");
4037 SAM("...... "
4038 "continuing with "
4039 "%i=peasycap->"
4040 "audio_altsetting_"
4041 "off\n",
4042 peasycap->
4043 audio_altsetting_off);
4046 break;
4048 default:
4049 break;
4052 } else if ((pepd->bmAttributes &
4053 USB_ENDPOINT_XFERTYPE_MASK) ==
4054 USB_ENDPOINT_XFER_BULK) {
4055 JOM(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",
4056 bInterfaceNumber, i, j);
4057 } else if ((pepd->bmAttributes &
4058 USB_ENDPOINT_XFERTYPE_MASK) ==
4059 USB_ENDPOINT_XFER_INT) {
4060 JOM(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",
4061 bInterfaceNumber, i, j);
4062 } else {
4063 JOM(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",
4064 bInterfaceNumber, i, j);
4066 if (0 == pepd->wMaxPacketSize) {
4067 JOM(4, "intf[%i]alt[%i]end[%i] "
4068 "has zero packet size\n",
4069 bInterfaceNumber, i, j);
4073 /*---------------------------------------------------------------------------*/
4075 * PERFORM INITIALIZATION OF THE PROBED INTERFACE
4077 /*---------------------------------------------------------------------------*/
4078 JOM(4, "initialization begins for interface %i\n",
4079 pusb_interface_descriptor->bInterfaceNumber);
4080 switch (bInterfaceNumber) {
4081 /*---------------------------------------------------------------------------*/
4083 * INTERFACE 0 IS THE VIDEO INTERFACE
4085 /*---------------------------------------------------------------------------*/
4086 case 0: {
4087 if (!peasycap) {
4088 SAM("MISTAKE: peasycap is NULL\n");
4089 return -EFAULT;
4091 if (!isokalt) {
4092 SAM("ERROR: no viable video_altsetting_on\n");
4093 return -ENOENT;
4094 } else {
4095 peasycap->video_altsetting_on = okalt[isokalt - 1];
4096 JOM(4, "%i=video_altsetting_on <====\n",
4097 peasycap->video_altsetting_on);
4099 /*---------------------------------------------------------------------------*/
4101 * DECIDE THE VIDEO STREAMING PARAMETERS
4103 /*---------------------------------------------------------------------------*/
4104 peasycap->video_endpointnumber = okepn[isokalt - 1];
4105 JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
4106 maxpacketsize = okmps[isokalt - 1];
4107 if (USB_2_0_MAXPACKETSIZE > maxpacketsize) {
4108 peasycap->video_isoc_maxframesize = maxpacketsize;
4109 } else {
4110 peasycap->video_isoc_maxframesize =
4111 USB_2_0_MAXPACKETSIZE;
4113 JOM(4, "%i=video_isoc_maxframesize\n",
4114 peasycap->video_isoc_maxframesize);
4115 if (0 >= peasycap->video_isoc_maxframesize) {
4116 SAM("ERROR: bad video_isoc_maxframesize\n");
4117 SAM(" possibly because port is USB 1.1\n");
4118 return -ENOENT;
4120 peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
4121 JOM(4, "%i=video_isoc_framesperdesc\n",
4122 peasycap->video_isoc_framesperdesc);
4123 if (0 >= peasycap->video_isoc_framesperdesc) {
4124 SAM("ERROR: bad video_isoc_framesperdesc\n");
4125 return -ENOENT;
4127 peasycap->video_isoc_buffer_size =
4128 peasycap->video_isoc_maxframesize *
4129 peasycap->video_isoc_framesperdesc;
4130 JOM(4, "%i=video_isoc_buffer_size\n",
4131 peasycap->video_isoc_buffer_size);
4132 if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
4133 peasycap->video_isoc_buffer_size) {
4134 SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
4135 return -EFAULT;
4137 /*---------------------------------------------------------------------------*/
4138 if (-1 == peasycap->video_interface) {
4139 SAM("MISTAKE: video_interface is unset\n");
4140 return -EFAULT;
4142 if (-1 == peasycap->video_altsetting_on) {
4143 SAM("MISTAKE: video_altsetting_on is unset\n");
4144 return -EFAULT;
4146 if (-1 == peasycap->video_altsetting_off) {
4147 SAM("MISTAKE: video_interface_off is unset\n");
4148 return -EFAULT;
4150 if (-1 == peasycap->video_endpointnumber) {
4151 SAM("MISTAKE: video_endpointnumber is unset\n");
4152 return -EFAULT;
4154 if (-1 == peasycap->video_isoc_maxframesize) {
4155 SAM("MISTAKE: video_isoc_maxframesize is unset\n");
4156 return -EFAULT;
4158 if (-1 == peasycap->video_isoc_buffer_size) {
4159 SAM("MISTAKE: video_isoc_buffer_size is unset\n");
4160 return -EFAULT;
4162 /*---------------------------------------------------------------------------*/
4164 * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
4166 /*---------------------------------------------------------------------------*/
4167 INIT_LIST_HEAD(&(peasycap->urb_video_head));
4168 peasycap->purb_video_head = &(peasycap->urb_video_head);
4169 /*---------------------------------------------------------------------------*/
4170 JOM(4, "allocating %i frame buffers of size %li\n",
4171 FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
4172 JOM(4, ".... each scattered over %li pages\n",
4173 FRAME_BUFFER_SIZE/PAGE_SIZE);
4175 for (k = 0; k < FRAME_BUFFER_MANY; k++) {
4176 for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
4177 if ((void *)NULL != peasycap->frame_buffer[k][m].pgo)
4178 SAM("attempting to reallocate frame "
4179 " buffers\n");
4180 else {
4181 pbuf = (void *)__get_free_page(GFP_KERNEL);
4182 if ((void *)NULL == pbuf) {
4183 SAM("ERROR: Could not allocate frame "
4184 "buffer %i page %i\n", k, m);
4185 return -ENOMEM;
4186 } else
4187 peasycap->allocation_video_page += 1;
4188 peasycap->frame_buffer[k][m].pgo = pbuf;
4190 peasycap->frame_buffer[k][m].pto =
4191 peasycap->frame_buffer[k][m].pgo;
4195 peasycap->frame_fill = 0;
4196 peasycap->frame_read = 0;
4197 JOM(4, "allocation of frame buffers done: %i pages\n", k *
4199 /*---------------------------------------------------------------------------*/
4200 JOM(4, "allocating %i field buffers of size %li\n",
4201 FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
4202 JOM(4, ".... each scattered over %li pages\n",
4203 FIELD_BUFFER_SIZE/PAGE_SIZE);
4205 for (k = 0; k < FIELD_BUFFER_MANY; k++) {
4206 for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
4207 if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
4208 SAM("ERROR: attempting to reallocate "
4209 "field buffers\n");
4210 } else {
4211 pbuf = (void *) __get_free_page(GFP_KERNEL);
4212 if ((void *)NULL == pbuf) {
4213 SAM("ERROR: Could not allocate field"
4214 " buffer %i page %i\n", k, m);
4215 return -ENOMEM;
4217 else
4218 peasycap->allocation_video_page += 1;
4219 peasycap->field_buffer[k][m].pgo = pbuf;
4221 peasycap->field_buffer[k][m].pto =
4222 peasycap->field_buffer[k][m].pgo;
4224 peasycap->field_buffer[k][0].kount = 0x0200;
4226 peasycap->field_fill = 0;
4227 peasycap->field_page = 0;
4228 peasycap->field_read = 0;
4229 JOM(4, "allocation of field buffers done: %i pages\n", k *
4231 /*---------------------------------------------------------------------------*/
4232 JOM(4, "allocating %i isoc video buffers of size %i\n",
4233 VIDEO_ISOC_BUFFER_MANY,
4234 peasycap->video_isoc_buffer_size);
4235 JOM(4, ".... each occupying contiguous memory pages\n");
4237 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
4238 pbuf = (void *)__get_free_pages(GFP_KERNEL, VIDEO_ISOC_ORDER);
4239 if (NULL == pbuf) {
4240 SAM("ERROR: Could not allocate isoc video buffer "
4241 "%i\n", k);
4242 return -ENOMEM;
4243 } else
4244 peasycap->allocation_video_page +=
4245 ((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
4247 peasycap->video_isoc_buffer[k].pgo = pbuf;
4248 peasycap->video_isoc_buffer[k].pto = pbuf +
4249 peasycap->video_isoc_buffer_size;
4250 peasycap->video_isoc_buffer[k].kount = k;
4252 JOM(4, "allocation of isoc video buffers done: %i pages\n",
4253 k * (0x01 << VIDEO_ISOC_ORDER));
4254 /*---------------------------------------------------------------------------*/
4256 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4258 /*---------------------------------------------------------------------------*/
4259 JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
4260 JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
4261 peasycap->video_isoc_framesperdesc);
4262 JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
4263 peasycap->video_isoc_maxframesize);
4264 JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
4265 peasycap->video_isoc_buffer_size);
4267 for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
4268 purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
4269 GFP_KERNEL);
4270 if (NULL == purb) {
4271 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4272 "%i\n", k);
4273 return -ENOMEM;
4274 } else
4275 peasycap->allocation_video_urb += 1;
4276 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4277 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
4278 if (NULL == pdata_urb) {
4279 SAM("ERROR: Could not allocate struct data_urb.\n");
4280 return -ENOMEM;
4281 } else
4282 peasycap->allocation_video_struct +=
4283 sizeof(struct data_urb);
4285 pdata_urb->purb = purb;
4286 pdata_urb->isbuf = k;
4287 pdata_urb->length = 0;
4288 list_add_tail(&(pdata_urb->list_head),
4289 peasycap->purb_video_head);
4290 /*---------------------------------------------------------------------------*/
4292 * ... AND INITIALIZE THEM
4294 /*---------------------------------------------------------------------------*/
4295 if (!k) {
4296 JOM(4, "initializing video urbs thus:\n");
4297 JOM(4, " purb->interval = 1;\n");
4298 JOM(4, " purb->dev = peasycap->pusb_device;\n");
4299 JOM(4, " purb->pipe = usb_rcvisocpipe"
4300 "(peasycap->pusb_device,%i);\n",
4301 peasycap->video_endpointnumber);
4302 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4303 JOM(4, " purb->transfer_buffer = peasycap->"
4304 "video_isoc_buffer[.].pgo;\n");
4305 JOM(4, " purb->transfer_buffer_length = %i;\n",
4306 peasycap->video_isoc_buffer_size);
4307 JOM(4, " purb->complete = easycap_complete;\n");
4308 JOM(4, " purb->context = peasycap;\n");
4309 JOM(4, " purb->start_frame = 0;\n");
4310 JOM(4, " purb->number_of_packets = %i;\n",
4311 peasycap->video_isoc_framesperdesc);
4312 JOM(4, " for (j = 0; j < %i; j++)\n",
4313 peasycap->video_isoc_framesperdesc);
4314 JOM(4, " {\n");
4315 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
4316 peasycap->video_isoc_maxframesize);
4317 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
4318 peasycap->video_isoc_maxframesize);
4319 JOM(4, " }\n");
4322 purb->interval = 1;
4323 purb->dev = peasycap->pusb_device;
4324 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
4325 peasycap->video_endpointnumber);
4326 purb->transfer_flags = URB_ISO_ASAP;
4327 purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
4328 purb->transfer_buffer_length =
4329 peasycap->video_isoc_buffer_size;
4330 purb->complete = easycap_complete;
4331 purb->context = peasycap;
4332 purb->start_frame = 0;
4333 purb->number_of_packets = peasycap->video_isoc_framesperdesc;
4334 for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
4335 purb->iso_frame_desc[j].offset = j *
4336 peasycap->video_isoc_maxframesize;
4337 purb->iso_frame_desc[j].length =
4338 peasycap->video_isoc_maxframesize;
4341 JOM(4, "allocation of %i struct urb done.\n", k);
4342 /*--------------------------------------------------------------------------*/
4344 * SAVE POINTER peasycap IN THIS INTERFACE.
4346 /*--------------------------------------------------------------------------*/
4347 usb_set_intfdata(pusb_interface, peasycap);
4348 /*---------------------------------------------------------------------------*/
4350 * IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
4351 * THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
4352 * CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
4353 * BEWARE.
4355 /*---------------------------------------------------------------------------*/
4356 #if defined(PREFER_NTSC)
4357 peasycap->ntsc = true;
4358 JOM(8, "defaulting initially to NTSC\n");
4359 #else
4360 peasycap->ntsc = false;
4361 JOM(8, "defaulting initially to PAL\n");
4362 #endif /*PREFER_NTSC*/
4363 rc = reset(peasycap);
4364 if (0 != rc) {
4365 SAM("ERROR: reset() returned %i\n", rc);
4366 return -EFAULT;
4368 /*--------------------------------------------------------------------------*/
4370 * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4372 /*--------------------------------------------------------------------------*/
4373 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
4374 if (0 != (usb_register_dev(pusb_interface, &easycap_class))) {
4375 err("Not able to get a minor for this device");
4376 usb_set_intfdata(pusb_interface, NULL);
4377 return -ENODEV;
4378 } else {
4379 (peasycap->registered_video)++;
4380 SAM("easycap attached to minor #%d\n", pusb_interface->minor);
4381 peasycap->minor = pusb_interface->minor;
4382 break;
4384 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4385 #else
4386 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4387 if (0 != (v4l2_device_register(&(pusb_interface->dev),
4388 &(peasycap->v4l2_device)))) {
4389 SAM("v4l2_device_register() failed\n");
4390 return -ENODEV;
4391 } else {
4392 JOM(4, "registered device instance: %s\n",
4393 &(peasycap->v4l2_device.name[0]));
4395 /*---------------------------------------------------------------------------*/
4397 * FIXME
4400 * THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
4402 /*---------------------------------------------------------------------------*/
4403 peasycap->video_device.v4l2_dev = (struct v4l2_device *)NULL;
4404 /*---------------------------------------------------------------------------*/
4406 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4408 strcpy(&peasycap->video_device.name[0], "easycapdc60");
4409 #if defined(EASYCAP_NEEDS_V4L2_FOPS)
4410 peasycap->video_device.fops = &v4l2_fops;
4411 #else
4412 peasycap->video_device.fops = &easycap_fops;
4413 #endif /*EASYCAP_NEEDS_V4L2_FOPS*/
4414 peasycap->video_device.minor = -1;
4415 peasycap->video_device.release = (void *)(&videodev_release);
4417 video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
4419 if (0 != (video_register_device(&(peasycap->video_device),
4420 VFL_TYPE_GRABBER, -1))) {
4421 err("Not able to register with videodev");
4422 videodev_release(&(peasycap->video_device));
4423 return -ENODEV;
4424 } else {
4425 (peasycap->registered_video)++;
4426 SAM("registered with videodev: %i=minor\n",
4427 peasycap->video_device.minor);
4428 peasycap->minor = peasycap->video_device.minor;
4430 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4431 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4433 break;
4435 /*--------------------------------------------------------------------------*/
4437 * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
4438 * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
4440 /*--------------------------------------------------------------------------*/
4441 case 1: {
4442 #if defined(EASYCAP_SILENT)
4443 return -ENOENT;
4444 #endif /*EASYCAP_SILENT*/
4445 if (!peasycap) {
4446 SAM("MISTAKE: peasycap is NULL\n");
4447 return -EFAULT;
4449 /*--------------------------------------------------------------------------*/
4451 * SAVE POINTER peasycap IN INTERFACE 1
4453 /*--------------------------------------------------------------------------*/
4454 usb_set_intfdata(pusb_interface, peasycap);
4455 JOM(4, "no initialization required for interface %i\n",
4456 pusb_interface_descriptor->bInterfaceNumber);
4457 break;
4459 /*--------------------------------------------------------------------------*/
4460 case 2: {
4461 #if defined(EASYCAP_SILENT)
4462 return -ENOENT;
4463 #endif /*EASYCAP_SILENT*/
4464 if (!peasycap) {
4465 SAM("MISTAKE: peasycap is NULL\n");
4466 return -EFAULT;
4468 if (!isokalt) {
4469 SAM("ERROR: no viable audio_altsetting_on\n");
4470 return -ENOENT;
4471 } else {
4472 peasycap->audio_altsetting_on = okalt[isokalt - 1];
4473 JOM(4, "%i=audio_altsetting_on <====\n",
4474 peasycap->audio_altsetting_on);
4477 peasycap->audio_endpointnumber = okepn[isokalt - 1];
4478 JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
4480 peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
4481 JOM(4, "%i=audio_isoc_maxframesize\n",
4482 peasycap->audio_isoc_maxframesize);
4483 if (0 >= peasycap->audio_isoc_maxframesize) {
4484 SAM("ERROR: bad audio_isoc_maxframesize\n");
4485 return -ENOENT;
4487 if (9 == peasycap->audio_isoc_maxframesize) {
4488 peasycap->ilk |= 0x02;
4489 SAM("audio hardware is microphone\n");
4490 peasycap->microphone = true;
4491 peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
4492 } else if (256 == peasycap->audio_isoc_maxframesize) {
4493 peasycap->ilk &= ~0x02;
4494 SAM("audio hardware is AC'97\n");
4495 peasycap->microphone = false;
4496 peasycap->audio_pages_per_fragment = PAGES_PER_AUDIO_FRAGMENT;
4497 } else {
4498 SAM("hardware is unidentified:\n");
4499 SAM("%i=audio_isoc_maxframesize\n",
4500 peasycap->audio_isoc_maxframesize);
4501 return -ENOENT;
4504 peasycap->audio_bytes_per_fragment =
4505 peasycap->audio_pages_per_fragment *
4506 PAGE_SIZE ;
4507 peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
4508 peasycap->audio_pages_per_fragment);
4510 JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
4511 JOM(4, "%6i=audio_pages_per_fragment\n",
4512 peasycap->audio_pages_per_fragment);
4513 JOM(4, "%6i=audio_bytes_per_fragment\n",
4514 peasycap->audio_bytes_per_fragment);
4515 JOM(4, "%6i=audio_buffer_page_many\n",
4516 peasycap->audio_buffer_page_many);
4518 peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
4520 JOM(4, "%i=audio_isoc_framesperdesc\n",
4521 peasycap->audio_isoc_framesperdesc);
4522 if (0 >= peasycap->audio_isoc_framesperdesc) {
4523 SAM("ERROR: bad audio_isoc_framesperdesc\n");
4524 return -ENOENT;
4527 peasycap->audio_isoc_buffer_size =
4528 peasycap->audio_isoc_maxframesize *
4529 peasycap->audio_isoc_framesperdesc;
4530 JOM(4, "%i=audio_isoc_buffer_size\n",
4531 peasycap->audio_isoc_buffer_size);
4532 if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
4533 SAM("MISTAKE: audio_isoc_buffer_size bigger "
4534 "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
4535 AUDIO_ISOC_BUFFER_SIZE);
4536 return -EFAULT;
4538 if (-1 == peasycap->audio_interface) {
4539 SAM("MISTAKE: audio_interface is unset\n");
4540 return -EFAULT;
4542 if (-1 == peasycap->audio_altsetting_on) {
4543 SAM("MISTAKE: audio_altsetting_on is unset\n");
4544 return -EFAULT;
4546 if (-1 == peasycap->audio_altsetting_off) {
4547 SAM("MISTAKE: audio_interface_off is unset\n");
4548 return -EFAULT;
4550 if (-1 == peasycap->audio_endpointnumber) {
4551 SAM("MISTAKE: audio_endpointnumber is unset\n");
4552 return -EFAULT;
4554 if (-1 == peasycap->audio_isoc_maxframesize) {
4555 SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
4556 return -EFAULT;
4558 if (-1 == peasycap->audio_isoc_buffer_size) {
4559 SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
4560 return -EFAULT;
4562 /*---------------------------------------------------------------------------*/
4564 * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
4566 /*---------------------------------------------------------------------------*/
4567 INIT_LIST_HEAD(&(peasycap->urb_audio_head));
4568 peasycap->purb_audio_head = &(peasycap->urb_audio_head);
4570 #if !defined(EASYCAP_NEEDS_ALSA)
4571 JOM(4, "allocating an audio buffer\n");
4572 JOM(4, ".... scattered over %i pages\n",
4573 peasycap->audio_buffer_page_many);
4575 for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
4576 if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
4577 SAM("ERROR: attempting to reallocate audio buffers\n");
4578 } else {
4579 pbuf = (void *) __get_free_page(GFP_KERNEL);
4580 if ((void *)NULL == pbuf) {
4581 SAM("ERROR: Could not allocate audio "
4582 "buffer page %i\n", k);
4583 return -ENOMEM;
4584 } else
4585 peasycap->allocation_audio_page += 1;
4587 peasycap->audio_buffer[k].pgo = pbuf;
4589 peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
4592 peasycap->audio_fill = 0;
4593 peasycap->audio_read = 0;
4594 JOM(4, "allocation of audio buffer done: %i pages\n", k);
4595 #endif /*!EASYCAP_NEEDS_ALSA*/
4596 /*---------------------------------------------------------------------------*/
4597 JOM(4, "allocating %i isoc audio buffers of size %i\n",
4598 AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
4599 JOM(4, ".... each occupying contiguous memory pages\n");
4601 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4602 pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER);
4603 if (NULL == pbuf) {
4604 SAM("ERROR: Could not allocate isoc audio buffer "
4605 "%i\n", k);
4606 return -ENOMEM;
4607 } else
4608 peasycap->allocation_audio_page +=
4609 ((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
4611 peasycap->audio_isoc_buffer[k].pgo = pbuf;
4612 peasycap->audio_isoc_buffer[k].pto = pbuf +
4613 peasycap->audio_isoc_buffer_size;
4614 peasycap->audio_isoc_buffer[k].kount = k;
4616 JOM(4, "allocation of isoc audio buffers done.\n");
4617 /*---------------------------------------------------------------------------*/
4619 * ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
4621 /*---------------------------------------------------------------------------*/
4622 JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
4623 JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
4624 peasycap->audio_isoc_framesperdesc);
4625 JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
4626 peasycap->audio_isoc_maxframesize);
4627 JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
4628 peasycap->audio_isoc_buffer_size);
4630 for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
4631 purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
4632 GFP_KERNEL);
4633 if (NULL == purb) {
4634 SAM("ERROR: usb_alloc_urb returned NULL for buffer "
4635 "%i\n", k);
4636 return -ENOMEM;
4637 } else
4638 peasycap->allocation_audio_urb += 1 ;
4639 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
4640 pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
4641 if (NULL == pdata_urb) {
4642 SAM("ERROR: Could not allocate struct data_urb.\n");
4643 return -ENOMEM;
4644 } else
4645 peasycap->allocation_audio_struct +=
4646 sizeof(struct data_urb);
4648 pdata_urb->purb = purb;
4649 pdata_urb->isbuf = k;
4650 pdata_urb->length = 0;
4651 list_add_tail(&(pdata_urb->list_head),
4652 peasycap->purb_audio_head);
4653 /*---------------------------------------------------------------------------*/
4655 * ... AND INITIALIZE THEM
4657 /*---------------------------------------------------------------------------*/
4658 if (!k) {
4659 JOM(4, "initializing audio urbs thus:\n");
4660 JOM(4, " purb->interval = 1;\n");
4661 JOM(4, " purb->dev = peasycap->pusb_device;\n");
4662 JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->"
4663 "pusb_device,%i);\n",
4664 peasycap->audio_endpointnumber);
4665 JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
4666 JOM(4, " purb->transfer_buffer = "
4667 "peasycap->audio_isoc_buffer[.].pgo;\n");
4668 JOM(4, " purb->transfer_buffer_length = %i;\n",
4669 peasycap->audio_isoc_buffer_size);
4670 #if defined(EASYCAP_NEEDS_ALSA)
4671 JOM(4, " purb->complete = easycap_alsa_complete;\n");
4672 #else
4673 JOM(4, " purb->complete = easyoss_complete;\n");
4674 #endif /*EASYCAP_NEEDS_ALSA*/
4675 JOM(4, " purb->context = peasycap;\n");
4676 JOM(4, " purb->start_frame = 0;\n");
4677 JOM(4, " purb->number_of_packets = %i;\n",
4678 peasycap->audio_isoc_framesperdesc);
4679 JOM(4, " for (j = 0; j < %i; j++)\n",
4680 peasycap->audio_isoc_framesperdesc);
4681 JOM(4, " {\n");
4682 JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",
4683 peasycap->audio_isoc_maxframesize);
4684 JOM(4, " purb->iso_frame_desc[j].length = %i;\n",
4685 peasycap->audio_isoc_maxframesize);
4686 JOM(4, " }\n");
4689 purb->interval = 1;
4690 purb->dev = peasycap->pusb_device;
4691 purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
4692 peasycap->audio_endpointnumber);
4693 purb->transfer_flags = URB_ISO_ASAP;
4694 purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
4695 purb->transfer_buffer_length =
4696 peasycap->audio_isoc_buffer_size;
4697 #if defined(EASYCAP_NEEDS_ALSA)
4698 purb->complete = easycap_alsa_complete;
4699 #else
4700 purb->complete = easyoss_complete;
4701 #endif /*EASYCAP_NEEDS_ALSA*/
4702 purb->context = peasycap;
4703 purb->start_frame = 0;
4704 purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
4705 for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
4706 purb->iso_frame_desc[j].offset = j *
4707 peasycap->audio_isoc_maxframesize;
4708 purb->iso_frame_desc[j].length =
4709 peasycap->audio_isoc_maxframesize;
4712 JOM(4, "allocation of %i struct urb done.\n", k);
4713 /*---------------------------------------------------------------------------*/
4715 * SAVE POINTER peasycap IN THIS INTERFACE.
4717 /*---------------------------------------------------------------------------*/
4718 usb_set_intfdata(pusb_interface, peasycap);
4719 /*---------------------------------------------------------------------------*/
4721 * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
4723 /*---------------------------------------------------------------------------*/
4724 #if defined(EASYCAP_NEEDS_ALSA)
4725 JOM(4, "initializing ALSA card\n");
4727 rc = easycap_alsa_probe(peasycap);
4728 if (0 != rc) {
4729 err("easycap_alsa_probe() returned %i\n", rc);
4730 return -ENODEV;
4731 } else {
4732 JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",
4733 (int)peasycap->kref.refcount.counter);
4734 kref_get(&peasycap->kref);
4735 (peasycap->registered_audio)++;
4738 #else /*EASYCAP_NEEDS_ALSA*/
4739 rc = usb_register_dev(pusb_interface, &easyoss_class);
4740 if (0 != rc) {
4741 SAY("ERROR: usb_register_dev() failed\n");
4742 usb_set_intfdata(pusb_interface, NULL);
4743 return -ENODEV;
4744 } else {
4745 JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",
4746 (int)peasycap->kref.refcount.counter);
4747 kref_get(&peasycap->kref);
4748 (peasycap->registered_audio)++;
4750 /*---------------------------------------------------------------------------*/
4752 * LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
4754 /*---------------------------------------------------------------------------*/
4755 SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
4756 #endif /*EASYCAP_NEEDS_ALSA*/
4758 break;
4760 /*---------------------------------------------------------------------------*/
4762 * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
4764 /*---------------------------------------------------------------------------*/
4765 default: {
4766 JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
4767 return -EINVAL;
4770 SAM("ends successfully for interface %i\n",
4771 pusb_interface_descriptor->bInterfaceNumber);
4772 return 0;
4774 /*****************************************************************************/
4775 /*---------------------------------------------------------------------------*/
4777 * WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
4778 * UNPLUGGED. HENCE peasycap->pusb_device IS NO LONGER VALID.
4780 * THIS FUNCTION AFFECTS BOTH OSS AND ALSA. BEWARE.
4782 /*---------------------------------------------------------------------------*/
4783 void
4784 easycap_usb_disconnect(struct usb_interface *pusb_interface)
4786 struct usb_host_interface *pusb_host_interface;
4787 struct usb_interface_descriptor *pusb_interface_descriptor;
4788 __u8 bInterfaceNumber;
4789 struct easycap *peasycap;
4791 struct list_head *plist_head;
4792 struct data_urb *pdata_urb;
4793 int minor, m, kd;
4794 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4795 #if defined(EASYCAP_IS_VIDEODEV_CLIENT)
4796 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4797 struct v4l2_device *pv4l2_device;
4798 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4799 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4800 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4802 JOT(4, "\n");
4804 if ((struct usb_interface *)NULL == pusb_interface) {
4805 JOT(4, "ERROR: pusb_interface is NULL\n");
4806 return;
4808 pusb_host_interface = pusb_interface->cur_altsetting;
4809 if ((struct usb_host_interface *)NULL == pusb_host_interface) {
4810 JOT(4, "ERROR: pusb_host_interface is NULL\n");
4811 return;
4813 pusb_interface_descriptor = &(pusb_host_interface->desc);
4814 if ((struct usb_interface_descriptor *)NULL == pusb_interface_descriptor) {
4815 JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
4816 return;
4818 bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
4819 minor = pusb_interface->minor;
4820 JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
4822 if (1 == bInterfaceNumber)
4823 return;
4825 peasycap = usb_get_intfdata(pusb_interface);
4826 if (NULL == peasycap) {
4827 SAY("ERROR: peasycap is NULL\n");
4828 return;
4830 /*---------------------------------------------------------------------------*/
4831 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
4833 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4834 #else
4835 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4836 /*---------------------------------------------------------------------------*/
4838 * SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
4839 * BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
4840 * REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
4841 * TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
4843 /*---------------------------------------------------------------------------*/
4844 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4845 pv4l2_device = usb_get_intfdata(pusb_interface);
4846 if ((struct v4l2_device *)NULL == pv4l2_device) {
4847 SAY("ERROR: pv4l2_device is NULL\n");
4848 return;
4850 peasycap = (struct easycap *)
4851 container_of(pv4l2_device, struct easycap, v4l2_device);
4853 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4855 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4856 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4857 /*---------------------------------------------------------------------------*/
4858 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
4859 SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
4860 return;
4862 /*---------------------------------------------------------------------------*/
4864 * IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE. BEWARE.
4866 /*---------------------------------------------------------------------------*/
4867 peasycap->video_eof = 1;
4868 peasycap->audio_eof = 1;
4869 wake_up_interruptible(&(peasycap->wq_video));
4870 wake_up_interruptible(&(peasycap->wq_audio));
4871 /*---------------------------------------------------------------------------*/
4872 switch (bInterfaceNumber) {
4873 case 0: {
4874 if ((struct list_head *)NULL != peasycap->purb_video_head) {
4875 JOM(4, "killing video urbs\n");
4876 m = 0;
4877 list_for_each(plist_head, (peasycap->purb_video_head))
4879 pdata_urb = list_entry(plist_head,
4880 struct data_urb, list_head);
4881 if ((struct data_urb *)NULL != pdata_urb) {
4882 if ((struct urb *)NULL !=
4883 pdata_urb->purb) {
4884 usb_kill_urb(pdata_urb->purb);
4885 m++;
4889 JOM(4, "%i video urbs killed\n", m);
4891 break;
4893 /*---------------------------------------------------------------------------*/
4894 case 2: {
4895 if ((struct list_head *)NULL != peasycap->purb_audio_head) {
4896 JOM(4, "killing audio urbs\n");
4897 m = 0;
4898 list_for_each(plist_head,
4899 (peasycap->purb_audio_head)) {
4900 pdata_urb = list_entry(plist_head,
4901 struct data_urb, list_head);
4902 if ((struct data_urb *)NULL != pdata_urb) {
4903 if ((struct urb *)NULL !=
4904 pdata_urb->purb) {
4905 usb_kill_urb(pdata_urb->purb);
4906 m++;
4910 JOM(4, "%i audio urbs killed\n", m);
4912 break;
4914 /*---------------------------------------------------------------------------*/
4915 default:
4916 break;
4918 /*--------------------------------------------------------------------------*/
4920 * DEREGISTER
4922 * THIS PROCEDURE WILL BLOCK UNTIL easycap_poll(), VIDEO IOCTL AND AUDIO
4923 * IOCTL ARE ALL UNLOCKED. IF THIS IS NOT DONE AN Oops CAN OCCUR WHEN
4924 * AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING. BEWARE.
4926 /*--------------------------------------------------------------------------*/
4927 kd = isdongle(peasycap);
4928 switch (bInterfaceNumber) {
4929 case 0: {
4930 if (0 <= kd && DONGLE_MANY > kd) {
4931 wake_up_interruptible(&peasycap->wq_video);
4932 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n",
4933 kd);
4934 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4935 mutex_video)) {
4936 SAY("ERROR: cannot lock easycapdc60_dongle[%i]."
4937 "mutex_video\n", kd);
4938 return;
4940 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
4941 } else
4942 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4943 /*---------------------------------------------------------------------------*/
4944 #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
4945 if ((struct easycap *)NULL == peasycap) {
4946 SAM("ERROR: peasycap has become NULL\n");
4947 } else {
4948 usb_deregister_dev(pusb_interface, &easycap_class);
4949 (peasycap->registered_video)--;
4950 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
4951 SAM("easycap detached from minor #%d\n", minor);
4953 /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
4954 #else
4955 #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
4956 if (!peasycap->v4l2_device.name[0]) {
4957 SAM("ERROR: peasycap->v4l2_device.name is empty\n");
4958 if (0 <= kd && DONGLE_MANY > kd)
4959 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4960 return;
4962 v4l2_device_disconnect(&peasycap->v4l2_device);
4963 JOM(4, "v4l2_device_disconnect() OK\n");
4964 v4l2_device_unregister(&peasycap->v4l2_device);
4965 JOM(4, "v4l2_device_unregister() OK\n");
4966 #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
4968 video_unregister_device(&peasycap->video_device);
4969 JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber);
4970 (peasycap->registered_video)--;
4971 JOM(4, "unregistered with videodev: %i=minor\n", minor);
4972 #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
4973 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
4975 if (0 <= kd && DONGLE_MANY > kd) {
4976 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
4977 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
4979 break;
4981 case 2: {
4982 if (0 <= kd && DONGLE_MANY > kd) {
4983 wake_up_interruptible(&peasycap->wq_audio);
4984 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n",
4985 kd);
4986 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
4987 mutex_audio)) {
4988 SAY("ERROR: cannot lock easycapdc60_dongle[%i]."
4989 "mutex_audio\n", kd);
4990 return;
4992 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
4993 } else
4994 SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
4995 #if defined(EASYCAP_NEEDS_ALSA)
4999 if (0 != snd_card_free(peasycap->psnd_card)) {
5000 SAY("ERROR: snd_card_free() failed\n");
5001 } else {
5002 peasycap->psnd_card = (struct snd_card *)NULL;
5003 (peasycap->registered_audio)--;
5007 #else /*EASYCAP_NEEDS_ALSA*/
5008 usb_deregister_dev(pusb_interface, &easyoss_class);
5009 (peasycap->registered_audio)--;
5010 JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
5011 SAM("easyoss detached from minor #%d\n", minor);
5012 #endif /*EASYCAP_NEEDS_ALSA*/
5014 if (0 <= kd && DONGLE_MANY > kd) {
5015 mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
5016 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
5018 break;
5020 default:
5021 break;
5023 /*---------------------------------------------------------------------------*/
5025 * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
5026 * (ALSO WHEN ALSA HAS BEEN IN USE)
5028 /*---------------------------------------------------------------------------*/
5029 if (!peasycap->kref.refcount.counter) {
5030 SAM("ERROR: peasycap->kref.refcount.counter is zero "
5031 "so cannot call kref_put()\n");
5032 SAM("ending unsuccessfully: may cause memory leak\n");
5033 return;
5035 if (0 <= kd && DONGLE_MANY > kd) {
5036 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_video\n", kd);
5037 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
5038 SAY("ERROR: cannot down "
5039 "easycapdc60_dongle[%i].mutex_video\n", kd);
5040 SAM("ending unsuccessfully: may cause memory leak\n");
5041 return;
5043 JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
5044 JOM(4, "about to lock easycapdc60_dongle[%i].mutex_audio\n", kd);
5045 if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
5046 SAY("ERROR: cannot down "
5047 "easycapdc60_dongle[%i].mutex_audio\n", kd);
5048 mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
5049 JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
5050 SAM("ending unsuccessfully: may cause memory leak\n");
5051 return;
5053 JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
5055 JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
5056 bInterfaceNumber, (int)peasycap->kref.refcount.counter);
5057 kref_put(&peasycap->kref, easycap_delete);
5058 JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
5059 if (0 <= kd && DONGLE_MANY > kd) {
5060 mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
5061 JOT(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
5062 mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
5063 JOT(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
5065 /*---------------------------------------------------------------------------*/
5066 JOM(4, "ends\n");
5067 return;
5069 /*****************************************************************************/
5070 int __init
5071 easycap_module_init(void)
5073 int k, rc;
5075 SAY("========easycap=======\n");
5076 JOT(4, "begins. %i=debug %i=bars %i=gain\n", easycap_debug, easycap_bars,
5077 easycap_gain);
5078 SAY("version: " EASYCAP_DRIVER_VERSION "\n");
5080 mutex_init(&mutex_dongle);
5081 for (k = 0; k < DONGLE_MANY; k++) {
5082 easycapdc60_dongle[k].peasycap = (struct easycap *)NULL;
5083 mutex_init(&easycapdc60_dongle[k].mutex_video);
5084 mutex_init(&easycapdc60_dongle[k].mutex_audio);
5086 /*---------------------------------------------------------------------------*/
5088 * REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
5090 /*---------------------------------------------------------------------------*/
5091 JOT(4, "registering driver easycap\n");
5092 rc = usb_register(&easycap_usb_driver);
5093 if (0 != rc)
5094 SAY("ERROR: usb_register returned %i\n", rc);
5096 JOT(4, "ends\n");
5097 return rc;
5099 /*****************************************************************************/
5100 void __exit
5101 easycap_module_exit(void)
5103 JOT(4, "begins\n");
5105 /*---------------------------------------------------------------------------*/
5107 * DEREGISTER THIS DRIVER WITH THE USB SUBSYTEM.
5109 /*---------------------------------------------------------------------------*/
5110 usb_deregister(&easycap_usb_driver);
5112 JOT(4, "ends\n");
5114 /*****************************************************************************/
5116 module_init(easycap_module_init);
5117 module_exit(easycap_module_exit);
5119 MODULE_LICENSE("GPL");
5120 MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
5121 MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
5122 MODULE_VERSION(EASYCAP_DRIVER_VERSION);
5123 #if defined(EASYCAP_DEBUG)
5124 MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
5125 #endif /*EASYCAP_DEBUG*/
5126 MODULE_PARM_DESC(bars,
5127 "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
5128 MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
5129 /*****************************************************************************/