linux/drivers/staging/easycap/easycap_ioctl.c
<<
>>
Prefs
   1/******************************************************************************
   2*                                                                             *
   3*  easycap_ioctl.c                                                            *
   4*                                                                             *
   5******************************************************************************/
   6/*
   7 *
   8 *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
   9 *
  10 *
  11 *  This is free software; you can redistribute it and/or modify
  12 *  it under the terms of the GNU General Public License as published by
  13 *  the Free Software Foundation; either version 2 of the License, or
  14 *  (at your option) any later version.
  15 *
  16 *  The software is distributed in the hope that it will be useful,
  17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 *  GNU General Public License for more details.
  20 *
  21 *  You should have received a copy of the GNU General Public License
  22 *  along with this software; if not, write to the Free Software
  23 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  24 *
  25*/
  26/*****************************************************************************/
  27
  28#include <linux/smp_lock.h>
  29#include "easycap.h"
  30#include "easycap_debug.h"
  31#include "easycap_standard.h"
  32#include "easycap_ioctl.h"
  33
  34/*--------------------------------------------------------------------------*/
  35/*
  36 *  UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
  37 *  FOLLOWING:
  38 *          peasycap->standard_offset
  39 *          peasycap->inputset[peasycap->input].standard_offset
  40 *          peasycap->fps
  41 *          peasycap->usec
  42 *          peasycap->tolerate
  43 *          peasycap->skip
  44 */
  45/*---------------------------------------------------------------------------*/
  46int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
  47{
  48struct easycap_standard const *peasycap_standard;
  49__u16 reg, set;
  50int ir, rc, need, k;
  51unsigned int itwas, isnow;
  52bool resubmit;
  53
  54if (NULL == peasycap) {
  55        SAY("ERROR: peasycap is NULL\n");
  56        return -EFAULT;
  57}
  58if ((struct usb_device *)NULL == peasycap->pusb_device) {
  59        SAM("ERROR: peasycap->pusb_device is NULL\n");
  60        return -EFAULT;
  61}
  62peasycap_standard = &easycap_standard[0];
  63while (0xFFFF != peasycap_standard->mask) {
  64        if (std_id == peasycap_standard->v4l2_standard.id)
  65                break;
  66        peasycap_standard++;
  67}
  68if (0xFFFF == peasycap_standard->mask) {
  69        peasycap_standard = &easycap_standard[0];
  70        while (0xFFFF != peasycap_standard->mask) {
  71                if (std_id & peasycap_standard->v4l2_standard.id)
  72                        break;
  73                peasycap_standard++;
  74        }
  75}
  76if (0xFFFF == peasycap_standard->mask) {
  77        SAM("ERROR: 0x%08X=std_id: standard not found\n", \
  78                                                        (unsigned int)std_id);
  79        return -EINVAL;
  80}
  81SAM("selected standard: %s\n", \
  82                        &(peasycap_standard->v4l2_standard.name[0]));
  83if (peasycap->standard_offset == \
  84                        (int)(peasycap_standard - &easycap_standard[0])) {
  85        SAM("requested standard already in effect\n");
  86        return 0;
  87}
  88peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]);
  89for (k = 0; k < INPUT_MANY;  k++) {
  90        if (!peasycap->inputset[k].standard_offset_ok) {
  91                        peasycap->inputset[k].standard_offset = \
  92                                                peasycap->standard_offset;
  93        }
  94}
  95if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
  96        peasycap->inputset[peasycap->input].standard_offset = \
  97                                                peasycap->standard_offset;
  98        peasycap->inputset[peasycap->input].standard_offset_ok = 1;
  99} else
 100        JOM(8, "%i=peasycap->input\n", peasycap->input);
 101peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
 102                peasycap_standard->v4l2_standard.frameperiod.numerator;
 103switch (peasycap->fps) {
 104case 6:
 105case 30: {
 106        peasycap->ntsc = true;
 107        break;
 108}
 109case 5:
 110case 25: {
 111        peasycap->ntsc = false;
 112        break;
 113}
 114default: {
 115        SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
 116        return -ENOENT;
 117}
 118}
 119JOM(8, "%i frames-per-second\n", peasycap->fps);
 120if (0x8000 & peasycap_standard->mask) {
 121        peasycap->skip = 5;
 122        peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
 123        peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
 124} else {
 125        peasycap->skip = 0;
 126        peasycap->usec = 1000000 / (2 * peasycap->fps);
 127        peasycap->tolerate = 1000 * (25 / peasycap->fps);
 128}
 129if (peasycap->video_isoc_streaming) {
 130        resubmit = true;
 131        kill_video_urbs(peasycap);
 132} else
 133        resubmit = false;
 134/*--------------------------------------------------------------------------*/
 135/*
 136 *  SAA7113H DATASHEET PAGE 44, TABLE 42
 137 */
 138/*--------------------------------------------------------------------------*/
 139need = 0;  itwas = 0;  reg = 0x00;  set = 0x00;
 140switch (peasycap_standard->mask & 0x000F) {
 141case NTSC_M_JP: {
 142        reg = 0x0A;  set = 0x95;
 143        ir = read_saa(peasycap->pusb_device, reg);
 144        if (0 > ir)
 145                SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 146        else
 147                itwas = (unsigned int)ir;
 148        rc = write_saa(peasycap->pusb_device, reg, set);
 149        if (0 != rc)
 150                SAM("ERROR: failed to set SAA register " \
 151                        "0x%02X to 0x%02X for JP standard\n", reg, set);
 152        else {
 153                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 154                if (0 > ir)
 155                        JOM(8, "SAA register 0x%02X changed " \
 156                                "to 0x%02X\n", reg, isnow);
 157                else
 158                        JOM(8, "SAA register 0x%02X changed " \
 159                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 160        }
 161
 162        reg = 0x0B;  set = 0x48;
 163        ir = read_saa(peasycap->pusb_device, reg);
 164        if (0 > ir)
 165                SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 166        else
 167                itwas = (unsigned int)ir;
 168        rc = write_saa(peasycap->pusb_device, reg, set);
 169        if (0 != rc)
 170                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
 171                                                "for JP standard\n", reg, set);
 172        else {
 173                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 174                if (0 > ir)
 175                        JOM(8, "SAA register 0x%02X changed " \
 176                                "to 0x%02X\n", reg, isnow);
 177                else
 178                        JOM(8, "SAA register 0x%02X changed " \
 179                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 180        }
 181/*--------------------------------------------------------------------------*/
 182/*
 183 *  NOTE:  NO break HERE:  RUN ON TO NEXT CASE
 184 */
 185/*--------------------------------------------------------------------------*/
 186}
 187case NTSC_M:
 188case PAL_BGHIN: {
 189        reg = 0x0E;  set = 0x01;  need = 1;  break;
 190}
 191case NTSC_N_443:
 192case PAL_60: {
 193        reg = 0x0E;  set = 0x11;  need = 1;  break;
 194}
 195case NTSC_443:
 196case PAL_Nc: {
 197        reg = 0x0E;  set = 0x21;  need = 1;  break;
 198}
 199case NTSC_N:
 200case PAL_M: {
 201        reg = 0x0E;  set = 0x31;  need = 1;  break;
 202}
 203case SECAM: {
 204        reg = 0x0E;  set = 0x51;  need = 1;  break;
 205}
 206default:
 207        break;
 208}
 209/*--------------------------------------------------------------------------*/
 210if (need) {
 211        ir = read_saa(peasycap->pusb_device, reg);
 212        if (0 > ir)
 213                SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
 214        else
 215                itwas = (unsigned int)ir;
 216        rc = write_saa(peasycap->pusb_device, reg, set);
 217        if (0 != write_saa(peasycap->pusb_device, reg, set)) {
 218                SAM("ERROR: failed to set SAA register " \
 219                        "0x%02X to 0x%02X for table 42\n", reg, set);
 220        } else {
 221                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 222                if (0 > ir)
 223                        JOM(8, "SAA register 0x%02X changed " \
 224                                "to 0x%02X\n", reg, isnow);
 225                else
 226                        JOM(8, "SAA register 0x%02X changed " \
 227                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 228        }
 229}
 230/*--------------------------------------------------------------------------*/
 231/*
 232 *  SAA7113H DATASHEET PAGE 41
 233 */
 234/*--------------------------------------------------------------------------*/
 235reg = 0x08;
 236ir = read_saa(peasycap->pusb_device, reg);
 237if (0 > ir)
 238        SAM("ERROR: failed to read SAA register 0x%02X " \
 239                                                "so cannot reset\n", reg);
 240else {
 241        itwas = (unsigned int)ir;
 242        if (peasycap_standard->mask & 0x0001)
 243                set = itwas | 0x40 ;
 244        else
 245                set = itwas & ~0x40 ;
 246        rc  = write_saa(peasycap->pusb_device, reg, set);
 247        if (0 != rc)
 248                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 249                                                                reg, set);
 250        else {
 251                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 252                if (0 > ir)
 253                        JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
 254                                                                reg, isnow);
 255                else
 256                        JOM(8, "SAA register 0x%02X changed " \
 257                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 258        }
 259}
 260/*--------------------------------------------------------------------------*/
 261/*
 262 *  SAA7113H DATASHEET PAGE 51, TABLE 57
 263 */
 264/*---------------------------------------------------------------------------*/
 265reg = 0x40;
 266ir = read_saa(peasycap->pusb_device, reg);
 267if (0 > ir)
 268        SAM("ERROR: failed to read SAA register 0x%02X " \
 269                                                "so cannot reset\n", reg);
 270else {
 271        itwas = (unsigned int)ir;
 272        if (peasycap_standard->mask & 0x0001)
 273                set = itwas | 0x80 ;
 274        else
 275                set = itwas & ~0x80 ;
 276        rc = write_saa(peasycap->pusb_device, reg, set);
 277        if (0 != rc)
 278                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 279                                                                reg, set);
 280        else {
 281                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 282                if (0 > ir)
 283                        JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
 284                                                                reg, isnow);
 285                else
 286                        JOM(8, "SAA register 0x%02X changed " \
 287                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 288        }
 289}
 290/*--------------------------------------------------------------------------*/
 291/*
 292 *  SAA7113H DATASHEET PAGE 53, TABLE 66
 293 */
 294/*--------------------------------------------------------------------------*/
 295reg = 0x5A;
 296ir = read_saa(peasycap->pusb_device, reg);
 297if (0 > ir)
 298        SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
 299        itwas = (unsigned int)ir;
 300        if (peasycap_standard->mask & 0x0001)
 301                set = 0x0A ;
 302        else
 303                set = 0x07 ;
 304        if (0 != write_saa(peasycap->pusb_device, reg, set))
 305                SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
 306                                                                reg, set);
 307        else {
 308                isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 309                if (0 > ir)
 310                        JOM(8, "SAA register 0x%02X changed "
 311                                "to 0x%02X\n", reg, isnow);
 312                else
 313                        JOM(8, "SAA register 0x%02X changed "
 314                                "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 315        }
 316if (true == resubmit)
 317        submit_video_urbs(peasycap);
 318return 0;
 319}
 320/*****************************************************************************/
 321/*--------------------------------------------------------------------------*/
 322/*
 323 *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
 324 *  A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
 325 *
 326 *  PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
 327 *  THIS ROUTINE UPDATES THE FOLLOWING:
 328 *          peasycap->format_offset
 329 *          peasycap->inputset[peasycap->input].format_offset
 330 *          peasycap->pixelformat
 331 *          peasycap->height
 332 *          peasycap->width
 333 *          peasycap->bytesperpixel
 334 *          peasycap->byteswaporder
 335 *          peasycap->decimatepixel
 336 *          peasycap->frame_buffer_used
 337 *          peasycap->videofieldamount
 338 *          peasycap->offerfields
 339 *
 340 *  IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
 341 *  IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
 342 *  ERRORS RETURN A NEGATIVE NUMBER.
 343 */
 344/*--------------------------------------------------------------------------*/
 345int adjust_format(struct easycap *peasycap, \
 346        __u32 width, __u32 height, __u32 pixelformat, int field, bool try)
 347{
 348struct easycap_format *peasycap_format, *peasycap_best_format;
 349__u16 mask;
 350struct usb_device *p;
 351int miss, multiplier, best, k;
 352char bf[5], fo[32], *pc;
 353__u32 uc;
 354bool resubmit;
 355
 356if (NULL == peasycap) {
 357        SAY("ERROR: peasycap is NULL\n");
 358        return -EFAULT;
 359}
 360if (0 > peasycap->standard_offset) {
 361        JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
 362        return -EBUSY;
 363}
 364p = peasycap->pusb_device;
 365if ((struct usb_device *)NULL == p) {
 366        SAM("ERROR: peaycap->pusb_device is NULL\n");
 367        return -EFAULT;
 368}
 369pc = &bf[0];
 370uc = pixelformat;
 371memcpy((void *)pc, (void *)(&uc), 4);
 372bf[4] = 0;
 373mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
 374SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \
 375                                width, height, pc, pixelformat, field, mask);
 376switch (field) {
 377case V4L2_FIELD_ANY: {
 378        strcpy(&fo[0], "V4L2_FIELD_ANY ");
 379        break;
 380}
 381case V4L2_FIELD_NONE: {
 382        strcpy(&fo[0], "V4L2_FIELD_NONE");
 383        break;
 384}
 385case V4L2_FIELD_TOP: {
 386        strcpy(&fo[0], "V4L2_FIELD_TOP");
 387        break;
 388}
 389case V4L2_FIELD_BOTTOM: {
 390        strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
 391        break;
 392}
 393case V4L2_FIELD_INTERLACED: {
 394        strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
 395        break;
 396}
 397case V4L2_FIELD_SEQ_TB: {
 398        strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
 399        break;
 400}
 401case V4L2_FIELD_SEQ_BT: {
 402        strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
 403        break;
 404}
 405case V4L2_FIELD_ALTERNATE: {
 406        strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
 407        break;
 408}
 409case V4L2_FIELD_INTERLACED_TB: {
 410        strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
 411        break;
 412}
 413case V4L2_FIELD_INTERLACED_BT: {
 414        strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
 415        break;
 416}
 417default: {
 418        strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
 419        break;
 420}
 421}
 422SAM("sought:    %s\n", &fo[0]);
 423if (V4L2_FIELD_ANY == field) {
 424        field = V4L2_FIELD_NONE;
 425        SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
 426}
 427peasycap_best_format = (struct easycap_format *)NULL;
 428peasycap_format = &easycap_format[0];
 429while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
 430        JOM(16, ".> %i %i 0x%08X %ix%i\n", \
 431                peasycap_format->mask & 0x01,
 432                peasycap_format->v4l2_format.fmt.pix.field,
 433                peasycap_format->v4l2_format.fmt.pix.pixelformat,
 434                peasycap_format->v4l2_format.fmt.pix.width,
 435                peasycap_format->v4l2_format.fmt.pix.height);
 436
 437        if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
 438                (peasycap_format->v4l2_format.fmt.pix.field == field) && \
 439                (peasycap_format->v4l2_format.fmt.pix.pixelformat == \
 440                                                        pixelformat) && \
 441                (peasycap_format->v4l2_format.fmt.pix.width  == width) && \
 442                (peasycap_format->v4l2_format.fmt.pix.height == height)) {
 443                        peasycap_best_format = peasycap_format;
 444                        break;
 445                }
 446        peasycap_format++;
 447}
 448if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
 449        SAM("cannot do: %ix%i with standard mask 0x%02X\n", \
 450                                                        width, height, mask);
 451        peasycap_format = &easycap_format[0];  best = -1;
 452        while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
 453                if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
 454                                 (peasycap_format->v4l2_format.fmt.pix\
 455                                                .field == field) && \
 456                                 (peasycap_format->v4l2_format.fmt.pix\
 457                                                .pixelformat == pixelformat)) {
 458                        miss = abs(peasycap_format->\
 459                                        v4l2_format.fmt.pix.width  - width);
 460                        if ((best > miss) || (best < 0)) {
 461                                best = miss;
 462                                peasycap_best_format = peasycap_format;
 463                                if (!miss)
 464                                        break;
 465                        }
 466                }
 467                peasycap_format++;
 468        }
 469        if (-1 == best) {
 470                SAM("cannot do %ix... with standard mask 0x%02X\n", \
 471                                                                width, mask);
 472                SAM("cannot do ...x%i with standard mask 0x%02X\n", \
 473                                                                height, mask);
 474                SAM("           %ix%i unmatched\n", width, height);
 475                return peasycap->format_offset;
 476        }
 477}
 478if ((struct easycap_format *)NULL == peasycap_best_format) {
 479        SAM("MISTAKE: peasycap_best_format is NULL");
 480        return -EINVAL;
 481}
 482peasycap_format = peasycap_best_format;
 483
 484/*...........................................................................*/
 485if (true == try)
 486        return (int)(peasycap_best_format - &easycap_format[0]);
 487/*...........................................................................*/
 488
 489if (false != try) {
 490        SAM("MISTAKE: true==try where is should be false\n");
 491        return -EINVAL;
 492}
 493SAM("actioning: %ix%i %s\n", \
 494                        peasycap_format->v4l2_format.fmt.pix.width, \
 495                        peasycap_format->v4l2_format.fmt.pix.height,
 496                        &peasycap_format->name[0]);
 497peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
 498peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
 499peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
 500peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
 501
 502
 503for (k = 0; k < INPUT_MANY; k++) {
 504        if (!peasycap->inputset[k].format_offset_ok) {
 505                peasycap->inputset[k].format_offset = \
 506                                                peasycap->format_offset;
 507        }
 508}
 509if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 510        peasycap->inputset[peasycap->input].format_offset = \
 511                                                peasycap->format_offset;
 512        peasycap->inputset[peasycap->input].format_offset_ok = 1;
 513} else
 514        JOM(8, "%i=peasycap->input\n", peasycap->input);
 515
 516
 517
 518peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
 519if (0x0100 & peasycap_format->mask)
 520        peasycap->byteswaporder = true;
 521else
 522        peasycap->byteswaporder = false;
 523if (0x0200 & peasycap_format->mask)
 524        peasycap->skip = 5;
 525else
 526        peasycap->skip = 0;
 527if (0x0800 & peasycap_format->mask)
 528        peasycap->decimatepixel = true;
 529else
 530        peasycap->decimatepixel = false;
 531if (0x1000 & peasycap_format->mask)
 532        peasycap->offerfields = true;
 533else
 534        peasycap->offerfields = false;
 535if (true == peasycap->decimatepixel)
 536        multiplier = 2;
 537else
 538        multiplier = 1;
 539peasycap->videofieldamount = multiplier * peasycap->width * \
 540                                        multiplier * peasycap->height;
 541peasycap->frame_buffer_used = peasycap->bytesperpixel * \
 542                                        peasycap->width * peasycap->height;
 543if (peasycap->video_isoc_streaming) {
 544        resubmit = true;
 545        kill_video_urbs(peasycap);
 546} else
 547        resubmit = false;
 548/*---------------------------------------------------------------------------*/
 549/*
 550 *  PAL
 551 */
 552/*---------------------------------------------------------------------------*/
 553if (0 == (0x01 & peasycap_format->mask)) {
 554        if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
 555                        (576 == \
 556                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 557                        ((360 == \
 558                        peasycap_format->v4l2_format.fmt.pix.width) && \
 559                        (288 == \
 560                        peasycap_format->v4l2_format.fmt.pix.height))) {
 561                if (0 != set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
 562                        SAM("ERROR: set_resolution() failed\n");
 563                        return -EINVAL;
 564                }
 565        } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && \
 566                        (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
 567                if (0 != set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
 568                        SAM("ERROR: set_resolution() failed\n");
 569                        return -EINVAL;
 570                }
 571        } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
 572                        (480 == \
 573                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 574                        ((320 == \
 575                        peasycap_format->v4l2_format.fmt.pix.width) && \
 576                        (240 == \
 577                        peasycap_format->v4l2_format.fmt.pix.height))) {
 578                if (0 != set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
 579                        SAM("ERROR: set_resolution() failed\n");
 580                        return -EINVAL;
 581                }
 582        } else {
 583                SAM("MISTAKE: bad format, cannot set resolution\n");
 584                return -EINVAL;
 585        }
 586/*---------------------------------------------------------------------------*/
 587/*
 588 *  NTSC
 589 */
 590/*---------------------------------------------------------------------------*/
 591} else {
 592        if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
 593                        (480 == \
 594                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 595                        ((360 == \
 596                        peasycap_format->v4l2_format.fmt.pix.width) && \
 597                        (240 == \
 598                        peasycap_format->v4l2_format.fmt.pix.height))) {
 599                if (0 != set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
 600                        SAM("ERROR: set_resolution() failed\n");
 601                        return -EINVAL;
 602                }
 603        } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
 604                        (480 == \
 605                        peasycap_format->v4l2_format.fmt.pix.height)) || \
 606                        ((320 == \
 607                        peasycap_format->v4l2_format.fmt.pix.width) && \
 608                        (240 == \
 609                        peasycap_format->v4l2_format.fmt.pix.height))) {
 610                if (0 != set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
 611                        SAM("ERROR: set_resolution() failed\n");
 612                        return -EINVAL;
 613                }
 614        } else {
 615                SAM("MISTAKE: bad format, cannot set resolution\n");
 616                return -EINVAL;
 617        }
 618}
 619/*---------------------------------------------------------------------------*/
 620if (true == resubmit)
 621        submit_video_urbs(peasycap);
 622return (int)(peasycap_best_format - &easycap_format[0]);
 623}
 624/*****************************************************************************/
 625int adjust_brightness(struct easycap *peasycap, int value)
 626{
 627unsigned int mood;
 628int i1, k;
 629
 630if (NULL == peasycap) {
 631        SAY("ERROR: peasycap is NULL\n");
 632        return -EFAULT;
 633}
 634if ((struct usb_device *)NULL == peasycap->pusb_device) {
 635        SAM("ERROR: peasycap->pusb_device is NULL\n");
 636        return -EFAULT;
 637}
 638i1 = 0;
 639while (0xFFFFFFFF != easycap_control[i1].id) {
 640        if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
 641                if ((easycap_control[i1].minimum > value) || \
 642                                        (easycap_control[i1].maximum < value))
 643                        value = easycap_control[i1].default_value;
 644
 645                if ((easycap_control[i1].minimum <= peasycap->brightness) && \
 646                                        (easycap_control[i1].maximum >= \
 647                                                peasycap->brightness)) {
 648                        if (peasycap->brightness == value) {
 649                                SAM("unchanged brightness at  0x%02X\n", \
 650                                                                value);
 651                                return 0;
 652                        }
 653                }
 654                peasycap->brightness = value;
 655                for (k = 0; k < INPUT_MANY; k++) {
 656                        if (!peasycap->inputset[k].brightness_ok)
 657                                peasycap->inputset[k].brightness = \
 658                                                        peasycap->brightness;
 659                }
 660                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 661                        peasycap->inputset[peasycap->input].brightness = \
 662                                                        peasycap->brightness;
 663                        peasycap->inputset[peasycap->input].brightness_ok = 1;
 664                } else
 665                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 666                mood = 0x00FF & (unsigned int)peasycap->brightness;
 667                if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
 668                        SAM("adjusting brightness to  0x%02X\n", mood);
 669                        return 0;
 670                } else {
 671                        SAM("WARNING: failed to adjust brightness " \
 672                                                        "to 0x%02X\n", mood);
 673                        return -ENOENT;
 674                }
 675                break;
 676        }
 677        i1++;
 678}
 679SAM("WARNING: failed to adjust brightness: control not found\n");
 680return -ENOENT;
 681}
 682/*****************************************************************************/
 683int adjust_contrast(struct easycap *peasycap, int value)
 684{
 685unsigned int mood;
 686int i1, k;
 687
 688if (NULL == peasycap) {
 689        SAY("ERROR: peasycap is NULL\n");
 690        return -EFAULT;
 691}
 692if ((struct usb_device *)NULL == peasycap->pusb_device) {
 693        SAM("ERROR: peasycap->pusb_device is NULL\n");
 694        return -EFAULT;
 695}
 696i1 = 0;
 697while (0xFFFFFFFF != easycap_control[i1].id) {
 698        if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
 699                if ((easycap_control[i1].minimum > value) || \
 700                                        (easycap_control[i1].maximum < value))
 701                        value = easycap_control[i1].default_value;
 702
 703
 704
 705                if ((easycap_control[i1].minimum <= peasycap->contrast) && \
 706                                (easycap_control[i1].maximum >= \
 707                                                        peasycap->contrast)) {
 708                        if (peasycap->contrast == value) {
 709                                SAM("unchanged contrast at  0x%02X\n", value);
 710                                return 0;
 711                        }
 712                }
 713                peasycap->contrast = value;
 714                for (k = 0; k < INPUT_MANY; k++) {
 715                        if (!peasycap->inputset[k].contrast_ok) {
 716                                peasycap->inputset[k].contrast = \
 717                                                        peasycap->contrast;
 718                        }
 719                }
 720                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 721                        peasycap->inputset[peasycap->input].contrast = \
 722                                                        peasycap->contrast;
 723                        peasycap->inputset[peasycap->input].contrast_ok = 1;
 724                } else
 725                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 726                mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
 727                if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
 728                        SAM("adjusting contrast to  0x%02X\n", mood);
 729                        return 0;
 730                } else {
 731                        SAM("WARNING: failed to adjust contrast to " \
 732                                                        "0x%02X\n", mood);
 733                        return -ENOENT;
 734                }
 735                break;
 736        }
 737        i1++;
 738}
 739SAM("WARNING: failed to adjust contrast: control not found\n");
 740return -ENOENT;
 741}
 742/*****************************************************************************/
 743int adjust_saturation(struct easycap *peasycap, int value)
 744{
 745unsigned int mood;
 746int i1, k;
 747
 748if (NULL == peasycap) {
 749        SAY("ERROR: peasycap is NULL\n");
 750        return -EFAULT;
 751}
 752if ((struct usb_device *)NULL == peasycap->pusb_device) {
 753        SAM("ERROR: peasycap->pusb_device is NULL\n");
 754        return -EFAULT;
 755}
 756i1 = 0;
 757while (0xFFFFFFFF != easycap_control[i1].id) {
 758        if (V4L2_CID_SATURATION == easycap_control[i1].id) {
 759                if ((easycap_control[i1].minimum > value) || \
 760                                        (easycap_control[i1].maximum < value))
 761                        value = easycap_control[i1].default_value;
 762
 763
 764                if ((easycap_control[i1].minimum <= peasycap->saturation) && \
 765                                        (easycap_control[i1].maximum >= \
 766                                                peasycap->saturation)) {
 767                        if (peasycap->saturation == value) {
 768                                SAM("unchanged saturation at  0x%02X\n", \
 769                                                                value);
 770                                return 0;
 771                        }
 772                }
 773                peasycap->saturation = value;
 774                for (k = 0; k < INPUT_MANY; k++) {
 775                        if (!peasycap->inputset[k].saturation_ok) {
 776                                peasycap->inputset[k].saturation = \
 777                                                        peasycap->saturation;
 778                        }
 779                }
 780                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 781                        peasycap->inputset[peasycap->input].saturation = \
 782                                                        peasycap->saturation;
 783                        peasycap->inputset[peasycap->input].saturation_ok = 1;
 784                } else
 785                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 786                mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
 787                if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
 788                        SAM("adjusting saturation to  0x%02X\n", mood);
 789                        return 0;
 790                } else {
 791                        SAM("WARNING: failed to adjust saturation to " \
 792                                                        "0x%02X\n", mood);
 793                        return -ENOENT;
 794                }
 795                break;
 796        }
 797        i1++;
 798}
 799SAM("WARNING: failed to adjust saturation: control not found\n");
 800return -ENOENT;
 801}
 802/*****************************************************************************/
 803int adjust_hue(struct easycap *peasycap, int value)
 804{
 805unsigned int mood;
 806int i1, i2, k;
 807
 808if (NULL == peasycap) {
 809        SAY("ERROR: peasycap is NULL\n");
 810        return -EFAULT;
 811}
 812if ((struct usb_device *)NULL == peasycap->pusb_device) {
 813        SAM("ERROR: peasycap->pusb_device is NULL\n");
 814        return -EFAULT;
 815}
 816i1 = 0;
 817while (0xFFFFFFFF != easycap_control[i1].id) {
 818        if (V4L2_CID_HUE == easycap_control[i1].id) {
 819                if ((easycap_control[i1].minimum > value) || \
 820                                        (easycap_control[i1].maximum < value))
 821                        value = easycap_control[i1].default_value;
 822
 823                if ((easycap_control[i1].minimum <= peasycap->hue) && \
 824                                        (easycap_control[i1].maximum >= \
 825                                                        peasycap->hue)) {
 826                        if (peasycap->hue == value) {
 827                                SAM("unchanged hue at  0x%02X\n", value);
 828                                return 0;
 829                        }
 830                }
 831                peasycap->hue = value;
 832                for (k = 0; k < INPUT_MANY; k++) {
 833                        if (!peasycap->inputset[k].hue_ok)
 834                                peasycap->inputset[k].hue = peasycap->hue;
 835                }
 836                if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
 837                        peasycap->inputset[peasycap->input].hue = \
 838                                                        peasycap->hue;
 839                        peasycap->inputset[peasycap->input].hue_ok = 1;
 840                } else
 841                        JOM(8, "%i=peasycap->input\n", peasycap->input);
 842                i2 = peasycap->hue - 128;
 843                mood = 0x00FF & ((int) i2);
 844                if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
 845                        SAM("adjusting hue to  0x%02X\n", mood);
 846                        return 0;
 847                } else {
 848                        SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
 849                        return -ENOENT;
 850                }
 851                break;
 852        }
 853        i1++;
 854}
 855SAM("WARNING: failed to adjust hue: control not found\n");
 856return -ENOENT;
 857}
 858/*****************************************************************************/
 859int adjust_volume(struct easycap *peasycap, int value)
 860{
 861__s8 mood;
 862int i1;
 863
 864if (NULL == peasycap) {
 865        SAY("ERROR: peasycap is NULL\n");
 866        return -EFAULT;
 867}
 868if ((struct usb_device *)NULL == peasycap->pusb_device) {
 869        SAM("ERROR: peasycap->pusb_device is NULL\n");
 870        return -EFAULT;
 871}
 872i1 = 0;
 873while (0xFFFFFFFF != easycap_control[i1].id) {
 874        if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
 875                if ((easycap_control[i1].minimum > value) || \
 876                                (easycap_control[i1].maximum < value))
 877                        value = easycap_control[i1].default_value;
 878                if ((easycap_control[i1].minimum <= peasycap->volume) && \
 879                                        (easycap_control[i1].maximum >= \
 880                                                        peasycap->volume)) {
 881                        if (peasycap->volume == value) {
 882                                SAM("unchanged volume at  0x%02X\n", value);
 883                                return 0;
 884                        }
 885                }
 886                peasycap->volume = value;
 887                mood = (16 > peasycap->volume) ? 16 : \
 888                        ((31 < peasycap->volume) ? 31 : \
 889                        (__s8) peasycap->volume);
 890                if (!audio_gainset(peasycap->pusb_device, mood)) {
 891                        SAM("adjusting volume to 0x%02X\n", mood);
 892                        return 0;
 893                } else {
 894                        SAM("WARNING: failed to adjust volume to " \
 895                                                        "0x%2X\n", mood);
 896                        return -ENOENT;
 897                }
 898                break;
 899        }
 900i1++;
 901}
 902SAM("WARNING: failed to adjust volume: control not found\n");
 903return -ENOENT;
 904}
 905/*****************************************************************************/
 906/*---------------------------------------------------------------------------*/
 907/*
 908 *  AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
 909 *            usb_set_interface(peasycap->pusb_device, \
 910 *                              peasycap->audio_interface, \
 911 *                              peasycap->audio_altsetting_off);
 912 *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
 913 *  -ESHUTDOWN.  THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT
 914 *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
 915 */
 916/*---------------------------------------------------------------------------*/
 917int adjust_mute(struct easycap *peasycap, int value)
 918{
 919int i1;
 920
 921if (NULL == peasycap) {
 922        SAY("ERROR: peasycap is NULL\n");
 923        return -EFAULT;
 924}
 925if ((struct usb_device *)NULL == peasycap->pusb_device) {
 926        SAM("ERROR: peasycap->pusb_device is NULL\n");
 927        return -EFAULT;
 928}
 929i1 = 0;
 930while (0xFFFFFFFF != easycap_control[i1].id) {
 931        if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
 932                peasycap->mute = value;
 933                switch (peasycap->mute) {
 934                case 1: {
 935                        peasycap->audio_idle = 1;
 936                        peasycap->timeval0.tv_sec = 0;
 937                        SAM("adjusting mute: %i=peasycap->audio_idle\n", \
 938                                                        peasycap->audio_idle);
 939                        return 0;
 940                }
 941                default: {
 942                        peasycap->audio_idle = 0;
 943                        SAM("adjusting mute: %i=peasycap->audio_idle\n", \
 944                                                        peasycap->audio_idle);
 945                        return 0;
 946                }
 947                }
 948                break;
 949        }
 950        i1++;
 951}
 952SAM("WARNING: failed to adjust mute: control not found\n");
 953return -ENOENT;
 954}
 955/*****************************************************************************/
 956/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
 957#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
 958        (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
 959long
 960easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
 961        return (long)easycap_ioctl((struct inode *)NULL, file, cmd, arg);
 962}
 963#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
 964/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 965/*---------------------------------------------------------------------------*/
 966int
 967easycap_ioctl(struct inode *inode, struct file *file,
 968                                        unsigned int cmd, unsigned long arg)
 969{
 970struct easycap *peasycap;
 971struct usb_device *p;
 972int kd;
 973
 974if (NULL == file) {
 975        SAY("ERROR:  file is NULL\n");
 976        return -ERESTARTSYS;
 977}
 978peasycap = file->private_data;
 979if (NULL == peasycap) {
 980        SAY("ERROR:  peasycap is NULL\n");
 981        return -1;
 982}
 983if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 984        SAY("ERROR: bad peasycap\n");
 985        return -EFAULT;
 986}
 987p = peasycap->pusb_device;
 988if (NULL == p) {
 989        SAM("ERROR: peasycap->pusb_device is NULL\n");
 990        return -EFAULT;
 991}
 992kd = isdongle(peasycap);
 993if (0 <= kd && DONGLE_MANY > kd) {
 994        if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
 995                SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
 996                return -ERESTARTSYS;
 997        }
 998        JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
 999/*---------------------------------------------------------------------------*/
