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