1000/*
1001 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
1002 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1003 *  IF NECESSARY, BAIL OUT.
1004*/
1005/*---------------------------------------------------------------------------*/
1006        if (kd != isdongle(peasycap))
1007                return -ERESTARTSYS;
1008        if (NULL == file) {
1009                SAY("ERROR:  file is NULL\n");
1010                mutex_unlock(&easycap_dongle[kd].mutex_video);
1011                return -ERESTARTSYS;
1012        }
1013        peasycap = file->private_data;
1014        if (NULL == peasycap) {
1015                SAY("ERROR:  peasycap is NULL\n");
1016                mutex_unlock(&easycap_dongle[kd].mutex_video);
1017                return -ERESTARTSYS;
1018        }
1019        if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1020                SAY("ERROR: bad peasycap\n");
1021                mutex_unlock(&easycap_dongle[kd].mutex_video);
1022                return -EFAULT;
1023        }
1024        p = peasycap->pusb_device;
1025        if (NULL == peasycap->pusb_device) {
1026                SAM("ERROR: peasycap->pusb_device is NULL\n");
1027                mutex_unlock(&easycap_dongle[kd].mutex_video);
1028                return -ERESTARTSYS;
1029        }
1030} else {
1031/*---------------------------------------------------------------------------*/
1032/*
1033 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1034 *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
1035*/
1036/*---------------------------------------------------------------------------*/
1037        return -ERESTARTSYS;
1038}
1039/*---------------------------------------------------------------------------*/
1040switch (cmd) {
1041case VIDIOC_QUERYCAP: {
1042        struct v4l2_capability v4l2_capability;
1043        char version[16], *p1, *p2;
1044        int i, rc, k[3];
1045        long lng;
1046
1047        JOM(8, "VIDIOC_QUERYCAP\n");
1048
1049        if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
1050                SAM("ERROR: bad driver version string\n");
1051                mutex_unlock(&easycap_dongle[kd].mutex_video);
1052                return -EINVAL;
1053        }
1054        strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1055        for (i = 0; i < 3; i++)
1056                k[i] = 0;
1057        p2 = &version[0];  i = 0;
1058        while (*p2) {
1059                p1 = p2;
1060                while (*p2 && ('.' != *p2))
1061                        p2++;
1062                if (*p2)
1063                        *p2++ = 0;
1064                if (3 > i) {
1065                        rc = (int) strict_strtol(p1, 10, &lng);
1066                        if (0 != rc) {
1067                                SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
1068                                                                rc, p1);
1069                                mutex_unlock(&easycap_dongle[kd].mutex_video);
1070                                return -EINVAL;
1071                        }
1072                        k[i] = (int)lng;
1073                }
1074                i++;
1075        }
1076
1077        memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1078        strlcpy(&v4l2_capability.driver[0], "easycap", \
1079                                        sizeof(v4l2_capability.driver));
1080
1081        v4l2_capability.capabilities = \
1082                                V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
1083                                V4L2_CAP_AUDIO         | V4L2_CAP_READWRITE;
1084
1085        v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
1086        JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
1087
1088        strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \
1089                sizeof(v4l2_capability.card));
1090
1091        if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\
1092                                sizeof(v4l2_capability.bus_info)) < 0) {
1093                strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \
1094                                        sizeof(v4l2_capability.bus_info));
1095                JOM(8, "%s=v4l2_capability.bus_info\n", \
1096                                        &v4l2_capability.bus_info[0]);
1097        }
1098        if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
1099                                        sizeof(struct v4l2_capability))) {
1100                mutex_unlock(&easycap_dongle[kd].mutex_video);
1101                return -EFAULT;
1102        }
1103        break;
1104}
1105/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1106case VIDIOC_ENUMINPUT: {
1107        struct v4l2_input v4l2_input;
1108        __u32 index;
1109
1110        JOM(8, "VIDIOC_ENUMINPUT\n");
1111
1112        if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
1113                                        sizeof(struct v4l2_input))) {
1114                mutex_unlock(&easycap_dongle[kd].mutex_video);
1115                return -EFAULT;
1116        }
1117
1118        index = v4l2_input.index;
1119        memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1120
1121        switch (index) {
1122        case 0: {
1123                v4l2_input.index = index;
1124                strcpy(&v4l2_input.name[0], "CVBS0");
1125                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1126                v4l2_input.audioset = 0x01;
1127                v4l2_input.tuner = 0;
1128                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1129                                V4L2_STD_NTSC ;
1130                v4l2_input.status = 0;
1131                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1132                break;
1133        }
1134        case 1: {
1135                v4l2_input.index = index;
1136                strcpy(&v4l2_input.name[0], "CVBS1");
1137                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1138                v4l2_input.audioset = 0x01;
1139                v4l2_input.tuner = 0;
1140                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1141                                V4L2_STD_NTSC ;
1142                v4l2_input.status = 0;
1143                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1144                break;
1145        }
1146        case 2: {
1147                v4l2_input.index = index;
1148                strcpy(&v4l2_input.name[0], "CVBS2");
1149                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1150                v4l2_input.audioset = 0x01;
1151                v4l2_input.tuner = 0;
1152                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1153                                V4L2_STD_NTSC ;
1154                v4l2_input.status = 0;
1155                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1156                break;
1157        }
1158        case 3: {
1159                v4l2_input.index = index;
1160                strcpy(&v4l2_input.name[0], "CVBS3");
1161                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1162                v4l2_input.audioset = 0x01;
1163                v4l2_input.tuner = 0;
1164                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1165                                V4L2_STD_NTSC ;
1166                v4l2_input.status = 0;
1167                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1168                break;
1169        }
1170        case 4: {
1171                v4l2_input.index = index;
1172                strcpy(&v4l2_input.name[0], "CVBS4");
1173                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1174                v4l2_input.audioset = 0x01;
1175                v4l2_input.tuner = 0;
1176                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1177                                V4L2_STD_NTSC ;
1178                v4l2_input.status = 0;
1179                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1180                break;
1181        }
1182        case 5: {
1183                v4l2_input.index = index;
1184                strcpy(&v4l2_input.name[0], "S-VIDEO");
1185                v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1186                v4l2_input.audioset = 0x01;
1187                v4l2_input.tuner = 0;
1188                v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1189                                V4L2_STD_NTSC ;
1190                v4l2_input.status = 0;
1191                JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
1192                break;
1193        }
1194        default: {
1195                JOM(8, "%i=index: exhausts inputs\n", index);
1196                mutex_unlock(&easycap_dongle[kd].mutex_video);
1197                return -EINVAL;
1198        }
1199        }
1200
1201        if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
1202                                                sizeof(struct v4l2_input))) {
1203                mutex_unlock(&easycap_dongle[kd].mutex_video);
1204                return -EFAULT;
1205        }
1206        break;
1207}
1208/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1209case VIDIOC_G_INPUT: {
1210        __u32 index;
1211
1212        JOM(8, "VIDIOC_G_INPUT\n");
1213        index = (__u32)peasycap->input;
1214        JOM(8, "user is told: %i\n", index);
1215        if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
1216                mutex_unlock(&easycap_dongle[kd].mutex_video);
1217                return -EFAULT;
1218        }
1219        break;
1220}
1221/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1222case VIDIOC_S_INPUT:
1223        {
1224        __u32 index;
1225        int rc;
1226
1227        JOM(8, "VIDIOC_S_INPUT\n");
1228
1229        if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
1230                mutex_unlock(&easycap_dongle[kd].mutex_video);
1231                return -EFAULT;
1232        }
1233
1234        JOM(8, "user requests input %i\n", index);
1235
1236        if ((int)index == peasycap->input) {
1237                SAM("requested input already in effect\n");
1238                break;
1239        }
1240
1241        if ((0 > index) || (INPUT_MANY <= index)) {
1242                JOM(8, "ERROR:  bad requested input: %i\n", index);
1243                mutex_unlock(&easycap_dongle[kd].mutex_video);
1244                return -EINVAL;
1245        }
1246
1247        rc = newinput(peasycap, (int)index);
1248        if (0 == rc) {
1249                JOM(8, "newinput(.,%i) OK\n", (int)index);
1250        } else {
1251                SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
1252                mutex_unlock(&easycap_dongle[kd].mutex_video);
1253                return -EFAULT;
1254        }
1255        break;
1256}
1257/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1258case VIDIOC_ENUMAUDIO: {
1259        JOM(8, "VIDIOC_ENUMAUDIO\n");
1260        mutex_unlock(&easycap_dongle[kd].mutex_video);
1261        return -EINVAL;
1262}
1263/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1264case VIDIOC_ENUMAUDOUT: {
1265        struct v4l2_audioout v4l2_audioout;
1266
1267        JOM(8, "VIDIOC_ENUMAUDOUT\n");
1268
1269        if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
1270                                        sizeof(struct v4l2_audioout))) {
1271                mutex_unlock(&easycap_dongle[kd].mutex_video);
1272                return -EFAULT;
1273        }
1274
1275        if (0 != v4l2_audioout.index) {
1276                mutex_unlock(&easycap_dongle[kd].mutex_video);
1277                return -EINVAL;
1278        }
1279        memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1280        v4l2_audioout.index = 0;
1281        strcpy(&v4l2_audioout.name[0], "Soundtrack");
1282
1283        if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
1284                                        sizeof(struct v4l2_audioout))) {
1285                mutex_unlock(&easycap_dongle[kd].mutex_video);
1286                return -EFAULT;
1287        }
1288        break;
1289}
1290/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1291case VIDIOC_QUERYCTRL: {
1292        int i1;
1293        struct v4l2_queryctrl v4l2_queryctrl;
1294
1295        JOM(8, "VIDIOC_QUERYCTRL\n");
1296
1297        if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
1298                                        sizeof(struct v4l2_queryctrl))) {
1299                mutex_unlock(&easycap_dongle[kd].mutex_video);
1300                return -EFAULT;
1301        }
1302
1303        i1 = 0;
1304        while (0xFFFFFFFF != easycap_control[i1].id) {
1305                if (easycap_control[i1].id == v4l2_queryctrl.id) {
1306                        JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]" \
1307                                ".name\n", &easycap_control[i1].name[0], i1);
1308                        memcpy(&v4l2_queryctrl, &easycap_control[i1], \
1309                                                sizeof(struct v4l2_queryctrl));
1310                        break;
1311                }
1312                i1++;
1313        }
1314        if (0xFFFFFFFF == easycap_control[i1].id) {
1315                JOM(8, "%i=index: exhausts controls\n", i1);
1316                mutex_unlock(&easycap_dongle[kd].mutex_video);
1317                return -EINVAL;
1318        }
1319        if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
1320                                        sizeof(struct v4l2_queryctrl))) {
1321                mutex_unlock(&easycap_dongle[kd].mutex_video);
1322                return -EFAULT;
1323        }
1324        break;
1325}
1326/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1327case VIDIOC_QUERYMENU: {
1328        JOM(8, "VIDIOC_QUERYMENU unsupported\n");
1329        mutex_unlock(&easycap_dongle[kd].mutex_video);
1330        return -EINVAL;
1331}
1332/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1333case VIDIOC_G_CTRL: {
1334        struct v4l2_control *pv4l2_control;
1335
1336        JOM(8, "VIDIOC_G_CTRL\n");
1337        pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
1338        if (!pv4l2_control) {
1339                SAM("ERROR: out of memory\n");
1340                mutex_unlock(&easycap_dongle[kd].mutex_video);
1341                return -ENOMEM;
1342        }
1343        if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
1344                                        sizeof(struct v4l2_control))) {
1345                kfree(pv4l2_control);
1346                mutex_unlock(&easycap_dongle[kd].mutex_video);
1347                return -EFAULT;
1348        }
1349
1350        switch (pv4l2_control->id) {
1351        case V4L2_CID_BRIGHTNESS: {
1352                pv4l2_control->value = peasycap->brightness;
1353                JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
1354                break;
1355        }
1356        case V4L2_CID_CONTRAST: {
1357                pv4l2_control->value = peasycap->contrast;
1358                JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
1359                break;
1360        }
1361        case V4L2_CID_SATURATION: {
1362                pv4l2_control->value = peasycap->saturation;
1363                JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
1364                break;
1365        }
1366        case V4L2_CID_HUE: {
1367                pv4l2_control->value = peasycap->hue;
1368                JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
1369                break;
1370        }
1371        case V4L2_CID_AUDIO_VOLUME: {
1372                pv4l2_control->value = peasycap->volume;
1373                JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
1374                break;
1375        }
1376        case V4L2_CID_AUDIO_MUTE: {
1377                if (1 == peasycap->mute)
1378                        pv4l2_control->value = true;
1379                else
1380                        pv4l2_control->value = false;
1381                JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
1382                break;
1383        }
1384        default: {
1385                SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
1386                                                        pv4l2_control->id);
1387                kfree(pv4l2_control);
1388                mutex_unlock(&easycap_dongle[kd].mutex_video);
1389                return -EINVAL;
1390        }
1391        }
1392        if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
1393                                        sizeof(struct v4l2_control))) {
1394                kfree(pv4l2_control);
1395                mutex_unlock(&easycap_dongle[kd].mutex_video);
1396                return -EFAULT;
1397        }
1398        kfree(pv4l2_control);
1399        break;
1400}
1401/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1402#if defined(VIDIOC_S_CTRL_OLD)
1403case VIDIOC_S_CTRL_OLD: {
1404        JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
1405}
1406#endif /*VIDIOC_S_CTRL_OLD*/
1407case VIDIOC_S_CTRL:
1408        {
1409        struct v4l2_control v4l2_control;
1410
1411        JOM(8, "VIDIOC_S_CTRL\n");
1412
1413        if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
1414                                        sizeof(struct v4l2_control))) {
1415                mutex_unlock(&easycap_dongle[kd].mutex_video);
1416                return -EFAULT;
1417        }
1418
1419        switch (v4l2_control.id) {
1420        case V4L2_CID_BRIGHTNESS: {
1421                JOM(8, "user requests brightness %i\n", v4l2_control.value);
1422                if (0 != adjust_brightness(peasycap, v4l2_control.value))
1423                        ;
1424                break;
1425        }
1426        case V4L2_CID_CONTRAST: {
1427                JOM(8, "user requests contrast %i\n", v4l2_control.value);
1428                if (0 != adjust_contrast(peasycap, v4l2_control.value))
1429                        ;
1430                break;
1431        }
1432        case V4L2_CID_SATURATION: {
1433                JOM(8, "user requests saturation %i\n", v4l2_control.value);
1434                if (0 != adjust_saturation(peasycap, v4l2_control.value))
1435                        ;
1436                break;
1437        }
1438        case V4L2_CID_HUE: {
1439                JOM(8, "user requests hue %i\n", v4l2_control.value);
1440                if (0 != adjust_hue(peasycap, v4l2_control.value))
1441                        ;
1442                break;
1443        }
1444        case V4L2_CID_AUDIO_VOLUME: {
1445                JOM(8, "user requests volume %i\n", v4l2_control.value);
1446                if (0 != adjust_volume(peasycap, v4l2_control.value))
1447                        ;
1448                break;
1449        }
1450        case V4L2_CID_AUDIO_MUTE: {
1451                int mute;
1452
1453                JOM(8, "user requests mute %i\n", v4l2_control.value);
1454                if (true == v4l2_control.value)
1455                        mute = 1;
1456                else
1457                        mute = 0;
1458
1459                if (0 != adjust_mute(peasycap, mute))
1460                        SAM("WARNING: failed to adjust mute to %i\n", mute);
1461                break;
1462        }
1463        default: {
1464                SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
1465                                                        v4l2_control.id);
1466                mutex_unlock(&easycap_dongle[kd].mutex_video);
1467                return -EINVAL;
1468        }
1469        }
1470        break;
1471}
1472/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1473case VIDIOC_S_EXT_CTRLS: {
1474        JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
1475        mutex_unlock(&easycap_dongle[kd].mutex_video);
1476        return -EINVAL;
1477}
1478/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1479case VIDIOC_ENUM_FMT: {
1480        __u32 index;
1481        struct v4l2_fmtdesc v4l2_fmtdesc;
1482
1483        JOM(8, "VIDIOC_ENUM_FMT\n");
1484
1485        if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
1486                                        sizeof(struct v4l2_fmtdesc))) {
1487                mutex_unlock(&easycap_dongle[kd].mutex_video);
1488                return -EFAULT;
1489        }
1490
1491        index = v4l2_fmtdesc.index;
1492        memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1493
1494        v4l2_fmtdesc.index = index;
1495        v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1496
1497        switch (index) {
1498        case 0: {
1499                v4l2_fmtdesc.flags = 0;
1500                strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1501                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
1502                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1503                break;
1504        }
1505        case 1: {
1506                v4l2_fmtdesc.flags = 0;
1507                strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1508                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
1509                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1510                break;
1511        }
1512        case 2: {
1513                v4l2_fmtdesc.flags = 0;
1514                strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1515                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
1516                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1517                break;
1518        }
1519        case 3: {
1520                v4l2_fmtdesc.flags = 0;
1521                strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1522                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
1523                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1524                break;
1525        }
1526        case 4: {
1527                v4l2_fmtdesc.flags = 0;
1528                strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1529                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
1530                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1531                break;
1532        }
1533        case 5: {
1534                v4l2_fmtdesc.flags = 0;
1535                strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1536                v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
1537                JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
1538                break;
1539        }
1540        default: {
1541                JOM(8, "%i=index: exhausts formats\n", index);
1542                mutex_unlock(&easycap_dongle[kd].mutex_video);
1543                return -EINVAL;
1544        }
1545        }
1546        if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
1547                                        sizeof(struct v4l2_fmtdesc))) {
1548                mutex_unlock(&easycap_dongle[kd].mutex_video);
1549                return -EFAULT;
1550        }
1551        break;
1552}
1553/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1554/*
1555 *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1556 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1557*/
1558/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1559case VIDIOC_ENUM_FRAMESIZES: {
1560        __u32 index;
1561        struct v4l2_frmsizeenum v4l2_frmsizeenum;
1562
1563        JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1564
1565        if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
1566                                        sizeof(struct v4l2_frmsizeenum))) {
1567                mutex_unlock(&easycap_dongle[kd].mutex_video);
1568                return -EFAULT;
1569        }
1570
1571        index = v4l2_frmsizeenum.index;
1572
1573        v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1574
1575        if (true == peasycap->ntsc) {
1576                switch (index) {
1577                case 0: {
1578                        v4l2_frmsizeenum.discrete.width = 640;
1579                        v4l2_frmsizeenum.discrete.height = 480;
1580                        JOM(8, "%i=index: %ix%i\n", index, \
1581                                        (int)(v4l2_frmsizeenum.\
1582                                                 discrete.width), \
1583                                        (int)(v4l2_frmsizeenum.\
1584                                                discrete.height));
1585                        break;
1586                }
1587                case 1: {
1588                        v4l2_frmsizeenum.discrete.width = 320;
1589                        v4l2_frmsizeenum.discrete.height = 240;
1590                        JOM(8, "%i=index: %ix%i\n", index, \
1591                                        (int)(v4l2_frmsizeenum.\
1592                                                discrete.width), \
1593                                        (int)(v4l2_frmsizeenum.\
1594                                                discrete.height));
1595                        break;
1596                }
1597                case 2: {
1598                        v4l2_frmsizeenum.discrete.width = 720;
1599                        v4l2_frmsizeenum.discrete.height = 480;
1600                        JOM(8, "%i=index: %ix%i\n", index, \
1601                                        (int)(v4l2_frmsizeenum.\
1602                                                discrete.width), \
1603                                        (int)(v4l2_frmsizeenum.\
1604                                                discrete.height));
1605                        break;
1606                }
1607                case 3: {
1608                        v4l2_frmsizeenum.discrete.width = 360;
1609                        v4l2_frmsizeenum.discrete.height = 240;
1610                        JOM(8, "%i=index: %ix%i\n", index, \
1611                                        (int)(v4l2_frmsizeenum.\
1612                                                discrete.width), \
1613                                        (int)(v4l2_frmsizeenum.\
1614                                                discrete.height));
1615                        break;
1616                }
1617                default: {
1618                        JOM(8, "%i=index: exhausts framesizes\n", index);
1619                        mutex_unlock(&easycap_dongle[kd].mutex_video);
1620                        return -EINVAL;
1621                }
1622                }
1623        } else {
1624                switch (index) {
1625                case 0: {
1626                        v4l2_frmsizeenum.discrete.width = 640;
1627                        v4l2_frmsizeenum.discrete.height = 480;
1628                        JOM(8, "%i=index: %ix%i\n", index, \
1629                                        (int)(v4l2_frmsizeenum.\
1630                                                discrete.width), \
1631                                        (int)(v4l2_frmsizeenum.\
1632                                                discrete.height));
1633                        break;
1634                }
1635                case 1: {
1636                        v4l2_frmsizeenum.discrete.width = 320;
1637                        v4l2_frmsizeenum.discrete.height = 240;
1638                        JOM(8, "%i=index: %ix%i\n", index, \
1639                                        (int)(v4l2_frmsizeenum.\
1640                                                discrete.width), \
1641                                        (int)(v4l2_frmsizeenum.\
1642                                                discrete.height));
1643                        break;
1644                }
1645                case 2: {
1646                        v4l2_frmsizeenum.discrete.width = 704;
1647                        v4l2_frmsizeenum.discrete.height = 576;
1648                        JOM(8, "%i=index: %ix%i\n", index, \
1649                                        (int)(v4l2_frmsizeenum.\
1650                                                discrete.width), \
1651                                        (int)(v4l2_frmsizeenum.\
1652                                                discrete.height));
1653                        break;
1654                }
1655                case 3: {
1656                        v4l2_frmsizeenum.discrete.width = 720;
1657                        v4l2_frmsizeenum.discrete.height = 576;
1658                        JOM(8, "%i=index: %ix%i\n", index, \
1659                                        (int)(v4l2_frmsizeenum.\
1660                                                discrete.width), \
1661                                        (int)(v4l2_frmsizeenum.\
1662                                                discrete.height));
1663                        break;
1664                }
1665                case 4: {
1666                        v4l2_frmsizeenum.discrete.width = 360;
1667                        v4l2_frmsizeenum.discrete.height = 288;
1668                        JOM(8, "%i=index: %ix%i\n", index, \
1669                                        (int)(v4l2_frmsizeenum.\
1670                                                discrete.width), \
1671                                        (int)(v4l2_frmsizeenum.\
1672                                                discrete.height));
1673                        break;
1674                }
1675                default: {
1676                        JOM(8, "%i=index: exhausts framesizes\n", index);
1677                        mutex_unlock(&easycap_dongle[kd].mutex_video);
1678                        return -EINVAL;
1679                }
1680                }
1681        }
1682        if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
1683                                        sizeof(struct v4l2_frmsizeenum))) {
1684                mutex_unlock(&easycap_dongle[kd].mutex_video);
1685                return -EFAULT;
1686        }
1687        break;
1688}
1689/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1690/*
1691 *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1692 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
1693*/
1694/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1695case VIDIOC_ENUM_FRAMEINTERVALS: {
1696        __u32 index;
1697        int denominator;
1698        struct v4l2_frmivalenum v4l2_frmivalenum;
1699
1700        JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1701
1702        if (peasycap->fps)
1703                denominator = peasycap->fps;
1704        else {
1705                if (true == peasycap->ntsc)
1706                        denominator = 30;
1707                else
1708                        denominator = 25;
1709        }
1710
1711        if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
1712                                        sizeof(struct v4l2_frmivalenum))) {
1713                mutex_unlock(&easycap_dongle[kd].mutex_video);
1714                return -EFAULT;
1715        }
1716
1717        index = v4l2_frmivalenum.index;
1718
1719        v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1720
1721        switch (index) {
1722        case 0: {
1723                v4l2_frmivalenum.discrete.numerator = 1;
1724                v4l2_frmivalenum.discrete.denominator = denominator;
1725                JOM(8, "%i=index: %i/%i\n", index, \
1726                        (int)(v4l2_frmivalenum.discrete.numerator), \
1727                        (int)(v4l2_frmivalenum.discrete.denominator));
1728                break;
1729        }
1730        case 1: {
1731                v4l2_frmivalenum.discrete.numerator = 1;
1732                v4l2_frmivalenum.discrete.denominator = denominator/5;
1733                JOM(8, "%i=index: %i/%i\n", index, \
1734                        (int)(v4l2_frmivalenum.discrete.numerator), \
1735                        (int)(v4l2_frmivalenum.discrete.denominator));
1736                break;
1737        }
1738        default: {
1739                JOM(8, "%i=index: exhausts frameintervals\n", index);
1740                mutex_unlock(&easycap_dongle[kd].mutex_video);
1741                return -EINVAL;
1742        }
1743        }
1744        if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
1745                                        sizeof(struct v4l2_frmivalenum))) {
1746                mutex_unlock(&easycap_dongle[kd].mutex_video);
1747                return -EFAULT;
1748        }
1749        break;
1750}
1751/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1752case VIDIOC_G_FMT: {
1753        struct v4l2_format *pv4l2_format;
1754        struct v4l2_pix_format *pv4l2_pix_format;
1755
1756        JOM(8, "VIDIOC_G_FMT\n");
1757        pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1758        if (!pv4l2_format) {
1759                SAM("ERROR: out of memory\n");
1760                mutex_unlock(&easycap_dongle[kd].mutex_video);
1761                return -ENOMEM;
1762        }
1763        pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1764        if (!pv4l2_pix_format) {
1765                SAM("ERROR: out of memory\n");
1766                kfree(pv4l2_format);
1767                mutex_unlock(&easycap_dongle[kd].mutex_video);
1768                return -ENOMEM;
1769        }
1770        if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
1771                                        sizeof(struct v4l2_format))) {
1772                kfree(pv4l2_format);
1773                kfree(pv4l2_pix_format);
1774                mutex_unlock(&easycap_dongle[kd].mutex_video);
1775                return -EFAULT;
1776        }
1777
1778        if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1779                kfree(pv4l2_format);
1780                kfree(pv4l2_pix_format);
1781                mutex_unlock(&easycap_dongle[kd].mutex_video);
1782                return -EINVAL;
1783        }
1784
1785        memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1786        pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1787        memcpy(&pv4l2_format->fmt.pix, \
1788                         &easycap_format[peasycap->format_offset]\
1789                        .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
1790        JOM(8, "user is told: %s\n", \
1791                        &easycap_format[peasycap->format_offset].name[0]);
1792
1793        if (0 != copy_to_user((void __user *)arg, pv4l2_format, \
1794                                        sizeof(struct v4l2_format))) {
1795                kfree(pv4l2_format);
1796                kfree(pv4l2_pix_format);
1797                mutex_unlock(&easycap_dongle[kd].mutex_video);
1798                return -EFAULT;
1799        }
1800        kfree(pv4l2_format);
1801        kfree(pv4l2_pix_format);
1802        break;
1803}
1804/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1805case VIDIOC_TRY_FMT:
1806case VIDIOC_S_FMT: {
1807        struct v4l2_format v4l2_format;
1808        struct v4l2_pix_format v4l2_pix_format;
1809        bool try;
1810        int best_format;
1811
1812        if (VIDIOC_TRY_FMT == cmd) {
1813                JOM(8, "VIDIOC_TRY_FMT\n");
1814                try = true;
1815        } else {
1816                JOM(8, "VIDIOC_S_FMT\n");
1817                try = false;
1818        }
1819
1820        if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
1821                                        sizeof(struct v4l2_format))) {
1822                mutex_unlock(&easycap_dongle[kd].mutex_video);
1823                return -EFAULT;
1824        }
1825
1826        best_format = adjust_format(peasycap, \
1827                                        v4l2_format.fmt.pix.width, \
1828                                        v4l2_format.fmt.pix.height, \
1829                                        v4l2_format.fmt.pix.pixelformat, \
1830                                        v4l2_format.fmt.pix.field, \
1831                                        try);
1832        if (0 > best_format) {
1833                if (-EBUSY == best_format) {
1834                        mutex_unlock(&easycap_dongle[kd].mutex_video);
1835                        return -EBUSY;
1836                }
1837                JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
1838                mutex_unlock(&easycap_dongle[kd].mutex_video);
1839                return -ENOENT;
1840        }
1841/*...........................................................................*/
1842        memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1843        v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1844
1845        memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\
1846                        .v4l2_format.fmt.pix), sizeof(v4l2_pix_format));
1847        JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
1848
1849        if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
1850                                        sizeof(struct v4l2_format))) {
1851                mutex_unlock(&easycap_dongle[kd].mutex_video);
1852                return -EFAULT;
1853        }
1854        break;
1855}
1856/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1857case VIDIOC_CROPCAP: {
1858        struct v4l2_cropcap v4l2_cropcap;
1859
1860        JOM(8, "VIDIOC_CROPCAP\n");
1861
1862        if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
1863                                        sizeof(struct v4l2_cropcap))) {
1864                mutex_unlock(&easycap_dongle[kd].mutex_video);
1865                return -EFAULT;
1866        }
1867
1868        if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1869                JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
1870
1871        memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1872        v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1873        v4l2_cropcap.bounds.left      = 0;
1874        v4l2_cropcap.bounds.top       = 0;
1875        v4l2_cropcap.bounds.width     = peasycap->width;
1876        v4l2_cropcap.bounds.height    = peasycap->height;
1877        v4l2_cropcap.defrect.left     = 0;
1878        v4l2_cropcap.defrect.top      = 0;
1879        v4l2_cropcap.defrect.width    = peasycap->width;
1880        v4l2_cropcap.defrect.height   = peasycap->height;
1881        v4l2_cropcap.pixelaspect.numerator = 1;
1882        v4l2_cropcap.pixelaspect.denominator = 1;
1883
1884        JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
1885
1886        if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
1887                                        sizeof(struct v4l2_cropcap))) {
1888                mutex_unlock(&easycap_dongle[kd].mutex_video);
1889                return -EFAULT;
1890        }
1891        break;
1892}
1893/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1894case VIDIOC_G_CROP:
1895case VIDIOC_S_CROP: {
1896        JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
1897        mutex_unlock(&easycap_dongle[kd].mutex_video);
1898        return -EINVAL;
1899}
1900/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1901case VIDIOC_QUERYSTD: {
1902        JOM(8, "VIDIOC_QUERYSTD: " \
1903                        "EasyCAP is incapable of detecting standard\n");
1904        mutex_unlock(&easycap_dongle[kd].mutex_video);
1905        return -EINVAL;
1906        break;
1907}
1908/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1909/*---------------------------------------------------------------------------*/
1910/*
1911 *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
1912 *  FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
1913 *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1914 */
1915/*---------------------------------------------------------------------------*/
1916case VIDIOC_ENUMSTD: {
1917        int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1918        struct v4l2_standard v4l2_standard;
1919        __u32 index;
1920        struct easycap_standard const *peasycap_standard;
1921
1922        JOM(8, "VIDIOC_ENUMSTD\n");
1923
1924        if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
1925                                        sizeof(struct v4l2_standard))) {
1926                mutex_unlock(&easycap_dongle[kd].mutex_video);
1927                return -EFAULT;
1928        }
1929        index = v4l2_standard.index;
1930
1931        last3 = last2; last2 = last1; last1 = last0; last0 = index;
1932        if ((index == last3) && (index == last2) && \
1933                        (index == last1) && (index == last0)) {
1934                index++;
1935                last3 = last2; last2 = last1; last1 = last0; last0 = index;
1936        }
1937
1938        memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1939
1940        peasycap_standard = &easycap_standard[0];
1941        while (0xFFFF != peasycap_standard->mask) {
1942                if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1943                        break;
1944                peasycap_standard++;
1945        }
1946        if (0xFFFF == peasycap_standard->mask) {
1947                JOM(8, "%i=index: exhausts standards\n", index);
1948                mutex_unlock(&easycap_dongle[kd].mutex_video);
1949                return -EINVAL;
1950        }
1951        JOM(8, "%i=index: %s\n", index, \
1952                                &(peasycap_standard->v4l2_standard.name[0]));
1953        memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), \
1954                                        sizeof(struct v4l2_standard));
1955
1956        v4l2_standard.index = index;
1957
1958        if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
1959                                        sizeof(struct v4l2_standard))) {
1960                mutex_unlock(&easycap_dongle[kd].mutex_video);
1961                return -EFAULT;
1962        }
1963        break;
1964}
1965/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1966case VIDIOC_G_STD: {
1967        v4l2_std_id std_id;
1968        struct easycap_standard const *peasycap_standard;
1969
1970        JOM(8, "VIDIOC_G_STD\n");
1971
1972        if (0 > peasycap->standard_offset) {
1973                JOM(8, "%i=peasycap->standard_offset\n", \
1974                                        peasycap->standard_offset);
1975                mutex_unlock(&easycap_dongle[kd].mutex_video);
1976                return -EBUSY;
1977        }
1978
1979        if (0 != copy_from_user(&std_id, (void __user *)arg, \
1980                                                sizeof(v4l2_std_id))) {
1981                mutex_unlock(&easycap_dongle[kd].mutex_video);
1982                return -EFAULT;
1983        }
1984
1985        peasycap_standard = &easycap_standard[peasycap->standard_offset];
1986        std_id = peasycap_standard->v4l2_standard.id;
1987
1988        JOM(8, "user is told: %s\n", \
1989                                &peasycap_standard->v4l2_standard.name[0]);
1990
1991        if (0 != copy_to_user((void __user *)arg, &std_id, \
1992                                                sizeof(v4l2_std_id))) {
1993                mutex_unlock(&easycap_dongle[kd].mutex_video);
1994                return -EFAULT;
1995        }
1996        break;
1997}
1998/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1999case VIDIOC_S_STD: {
2000        v4l2_std_id std_id;
2001        int rc;
2002
2003        JOM(8, "VIDIOC_S_STD\n");
2004
2005        if (0 != copy_from_user(&std_id, (void __user *)arg, \
2006                                                sizeof(v4l2_std_id))) {
2007                mutex_unlock(&easycap_dongle[kd].mutex_video);
2008                return -EFAULT;
2009        }
2010
2011        JOM(8, "User requests standard: 0x%08X%08X\n", \
2012                (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
2013                (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
2014
2015        rc = adjust_standard(peasycap, std_id);
2016        if (0 > rc) {
2017                JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
2018                mutex_unlock(&easycap_dongle[kd].mutex_video);
2019                return -ENOENT;
2020        }
2021        break;
2022}
2023/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2024case VIDIOC_REQBUFS: {
2025        int nbuffers;
2026        struct v4l2_requestbuffers v4l2_requestbuffers;
2027
2028        JOM(8, "VIDIOC_REQBUFS\n");
2029
2030        if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
2031                                sizeof(struct v4l2_requestbuffers))) {
2032                mutex_unlock(&easycap_dongle[kd].mutex_video);
2033                return -EFAULT;
2034        }
2035
2036        if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2037                mutex_unlock(&easycap_dongle[kd].mutex_video);
2038                return -EINVAL;
2039        }
2040        if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2041                mutex_unlock(&easycap_dongle[kd].mutex_video);
2042                return -EINVAL;
2043        }
2044        nbuffers = v4l2_requestbuffers.count;
2045        JOM(8, "                   User requests %i buffers ...\n", nbuffers);
2046        if (nbuffers < 2)
2047                nbuffers = 2;
2048        if (nbuffers > FRAME_BUFFER_MANY)
2049                nbuffers = FRAME_BUFFER_MANY;
2050        if (v4l2_requestbuffers.count == nbuffers) {
2051                JOM(8, "                   ... agree to  %i buffers\n", \
2052                                                                nbuffers);
2053        } else {
2054                JOM(8, "                  ... insist on  %i buffers\n", \
2055                                                                nbuffers);
2056                v4l2_requestbuffers.count = nbuffers;
2057        }
2058        peasycap->frame_buffer_many = nbuffers;
2059
2060        if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
2061                                sizeof(struct v4l2_requestbuffers))) {
2062                mutex_unlock(&easycap_dongle[kd].mutex_video);
2063                return -EFAULT;
2064        }
2065        break;
2066}
2067/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2068case VIDIOC_QUERYBUF: {
2069        __u32 index;
2070        struct v4l2_buffer v4l2_buffer;
2071
2072        JOM(8, "VIDIOC_QUERYBUF\n");
2073
2074        if (peasycap->video_eof) {
2075                JOM(8, "returning -EIO because  %i=video_eof\n", \
2076                                                        peasycap->video_eof);
2077                mutex_unlock(&easycap_dongle[kd].mutex_video);
2078                return -EIO;
2079        }
2080
2081        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
2082                                        sizeof(struct v4l2_buffer))) {
2083                mutex_unlock(&easycap_dongle[kd].mutex_video);
2084                return -EFAULT;
2085        }
2086
2087        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2088                mutex_unlock(&easycap_dongle[kd].mutex_video);
2089                return -EINVAL;
2090        }
2091        index = v4l2_buffer.index;
2092        if (index < 0 || index >= peasycap->frame_buffer_many)
2093                return -EINVAL;
2094        memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2095        v4l2_buffer.index = index;
2096        v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2097        v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2098        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
2099                                                peasycap->done[index] | \
2100                                                peasycap->queued[index];
2101        v4l2_buffer.field = V4L2_FIELD_NONE;
2102        v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2103        v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2104        v4l2_buffer.length = FRAME_BUFFER_SIZE;
2105
2106        JOM(16, "  %10i=index\n", v4l2_buffer.index);
2107        JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2108        JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2109        JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2110        JOM(16, "  %10i=field\n", v4l2_buffer.field);
2111        JOM(16, "  %10li=timestamp.tv_usec\n", \
2112                                         (long)v4l2_buffer.timestamp.tv_usec);
2113        JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2114        JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2115        JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2116        JOM(16, "  %10i=length\n", v4l2_buffer.length);
2117
2118        if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
2119                                        sizeof(struct v4l2_buffer))) {
2120                mutex_unlock(&easycap_dongle[kd].mutex_video);
2121                return -EFAULT;
2122        }
2123        break;
2124}
2125/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2126case VIDIOC_QBUF: {
2127        struct v4l2_buffer v4l2_buffer;
2128
2129        JOM(8, "VIDIOC_QBUF\n");
2130
2131        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
2132                                        sizeof(struct v4l2_buffer))) {
2133                mutex_unlock(&easycap_dongle[kd].mutex_video);
2134                return -EFAULT;
2135        }
2136
2137        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2138                mutex_unlock(&easycap_dongle[kd].mutex_video);
2139                return -EINVAL;
2140        }
2141        if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2142                mutex_unlock(&easycap_dongle[kd].mutex_video);
2143                return -EINVAL;
2144        }
2145        if (v4l2_buffer.index < 0 || \
2146                 (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
2147                mutex_unlock(&easycap_dongle[kd].mutex_video);
2148                return -EINVAL;
2149        }
2150        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2151
2152        peasycap->done[v4l2_buffer.index]   = 0;
2153        peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2154
2155        if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
2156                                        sizeof(struct v4l2_buffer))) {
2157                mutex_unlock(&easycap_dongle[kd].mutex_video);
2158                return -EFAULT;
2159        }
2160
2161        JOM(8, ".....   user queueing frame buffer %i\n", \
2162                                                (int)v4l2_buffer.index);
2163
2164        peasycap->frame_lock = 0;
2165
2166        break;
2167}
2168/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2169case VIDIOC_DQBUF:
2170        {
2171#if defined(AUDIOTIME)
2172        struct signed_div_result sdr;
2173        long long int above, below, dnbydt, fudge, sll;
2174        unsigned long long int ull;
2175        struct timeval timeval8;
2176        struct timeval timeval1;
2177#endif /*AUDIOTIME*/
2178        struct timeval timeval, timeval2;
2179        int i, j;
2180        struct v4l2_buffer v4l2_buffer;
2181        int rcdq;
2182        __u16 input;
2183
2184        JOM(8, "VIDIOC_DQBUF\n");
2185
2186        if ((peasycap->video_idle) || (peasycap->video_eof)) {
2187                JOM(8, "returning -EIO because  " \
2188                                "%i=video_idle  %i=video_eof\n", \
2189                                peasycap->video_idle, peasycap->video_eof);
2190                mutex_unlock(&easycap_dongle[kd].mutex_video);
2191                return -EIO;
2192        }
2193
2194        if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
2195                                        sizeof(struct v4l2_buffer))) {
2196                mutex_unlock(&easycap_dongle[kd].mutex_video);
2197                return -EFAULT;
2198        }
2199
2200        if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2201                mutex_unlock(&easycap_dongle[kd].mutex_video);
2202                return -EINVAL;
2203        }
2204
2205        if (true == peasycap->offerfields) {
2206                /*-----------------------------------------------------------*/
2207                /*
2208                 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2209                 *  V4L2_FIELD_BOTTOM
2210                */
2211                /*-----------------------------------------------------------*/
2212                if (V4L2_FIELD_TOP == v4l2_buffer.field)
2213                        JOM(8, "user wants V4L2_FIELD_TOP\n");
2214                else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2215                        JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2216                else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2217                        JOM(8, "user wants V4L2_FIELD_ANY\n");
2218                else
2219                        JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
2220                                                        v4l2_buffer.field);
2221        }
2222
2223        if (!peasycap->video_isoc_streaming) {
2224                JOM(16, "returning -EIO because video urbs not streaming\n");
2225                mutex_unlock(&easycap_dongle[kd].mutex_video);
2226                return -EIO;
2227        }
2228/*---------------------------------------------------------------------------*/
2229/*
2230 *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
2231 *  THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE.  IN THIS
2232 *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2233 */
2234/*---------------------------------------------------------------------------*/
2235
2236        if (!peasycap->polled) {
2237                do {
2238                        rcdq = easycap_dqbuf(peasycap, 0);
2239                        if (-EIO == rcdq) {
2240                                JOM(8, "returning -EIO because " \
2241                                                "dqbuf() returned -EIO\n");
2242                                mutex_unlock(&easycap_dongle[kd].mutex_video);
2243                                return -EIO;
2244                        }
2245                } while (0 != rcdq);
2246        } else {
2247                if (peasycap->video_eof) {
2248                        mutex_unlock(&easycap_dongle[kd].mutex_video);
2249                        return -EIO;
2250                }
2251        }
2252        if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
2253                SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
2254                                        peasycap->done[peasycap->frame_read]);
2255        }
2256        peasycap->polled = 0;
2257
2258        if (!(peasycap->isequence % 10)) {
2259                for (i = 0; i < 179; i++)
2260                        peasycap->merit[i] = peasycap->merit[i+1];
2261                peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2262                j = 0;
2263                for (i = 0; i < 180; i++)
2264                        j += peasycap->merit[i];
2265                if (90 < j) {
2266                        SAM("easycap driver shutting down " \
2267                                                        "on condition blue\n");
2268                        peasycap->video_eof = 1; peasycap->audio_eof = 1;
2269                }
2270        }
2271
2272        v4l2_buffer.index = peasycap->frame_read;
2273        v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2274        v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2275        v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
2276        if (true == peasycap->offerfields)
2277                v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2278        else
2279                v4l2_buffer.field = V4L2_FIELD_NONE;
2280        do_gettimeofday(&timeval);
2281        timeval2 = timeval;
2282
2283#if defined(AUDIOTIME)
2284        if (!peasycap->timeval0.tv_sec) {
2285                timeval8 = timeval;
2286                timeval1 = timeval;
2287                timeval2 = timeval;
2288                dnbydt = 192000;
2289                peasycap->timeval0 = timeval8;
2290        } else {
2291                dnbydt = peasycap->dnbydt;
2292                timeval1 = peasycap->timeval1;
2293                above = dnbydt * MICROSECONDS(timeval, timeval1);
2294                below = 192000;
2295                sdr = signed_div(above, below);
2296
2297                above = sdr.quotient + timeval1.tv_usec - 350000;
2298
2299                below = 1000000;
2300                sdr = signed_div(above, below);
2301                timeval2.tv_usec = sdr.remainder;
2302                timeval2.tv_sec = timeval1.tv_sec + sdr.quotient;
2303        }
2304        if (!(peasycap->isequence % 500)) {
2305                fudge = ((long long int)(1000000)) * \
2306                                ((long long int)(timeval.tv_sec - \
2307                                                timeval2.tv_sec)) + \
2308                                (long long int)(timeval.tv_usec - \
2309                                                timeval2.tv_usec);
2310                sdr = signed_div(fudge, 1000);
2311                sll = sdr.quotient;
2312                ull = sdr.remainder;
2313
2314                SAM("%5lli.%-3lli=ms timestamp fudge\n", sll, ull);
2315        }
2316#endif /*AUDIOTIME*/
2317
2318        v4l2_buffer.timestamp = timeval2;
2319        v4l2_buffer.sequence = peasycap->isequence++;
2320        v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2321        v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2322        v4l2_buffer.length = FRAME_BUFFER_SIZE;
2323
2324        JOM(16, "  %10i=index\n", v4l2_buffer.index);
2325        JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
2326        JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
2327        JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
2328        JOM(16, "  %10i=field\n", v4l2_buffer.field);
2329        JOM(16, "  %10li=timestamp.tv_sec\n", \
2330                                        (long)v4l2_buffer.timestamp.tv_sec);
2331        JOM(16, "  %10li=timestamp.tv_usec\n", \
2332                                        (long)v4l2_buffer.timestamp.tv_usec);
2333        JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
2334        JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
2335        JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
2336        JOM(16, "  %10i=length\n", v4l2_buffer.length);
2337
2338        if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
2339                                                sizeof(struct v4l2_buffer))) {
2340                mutex_unlock(&easycap_dongle[kd].mutex_video);
2341                return -EFAULT;
2342        }
2343
2344        input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2345        if (0x08 & input) {
2346                JOM(8, "user is offered frame buffer %i, input %i\n", \
2347                                        peasycap->frame_read, (0x07 & input));
2348        } else {
2349                JOM(8, "user is offered frame buffer %i\n", \
2350                                                        peasycap->frame_read);
2351        }
2352        peasycap->frame_lock = 1;
2353        JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
2354        if (peasycap->frame_read == peasycap->frame_fill) {
2355                if (peasycap->frame_lock) {
2356                        JOM(8, "WORRY:  filling frame buffer " \
2357                                                "while offered to user\n");
2358                }
2359        }
2360        break;
2361}
2362/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2363case VIDIOC_STREAMON: {
2364        int i;
2365
2366        JOM(8, "VIDIOC_STREAMON\n");
2367
2368        peasycap->isequence = 0;
2369        for (i = 0; i < 180; i++)
2370                peasycap->merit[i] = 0;
2371        if ((struct usb_device *)NULL == peasycap->pusb_device) {
2372                SAM("ERROR: peasycap->pusb_device is NULL\n");
2373                mutex_unlock(&easycap_dongle[kd].mutex_video);
2374                return -EFAULT;
2375        }
2376        submit_video_urbs(peasycap);
2377        peasycap->video_idle = 0;
2378        peasycap->audio_idle = 0;
2379        peasycap->video_eof = 0;
2380        peasycap->audio_eof = 0;
2381        break;
2382}
2383/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2384case VIDIOC_STREAMOFF: {
2385        JOM(8, "VIDIOC_STREAMOFF\n");
2386
2387        if ((struct usb_device *)NULL == peasycap->pusb_device) {
2388                SAM("ERROR: peasycap->pusb_device is NULL\n");
2389                mutex_unlock(&easycap_dongle[kd].mutex_video);
2390                return -EFAULT;
2391        }
2392
2393        peasycap->video_idle = 1;
2394        peasycap->audio_idle = 1;  peasycap->timeval0.tv_sec = 0;
2395/*---------------------------------------------------------------------------*/
2396/*
2397 *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2398 *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
2399 */
2400/*---------------------------------------------------------------------------*/
2401        JOM(8, "calling wake_up on wq_video and wq_audio\n");
2402        wake_up_interruptible(&(peasycap->wq_video));
2403        wake_up_interruptible(&(peasycap->wq_audio));
2404/*---------------------------------------------------------------------------*/
2405        break;
2406}
2407/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2408case VIDIOC_G_PARM: {
2409        struct v4l2_streamparm *pv4l2_streamparm;
2410
2411        JOM(8, "VIDIOC_G_PARM\n");
2412        pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2413        if (!pv4l2_streamparm) {
2414                SAM("ERROR: out of memory\n");
2415                mutex_unlock(&easycap_dongle[kd].mutex_video);
2416                return -ENOMEM;
2417        }
2418        if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
2419                                        sizeof(struct v4l2_streamparm))) {
2420                kfree(pv4l2_streamparm);
2421                mutex_unlock(&easycap_dongle[kd].mutex_video);
2422                return -EFAULT;
2423        }
2424
2425        if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2426                kfree(pv4l2_streamparm);
2427                mutex_unlock(&easycap_dongle[kd].mutex_video);
2428                return -EINVAL;
2429        }
2430        pv4l2_streamparm->parm.capture.capability = 0;
2431        pv4l2_streamparm->parm.capture.capturemode = 0;
2432        pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
2433
2434        if (peasycap->fps) {
2435                pv4l2_streamparm->parm.capture.timeperframe.\
2436                                                denominator = peasycap->fps;
2437        } else {
2438                if (true == peasycap->ntsc) {
2439                        pv4l2_streamparm->parm.capture.timeperframe.\
2440                                                denominator = 30;
2441                } else {
2442                        pv4l2_streamparm->parm.capture.timeperframe.\
2443                                                denominator = 25;
2444                }
2445        }
2446
2447        pv4l2_streamparm->parm.capture.readbuffers = \
2448                                                peasycap->frame_buffer_many;
2449        pv4l2_streamparm->parm.capture.extendedmode = 0;
2450        if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
2451                                        sizeof(struct v4l2_streamparm))) {
2452                kfree(pv4l2_streamparm);
2453                mutex_unlock(&easycap_dongle[kd].mutex_video);
2454                return -EFAULT;
2455        }
2456        kfree(pv4l2_streamparm);
2457        break;
2458}
2459/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2460case VIDIOC_S_PARM: {
2461        JOM(8, "VIDIOC_S_PARM unsupported\n");
2462        mutex_unlock(&easycap_dongle[kd].mutex_video);
2463        return -EINVAL;
2464}
2465/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2466case VIDIOC_G_AUDIO: {
2467        JOM(8, "VIDIOC_G_AUDIO unsupported\n");
2468        mutex_unlock(&easycap_dongle[kd].mutex_video);
2469        return -EINVAL;
2470}
2471/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2472case VIDIOC_S_AUDIO: {
2473        JOM(8, "VIDIOC_S_AUDIO unsupported\n");
2474        mutex_unlock(&easycap_dongle[kd].mutex_video);
2475        return -EINVAL;
2476}
2477/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2478case VIDIOC_S_TUNER: {
2479        JOM(8, "VIDIOC_S_TUNER unsupported\n");
2480        mutex_unlock(&easycap_dongle[kd].mutex_video);
2481        return -EINVAL;
2482}
2483/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2484case VIDIOC_G_FBUF:
2485case VIDIOC_S_FBUF:
2486case VIDIOC_OVERLAY: {
2487        JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
2488        mutex_unlock(&easycap_dongle[kd].mutex_video);
2489        return -EINVAL;
2490}
2491/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2492case VIDIOC_G_TUNER: {
2493        JOM(8, "VIDIOC_G_TUNER unsupported\n");
2494        mutex_unlock(&easycap_dongle[kd].mutex_video);
2495        return -EINVAL;
2496}
2497case VIDIOC_G_FREQUENCY:
2498case VIDIOC_S_FREQUENCY: {
2499        JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
2500        mutex_unlock(&easycap_dongle[kd].mutex_video);
2501        return -EINVAL;
2502}
2503/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2504default: {
2505        JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
2506        mutex_unlock(&easycap_dongle[kd].mutex_video);
2507        return -ENOIOCTLCMD;
2508}
2509}
2510mutex_unlock(&easycap_dongle[kd].mutex_video);
2511JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
2512return 0;
2513}
2514/*****************************************************************************/
2515/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2516#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
2517        (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
2518long
2519easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
2520        return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
2521}
2522#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
2523/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
2524/*---------------------------------------------------------------------------*/
2525int
2526easysnd_ioctl(struct inode *inode, struct file *file,
2527                                        unsigned int cmd, unsigned long arg)
2528{
2529struct easycap *peasycap;
2530struct usb_device *p;
2531int kd;
2532
2533if (NULL == file) {
2534        SAY("ERROR:  file is NULL\n");
2535        return -ERESTARTSYS;
2536}
2537peasycap = file->private_data;
2538if (NULL == peasycap) {
2539        SAY("ERROR:  peasycap is NULL.\n");
2540        return -EFAULT;
2541}
2542if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2543        SAY("ERROR: bad peasycap\n");
2544        return -EFAULT;
2545}
2546p = peasycap->pusb_device;
2547if (NULL == p) {
2548        SAM("ERROR: peasycap->pusb_device is NULL\n");
2549        return -EFAULT;
2550}
2551kd = isdongle(peasycap);
2552if (0 <= kd && DONGLE_MANY > kd) {
2553        if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
2554                SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
2555                return -ERESTARTSYS;
2556        }
2557        JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
2558/*---------------------------------------------------------------------------*/
2559/*
2560 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
2561 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
2562 *  IF NECESSARY, BAIL OUT.
2563*/
2564/*---------------------------------------------------------------------------*/
2565        if (kd != isdongle(peasycap))
2566                return -ERESTARTSYS;
2567        if (NULL == file) {
2568                SAY("ERROR:  file is NULL\n");
2569                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2570                return -ERESTARTSYS;
2571        }
2572        peasycap = file->private_data;
2573        if (NULL == peasycap) {
2574                SAY("ERROR:  peasycap is NULL\n");
2575                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2576                return -ERESTARTSYS;
2577        }
2578        if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2579                SAY("ERROR: bad peasycap\n");
2580                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2581                return -EFAULT;
2582        }
2583        p = peasycap->pusb_device;
2584        if (NULL == peasycap->pusb_device) {
2585                SAM("ERROR: peasycap->pusb_device is NULL\n");
2586                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2587                return -ERESTARTSYS;
2588        }
2589} else {
2590/*---------------------------------------------------------------------------*/
2591/*
2592 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
2593 *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
2594*/
2595/*---------------------------------------------------------------------------*/
2596        return -ERESTARTSYS;
2597}
2598/*---------------------------------------------------------------------------*/
2599switch (cmd) {
2600case SNDCTL_DSP_GETCAPS: {
2601        int caps;
2602        JOM(8, "SNDCTL_DSP_GETCAPS\n");
2603
2604#if defined(UPSAMPLE)
2605        if (true == peasycap->microphone)
2606                caps = 0x04400000;
2607        else
2608                caps = 0x04400000;
2609#else
2610        if (true == peasycap->microphone)
2611                caps = 0x02400000;
2612        else
2613                caps = 0x04400000;
2614#endif /*UPSAMPLE*/
2615
2616        if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
2617                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2618                return -EFAULT;
2619        }
2620        break;
2621}
2622case SNDCTL_DSP_GETFMTS: {
2623        int incoming;
2624        JOM(8, "SNDCTL_DSP_GETFMTS\n");
2625
2626#if defined(UPSAMPLE)
2627        if (true == peasycap->microphone)
2628                incoming = AFMT_S16_LE;
2629        else
2630                incoming = AFMT_S16_LE;
2631#else
2632        if (true == peasycap->microphone)
2633                incoming = AFMT_S16_LE;
2634        else
2635                incoming = AFMT_S16_LE;
2636#endif /*UPSAMPLE*/
2637
2638        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2639                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2640                return -EFAULT;
2641        }
2642        break;
2643}
2644case SNDCTL_DSP_SETFMT: {
2645        int incoming, outgoing;
2646        JOM(8, "SNDCTL_DSP_SETFMT\n");
2647        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2648                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2649                return -EFAULT;
2650        }
2651        JOM(8, "........... %i=incoming\n", incoming);
2652
2653#if defined(UPSAMPLE)
2654        if (true == peasycap->microphone)
2655                outgoing = AFMT_S16_LE;
2656        else
2657                outgoing = AFMT_S16_LE;
2658#else
2659        if (true == peasycap->microphone)
2660                outgoing = AFMT_S16_LE;
2661        else
2662                outgoing = AFMT_S16_LE;
2663#endif /*UPSAMPLE*/
2664
2665        if (incoming != outgoing) {
2666                JOM(8, "........... %i=outgoing\n", outgoing);
2667                JOM(8, "        cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
2668                JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
2669                if (0 != copy_to_user((void __user *)arg, &outgoing, \
2670                                                                sizeof(int))) {
2671                        mutex_unlock(&easycap_dongle[kd].mutex_audio);
2672                        return -EFAULT;
2673                }
2674                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2675                return -EINVAL ;
2676        }
2677        break;
2678}
2679case SNDCTL_DSP_STEREO: {
2680        int incoming;
2681        JOM(8, "SNDCTL_DSP_STEREO\n");
2682        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2683                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2684                return -EFAULT;
2685        }
2686        JOM(8, "........... %i=incoming\n", incoming);
2687
2688#if defined(UPSAMPLE)
2689        if (true == peasycap->microphone)
2690                incoming = 1;
2691        else
2692                incoming = 1;
2693#else
2694        if (true == peasycap->microphone)
2695                incoming = 0;
2696        else
2697                incoming = 1;
2698#endif /*UPSAMPLE*/
2699
2700        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2701                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2702                return -EFAULT;
2703        }
2704        break;
2705}
2706case SNDCTL_DSP_SPEED: {
2707        int incoming;
2708        JOM(8, "SNDCTL_DSP_SPEED\n");
2709        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2710                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2711                return -EFAULT;
2712        }
2713        JOM(8, "........... %i=incoming\n", incoming);
2714
2715#if defined(UPSAMPLE)
2716        if (true == peasycap->microphone)
2717                incoming = 32000;
2718        else
2719                incoming = 48000;
2720#else
2721        if (true == peasycap->microphone)
2722                incoming = 8000;
2723        else
2724                incoming = 48000;
2725#endif /*UPSAMPLE*/
2726
2727        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2728                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2729                return -EFAULT;
2730        }
2731        break;
2732}
2733case SNDCTL_DSP_GETTRIGGER: {
2734        int incoming;
2735        JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
2736        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2737                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2738                return -EFAULT;
2739        }
2740        JOM(8, "........... %i=incoming\n", incoming);
2741
2742        incoming = PCM_ENABLE_INPUT;
2743        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2744                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2745                return -EFAULT;
2746        }
2747        break;
2748}
2749case SNDCTL_DSP_SETTRIGGER: {
2750        int incoming;
2751        JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
2752        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2753                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2754                return -EFAULT;
2755        }
2756        JOM(8, "........... %i=incoming\n", incoming);
2757        JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \
2758                                "0x%x=PCM_ENABLE_OUTPUT\n", \
2759                                        PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
2760        ;
2761        ;
2762        ;
2763        ;
2764        break;
2765}
2766case SNDCTL_DSP_GETBLKSIZE: {
2767        int incoming;
2768        JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
2769        if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2770                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2771                return -EFAULT;
2772        }
2773        JOM(8, "........... %i=incoming\n", incoming);
2774        incoming = peasycap->audio_bytes_per_fragment;
2775        if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2776                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2777                return -EFAULT;
2778        }
2779        break;
2780}
2781case SNDCTL_DSP_GETISPACE: {
2782        struct audio_buf_info audio_buf_info;
2783
2784        JOM(8, "SNDCTL_DSP_GETISPACE\n");
2785
2786        audio_buf_info.bytes      = peasycap->audio_bytes_per_fragment;
2787        audio_buf_info.fragments  = 1;
2788        audio_buf_info.fragsize   = 0;
2789        audio_buf_info.fragstotal = 0;
2790
2791        if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
2792                                                                sizeof(int))) {
2793                mutex_unlock(&easycap_dongle[kd].mutex_audio);
2794                return -EFAULT;
2795        }
2796        break;
2797}
2798case 0x00005401:
2799case 0x00005402:
2800case 0x00005403:
2801case 0x00005404:
2802case 0x00005405:
2803case 0x00005406: {
2804        JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
2805        mutex_unlock(&easycap_dongle[kd].mutex_audio);
2806        return -ENOIOCTLCMD;
2807}
2808default: {
2809        JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
2810        mutex_unlock(&easycap_dongle[kd].mutex_audio);
2811        return -ENOIOCTLCMD;
2812}
2813}
2814mutex_unlock(&easycap_dongle[kd].mutex_audio);
2815return 0;
2816}
2817/*****************************************************************************/
2818
2819
2820