1/* Driver for Philips webcam 2 Functions that send various control messages to the webcam, including 3 video modes. 4 (C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl) 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19*/ 20 21/* 22 Changes 23 2001/08/03 Alvarado Added methods for changing white balance and 24 red/green gains 25 */ 26 27/* Control functions for the cam; brightness, contrast, video mode, etc. */ 28 29#ifdef __KERNEL__ 30#include <asm/uaccess.h> 31#endif 32#include <asm/errno.h> 33 34#include "pwc.h" 35#include "pwc-ioctl.h" 36#include "pwc-uncompress.h" 37 38/* Request types: video */ 39#define SET_LUM_CTL 0x01 40#define GET_LUM_CTL 0x02 41#define SET_CHROM_CTL 0x03 42#define GET_CHROM_CTL 0x04 43#define SET_STATUS_CTL 0x05 44#define GET_STATUS_CTL 0x06 45#define SET_EP_STREAM_CTL 0x07 46#define GET_EP_STREAM_CTL 0x08 47 48/* Selectors for the Luminance controls [GS]ET_LUM_CTL */ 49#define AGC_MODE_FORMATTER 0x2000 50#define PRESET_AGC_FORMATTER 0x2100 51#define SHUTTER_MODE_FORMATTER 0x2200 52#define PRESET_SHUTTER_FORMATTER 0x2300 53#define PRESET_CONTOUR_FORMATTER 0x2400 54#define AUTO_CONTOUR_FORMATTER 0x2500 55#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600 56#define CONTRAST_FORMATTER 0x2700 57#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800 58#define FLICKERLESS_MODE_FORMATTER 0x2900 59#define AE_CONTROL_SPEED 0x2A00 60#define BRIGHTNESS_FORMATTER 0x2B00 61#define GAMMA_FORMATTER 0x2C00 62 63/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */ 64#define WB_MODE_FORMATTER 0x1000 65#define AWB_CONTROL_SPEED_FORMATTER 0x1100 66#define AWB_CONTROL_DELAY_FORMATTER 0x1200 67#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300 68#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400 69#define COLOUR_MODE_FORMATTER 0x1500 70#define SATURATION_MODE_FORMATTER1 0x1600 71#define SATURATION_MODE_FORMATTER2 0x1700 72 73/* Selectors for the Status controls [GS]ET_STATUS_CTL */ 74#define SAVE_USER_DEFAULTS_FORMATTER 0x0200 75#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300 76#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400 77#define READ_AGC_FORMATTER 0x0500 78#define READ_SHUTTER_FORMATTER 0x0600 79#define READ_RED_GAIN_FORMATTER 0x0700 80#define READ_BLUE_GAIN_FORMATTER 0x0800 81#define SENSOR_TYPE_FORMATTER1 0x0C00 82#define READ_RAW_Y_MEAN_FORMATTER 0x3100 83#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 84#define MIRROR_IMAGE_FORMATTER 0x3300 85#define LED_FORMATTER 0x3400 86#define SENSOR_TYPE_FORMATTER2 0x3700 87 88/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ 89#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 90 91static char *size2name[PSZ_MAX] = 92{ 93 "subQCIF", 94 "QSIF", 95 "QCIF", 96 "SIF", 97 "CIF", 98 "VGA", 99}; 100 101/********/ 102 103/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 104 preferences, so you either get compressed or non-compressed streams. 105 106 An alternate value of 0 means this mode is not available at all. 107 */ 108 109struct Nala_table_entry { 110 char alternate; /* USB alternate setting */ 111 int compressed; /* Compressed yes/no */ 112 113 unsigned char mode[3]; /* precomputed mode table */ 114}; 115 116static struct Nala_table_entry Nala_table[PSZ_MAX][8] = 117{ 118#include "pwc_nala.h" 119}; 120 121/* This tables contains entries for the 675/680/690 (Timon) camera, with 122 4 different qualities (no compression, low, medium, high). 123 It lists the bandwidth requirements for said mode by its alternate interface 124 number. An alternate of 0 means that the mode is unavailable. 125 126 There are 6 * 4 * 4 entries: 127 6 different resolutions subqcif, qsif, qcif, sif, cif, vga 128 6 framerates: 5, 10, 15, 20, 25, 30 129 4 compression modi: none, low, medium, high 130 131 When an uncompressed mode is not available, the next available compressed mode 132 will be choosen (unless the decompressor is absent). Sometimes there are only 133 1 or 2 compressed modes available; in that case entries are duplicated. 134*/ 135struct Timon_table_entry 136{ 137 char alternate; /* USB alternate interface */ 138 unsigned short packetsize; /* Normal packet size */ 139 unsigned short bandlength; /* Bandlength when decompressing */ 140 unsigned char mode[13]; /* precomputed mode settings for cam */ 141}; 142 143static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = 144{ 145#include "pwc_timon.h" 146}; 147 148/* Entries for the Kiara (730/740/750) camera */ 149 150struct Kiara_table_entry 151{ 152 char alternate; /* USB alternate interface */ 153 unsigned short packetsize; /* Normal packet size */ 154 unsigned short bandlength; /* Bandlength when decompressing */ 155 unsigned char mode[12]; /* precomputed mode settings for cam */ 156}; 157 158static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] = 159{ 160#include "pwc_kiara.h" 161}; 162 163 164/****************************************************************************/ 165 166 167#define SendControlMsg(request, value, buflen) \ 168 usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \ 169 request, \ 170 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ 171 value, \ 172 pdev->vcinterface, \ 173 &buf, buflen, HZ / 2) 174 175#define RecvControlMsg(request, value, buflen) \ 176 usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \ 177 request, \ 178 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \ 179 value, \ 180 pdev->vcinterface, \ 181 &buf, buflen, HZ / 2) 182 183 184#if PWC_DEBUG 185void pwc_hexdump(void *p, int len) 186{ 187 int i; 188 unsigned char *s; 189 char buf[100], *d; 190 191 s = (unsigned char *)p; 192 d = buf; 193 *d = '\0'; 194 Debug("Doing hexdump @ %p, %d bytes.\n", p, len); 195 for (i = 0; i < len; i++) { 196 d += sprintf(d, "%02X ", *s++); 197 if ((i & 0xF) == 0xF) { 198 Debug("%s\n", buf); 199 d = buf; 200 *d = '\0'; 201 } 202 } 203 if ((i & 0xF) != 0) 204 Debug("%s\n", buf); 205} 206#endif 207 208static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen) 209{ 210 return usb_control_msg(udev, 211 usb_sndctrlpipe(udev, 0), 212 SET_EP_STREAM_CTL, 213 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 214 VIDEO_OUTPUT_CONTROL_FORMATTER, 215 index, 216 buf, buflen, HZ); 217} 218 219 220 221static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) 222{ 223 unsigned char buf[3]; 224 int ret, fps; 225 struct Nala_table_entry *pEntry; 226 int frames2frames[31] = 227 { /* closest match of framerate */ 228 0, 0, 0, 0, 4, /* 0-4 */ 229 5, 5, 7, 7, 10, /* 5-9 */ 230 10, 10, 12, 12, 15, /* 10-14 */ 231 15, 15, 15, 20, 20, /* 15-19 */ 232 20, 20, 20, 24, 24, /* 20-24 */ 233 24, 24, 24, 24, 24, /* 25-29 */ 234 24 /* 30 */ 235 }; 236 int frames2table[31] = 237 { 0, 0, 0, 0, 0, /* 0-4 */ 238 1, 1, 1, 2, 2, /* 5-9 */ 239 3, 3, 4, 4, 4, /* 10-14 */ 240 5, 5, 5, 5, 5, /* 15-19 */ 241 6, 6, 6, 6, 7, /* 20-24 */ 242 7, 7, 7, 7, 7, /* 25-29 */ 243 7 /* 30 */ 244 }; 245 246 if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25) 247 return -EINVAL; 248 frames = frames2frames[frames]; 249 fps = frames2table[frames]; 250 pEntry = &Nala_table[size][fps]; 251 if (pEntry->alternate == 0) 252 return -EINVAL; 253 254 if (pEntry->compressed && pdev->decompressor == NULL) 255 return -ENOENT; /* Not supported. */ 256 257 memcpy(buf, pEntry->mode, 3); 258 ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); 259 if (ret < 0) { 260 Debug("Failed to send video command... %d\n", ret); 261 return ret; 262 } 263 if (pEntry->compressed && pdev->decompressor != NULL) 264 pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); 265 266 /* Set various parameters */ 267 pdev->vframes = frames; 268 pdev->vsize = size; 269 pdev->valternate = pEntry->alternate; 270 pdev->image = pwc_image_sizes[size]; 271 pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2; 272 if (pEntry->compressed) { 273 if (pdev->release < 5) { /* 4 fold compression */ 274 pdev->vbandlength = 528; 275 pdev->frame_size /= 4; 276 } 277 else { 278 pdev->vbandlength = 704; 279 pdev->frame_size /= 3; 280 } 281 } 282 else 283 pdev->vbandlength = 0; 284 return 0; 285} 286 287 288static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) 289{ 290 unsigned char buf[13]; 291 struct Timon_table_entry *pChoose; 292 int ret, fps; 293 294 if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) 295 return -EINVAL; 296 if (size == PSZ_VGA && frames > 15) 297 return -EINVAL; 298 fps = (frames / 5) - 1; 299 300 /* Find a supported framerate with progressively higher compression ratios 301 if the preferred ratio is not available. 302 */ 303 pChoose = NULL; 304 if (pdev->decompressor == NULL) { 305#if PWC_DEBUG 306 Debug("Trying to find uncompressed mode.\n"); 307#endif 308 pChoose = &Timon_table[size][fps][0]; 309 } 310 else { 311 while (compression <= 3) { 312 pChoose = &Timon_table[size][fps][compression]; 313 if (pChoose->alternate != 0) 314 break; 315 compression++; 316 } 317 } 318 if (pChoose == NULL || pChoose->alternate == 0) 319 return -ENOENT; /* Not supported. */ 320 321 memcpy(buf, pChoose->mode, 13); 322 if (snapshot) 323 buf[0] |= 0x80; 324 ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13); 325 if (ret < 0) 326 return ret; 327 328 if (pChoose->bandlength > 0) 329 pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); 330 331 /* Set various parameters */ 332 pdev->vframes = frames; 333 pdev->vsize = size; 334 pdev->vsnapshot = snapshot; 335 pdev->valternate = pChoose->alternate; 336 pdev->image = pwc_image_sizes[size]; 337 pdev->vbandlength = pChoose->bandlength; 338 if (pChoose->bandlength > 0) 339 pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; 340 else 341 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; 342 return 0; 343} 344 345 346static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) 347{ 348 struct Kiara_table_entry *pChoose; 349 int fps, ret; 350 unsigned char buf[12]; 351 352 if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) 353 return -EINVAL; 354 if (size == PSZ_VGA && frames > 15) 355 return -EINVAL; 356 fps = (frames / 5) - 1; 357 358 /* Find a supported framerate with progressively higher compression ratios 359 if the preferred ratio is not available. 360 */ 361 pChoose = NULL; 362 if (pdev->decompressor == NULL) { 363#if PWC_DEBUG 364 Debug("Trying to find uncompressed mode.\n"); 365#endif 366 pChoose = &Kiara_table[size][fps][0]; 367 } 368 else { 369 while (compression <= 3) { 370 pChoose = &Kiara_table[size][fps][compression]; 371 if (pChoose->alternate != 0) 372 break; 373 compression++; 374 } 375 } 376 if (pChoose == NULL || pChoose->alternate == 0) 377 return -ENOENT; /* Not supported. */ 378 379 /* usb_control_msg won't take staticly allocated arrays as argument?? */ 380 memcpy(buf, pChoose->mode, 12); 381 if (snapshot) 382 buf[0] |= 0x80; 383 384 /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ 385 ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12); 386 if (ret < 0) 387 return ret; 388 389 if (pChoose->bandlength > 0) 390 pdev->decompressor->init(pdev->release, buf, pdev->decompress_data); 391 392 /* All set and go */ 393 pdev->vframes = frames; 394 pdev->vsize = size; 395 pdev->vsnapshot = snapshot; 396 pdev->valternate = pChoose->alternate; 397 pdev->image = pwc_image_sizes[size]; 398 pdev->vbandlength = pChoose->bandlength; 399 if (pChoose->bandlength > 0) 400 pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; 401 else 402 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; 403 pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size); 404 return 0; 405} 406 407 408/** 409 @pdev: device structure 410 @width: viewport width 411 @height: viewport height 412 @frame: framerate, in fps 413 @compression: preferred compression ratio 414 @snapshot: snapshot mode or streaming 415 */ 416int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot) 417{ 418 int ret, size; 419 420 size = pwc_decode_size(pdev, width, height); 421 if (size < 0) { 422 Debug("Could not find suitable size.\n"); 423 return -ERANGE; 424 } 425 ret = -EINVAL; 426 switch(pdev->type) { 427 case 645: 428 case 646: 429 ret = set_video_mode_Nala(pdev, size, frames); 430 break; 431 432 case 675: 433 case 680: 434 case 690: 435 ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); 436 break; 437 438 case 730: 439 case 740: 440 case 750: 441 ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); 442 break; 443 } 444 if (ret < 0) { 445 if (ret == -ENOENT) 446 Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames); 447 else { 448 Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); 449 } 450 return ret; 451 } 452 pdev->view.x = width; 453 pdev->view.y = height; 454 pwc_set_image_buffer_size(pdev); 455 Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); 456 return 0; 457} 458 459 460void pwc_set_image_buffer_size(struct pwc_device *pdev) 461{ 462 int factor, i, filler = 0; 463 464 /* for PALETTE_YUV420P */ 465 factor = 6; 466 filler = 128; 467 468 /* Set sizes in bytes */ 469 pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; 470 pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; 471 472 /* Align offset, or you'll get some very weird results in 473 YUV420 mode... x must be multiple of 4 (to get the Y's in 474 place), and y even (or you'll mixup U & V). This is less of a 475 problem for YUV420P. 476 */ 477 pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; 478 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; 479 480 /* Fill buffers with gray or black */ 481 for (i = 0; i < MAX_IMAGES; i++) { 482 if (pdev->image_ptr[i] != NULL) 483 memset(pdev->image_ptr[i], filler, pdev->view.size); 484 } 485} 486 487 488 489/* BRIGHTNESS */ 490 491int pwc_get_brightness(struct pwc_device *pdev) 492{ 493 char buf; 494 int ret; 495 496 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 497 GET_LUM_CTL, 498 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 499 BRIGHTNESS_FORMATTER, 500 pdev->vcinterface, 501 &buf, 1, HZ / 2); 502 if (ret < 0) 503 return ret; 504 return buf << 9; 505} 506 507int pwc_set_brightness(struct pwc_device *pdev, int value) 508{ 509 char buf; 510 511 if (value < 0) 512 value = 0; 513 if (value > 0xffff) 514 value = 0xffff; 515 buf = (value >> 9) & 0x7f; 516 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 517 SET_LUM_CTL, 518 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 519 BRIGHTNESS_FORMATTER, 520 pdev->vcinterface, 521 &buf, 1, HZ / 2); 522} 523 524/* CONTRAST */ 525 526int pwc_get_contrast(struct pwc_device *pdev) 527{ 528 char buf; 529 int ret; 530 531 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 532 GET_LUM_CTL, 533 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 534 CONTRAST_FORMATTER, 535 pdev->vcinterface, 536 &buf, 1, HZ / 2); 537 if (ret < 0) 538 return ret; 539 return buf << 10; 540} 541 542int pwc_set_contrast(struct pwc_device *pdev, int value) 543{ 544 char buf; 545 546 if (value < 0) 547 value = 0; 548 if (value > 0xffff) 549 value = 0xffff; 550 buf = (value >> 10) & 0x3f; 551 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 552 SET_LUM_CTL, 553 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 554 CONTRAST_FORMATTER, 555 pdev->vcinterface, 556 &buf, 1, HZ / 2); 557} 558 559/* GAMMA */ 560 561int pwc_get_gamma(struct pwc_device *pdev) 562{ 563 char buf; 564 int ret; 565 566 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 567 GET_LUM_CTL, 568 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 569 GAMMA_FORMATTER, 570 pdev->vcinterface, 571 &buf, 1, HZ / 2); 572 if (ret < 0) 573 return ret; 574 return buf << 11; 575} 576 577int pwc_set_gamma(struct pwc_device *pdev, int value) 578{ 579 char buf; 580 581 if (value < 0) 582 value = 0; 583 if (value > 0xffff) 584 value = 0xffff; 585 buf = (value >> 11) & 0x1f; 586 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 587 SET_LUM_CTL, 588 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 589 GAMMA_FORMATTER, 590 pdev->vcinterface, 591 &buf, 1, HZ / 2); 592} 593 594 595/* SATURATION */ 596 597int pwc_get_saturation(struct pwc_device *pdev) 598{ 599 char buf; 600 int ret; 601 602 if (pdev->type < 675) 603 return -1; 604 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 605 GET_CHROM_CTL, 606 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 607 pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 608 pdev->vcinterface, 609 &buf, 1, HZ / 2); 610 if (ret < 0) 611 return ret; 612 return 32768 + buf * 327; 613} 614 615int pwc_set_saturation(struct pwc_device *pdev, int value) 616{ 617 char buf; 618 619 if (pdev->type < 675) 620 return -EINVAL; 621 if (value < 0) 622 value = 0; 623 if (value > 0xffff) 624 value = 0xffff; 625 /* saturation ranges from -100 to +100 */ 626 buf = (value - 32768) / 327; 627 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 628 SET_CHROM_CTL, 629 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 630 pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 631 pdev->vcinterface, 632 &buf, 1, HZ / 2); 633} 634 635/* AGC */ 636 637static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) 638{ 639 char buf; 640 int ret; 641 642 if (mode) 643 buf = 0x0; /* auto */ 644 else 645 buf = 0xff; /* fixed */ 646 647 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 648 SET_LUM_CTL, 649 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 650 AGC_MODE_FORMATTER, 651 pdev->vcinterface, 652 &buf, 1, HZ / 2); 653 654 if (!mode && ret >= 0) { 655 if (value < 0) 656 value = 0; 657 if (value > 0xffff) 658 value = 0xffff; 659 buf = (value >> 10) & 0x3F; 660 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 661 SET_LUM_CTL, 662 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 663 PRESET_AGC_FORMATTER, 664 pdev->vcinterface, 665 &buf, 1, HZ / 2); 666 } 667 if (ret < 0) 668 return ret; 669 return 0; 670} 671 672static inline int pwc_get_agc(struct pwc_device *pdev, int *value) 673{ 674 unsigned char buf; 675 int ret; 676 677 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 678 GET_LUM_CTL, 679 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 680 AGC_MODE_FORMATTER, 681 pdev->vcinterface, 682 &buf, 1, HZ / 2); 683 if (ret < 0) 684 return ret; 685 686 if (buf != 0) { /* fixed */ 687 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 688 GET_LUM_CTL, 689 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 690 PRESET_AGC_FORMATTER, 691 pdev->vcinterface, 692 &buf, 1, HZ / 2); 693 if (ret < 0) 694 return ret; 695 if (buf > 0x3F) 696 buf = 0x3F; 697 *value = (buf << 10); 698 } 699 else { /* auto */ 700 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 701 GET_STATUS_CTL, 702 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 703 READ_AGC_FORMATTER, 704 pdev->vcinterface, 705 &buf, 1, HZ / 2); 706 if (ret < 0) 707 return ret; 708 /* Gah... this value ranges from 0x00 ... 0x9F */ 709 if (buf > 0x9F) 710 buf = 0x9F; 711 *value = -(48 + buf * 409); 712 } 713 714 return 0; 715} 716 717static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) 718{ 719 char buf[2]; 720 int speed, ret; 721 722 723 if (mode) 724 buf[0] = 0x0; /* auto */ 725 else 726 buf[0] = 0xff; /* fixed */ 727 728 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 729 SET_LUM_CTL, 730 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 731 SHUTTER_MODE_FORMATTER, 732 pdev->vcinterface, 733 buf, 1, HZ / 2); 734 735 if (!mode && ret >= 0) { 736 if (value < 0) 737 value = 0; 738 if (value > 0xffff) 739 value = 0xffff; 740 switch(pdev->type) { 741 case 675: 742 case 680: 743 case 690: 744 /* speed ranges from 0x0 to 0x290 (656) */ 745 speed = (value / 100); 746 buf[1] = speed >> 8; 747 buf[0] = speed & 0xff; 748 break; 749 case 730: 750 case 740: 751 case 750: 752 /* speed seems to range from 0x0 to 0xff */ 753 buf[1] = 0; 754 buf[0] = value >> 8; 755 break; 756 } 757 758 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 759 SET_LUM_CTL, 760 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 761 PRESET_SHUTTER_FORMATTER, 762 pdev->vcinterface, 763 &buf, 2, HZ / 2); 764 } 765 return ret; 766} 767 768 769/* POWER */ 770 771int pwc_camera_power(struct pwc_device *pdev, int power) 772{ 773 char buf; 774 775 if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) 776 return 0; /* Not supported by Nala or Timon < release 6 */ 777 778 if (power) 779 buf = 0x00; /* active */ 780 else 781 buf = 0xFF; /* power save */ 782 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 783 SET_STATUS_CTL, 784 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 785 SET_POWER_SAVE_MODE_FORMATTER, 786 pdev->vcinterface, 787 &buf, 1, HZ / 2); 788} 789 790 791 792/* private calls */ 793 794static inline int pwc_restore_user(struct pwc_device *pdev) 795{ 796 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 797 SET_STATUS_CTL, 798 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 799 RESTORE_USER_DEFAULTS_FORMATTER, 800 pdev->vcinterface, 801 NULL, 0, HZ / 2); 802} 803 804static inline int pwc_save_user(struct pwc_device *pdev) 805{ 806 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 807 SET_STATUS_CTL, 808 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 809 SAVE_USER_DEFAULTS_FORMATTER, 810 pdev->vcinterface, 811 NULL, 0, HZ / 2); 812} 813 814static inline int pwc_restore_factory(struct pwc_device *pdev) 815{ 816 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 817 SET_STATUS_CTL, 818 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 819 RESTORE_FACTORY_DEFAULTS_FORMATTER, 820 pdev->vcinterface, 821 NULL, 0, HZ / 2); 822} 823 824 /* ************************************************* */ 825 /* Patch by Alvarado: (not in the original version */ 826 827 /* 828 * the camera recognizes modes from 0 to 4: 829 * 830 * 00: indoor (incandescant lighting) 831 * 01: outdoor (sunlight) 832 * 02: fluorescent lighting 833 * 03: manual 834 * 04: auto 835 */ 836static inline int pwc_set_awb(struct pwc_device *pdev, int mode) 837{ 838 char buf; 839 int ret; 840 841 if (mode < 0) 842 mode = 0; 843 844 if (mode > 4) 845 mode = 4; 846 847 buf = mode & 0x07; /* just the lowest three bits */ 848 849 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 850 SET_CHROM_CTL, 851 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 852 WB_MODE_FORMATTER, 853 pdev->vcinterface, 854 &buf, 1, HZ / 2); 855 856 if (ret < 0) 857 return ret; 858 return 0; 859} 860 861static inline int pwc_get_awb(struct pwc_device *pdev) 862{ 863 unsigned char buf; 864 int ret; 865 866 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 867 GET_CHROM_CTL, 868 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 869 WB_MODE_FORMATTER, 870 pdev->vcinterface, 871 &buf, 1, HZ / 2); 872 873 if (ret < 0) 874 return ret; 875 return buf; 876} 877 878static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) 879{ 880 unsigned char buf; 881 882 if (value < 0) 883 value = 0; 884 if (value > 0xffff) 885 value = 0xffff; 886 887 /* only the msb are considered */ 888 buf = value >> 8; 889 890 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 891 SET_CHROM_CTL, 892 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 893 PRESET_MANUAL_RED_GAIN_FORMATTER, 894 pdev->vcinterface, 895 &buf, 1, HZ / 2); 896} 897 898static inline int pwc_get_red_gain(struct pwc_device *pdev) 899{ 900 unsigned char buf; 901 int ret; 902 903 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 904 GET_CHROM_CTL, 905 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 906 PRESET_MANUAL_RED_GAIN_FORMATTER, 907 pdev->vcinterface, 908 &buf, 1, HZ / 2); 909 910 if (ret < 0) 911 return ret; 912 913 return (buf << 8); 914} 915 916 917static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) 918{ 919 unsigned char buf; 920 921 if (value < 0) 922 value = 0; 923 if (value > 0xffff) 924 value = 0xffff; 925 926 /* linear mapping of 0..0xffff to -0x80..0x7f */ 927 buf = (value >> 8); 928 929 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 930 SET_CHROM_CTL, 931 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 932 PRESET_MANUAL_BLUE_GAIN_FORMATTER, 933 pdev->vcinterface, 934 &buf, 1, HZ / 2); 935} 936 937static inline int pwc_get_blue_gain(struct pwc_device *pdev) 938{ 939 unsigned char buf; 940 int ret; 941 942 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 943 GET_CHROM_CTL, 944 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 945 PRESET_MANUAL_BLUE_GAIN_FORMATTER, 946 pdev->vcinterface, 947 &buf, 1, HZ / 2); 948 949 if (ret < 0) 950 return ret; 951 952 return (buf << 8); 953} 954 955 956/* The following two functions are different, since they only read the 957 internal red/blue gains, which may be different from the manual 958 gains set or read above. 959 */ 960static inline int pwc_read_red_gain(struct pwc_device *pdev) 961{ 962 unsigned char buf; 963 int ret; 964 965 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 966 GET_STATUS_CTL, 967 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 968 READ_RED_GAIN_FORMATTER, 969 pdev->vcinterface, 970 &buf, 1, HZ / 2); 971 972 if (ret < 0) 973 return ret; 974 975 return (buf << 8); 976} 977 978static inline int pwc_read_blue_gain(struct pwc_device *pdev) 979{ 980 unsigned char buf; 981 int ret; 982 983 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 984 GET_STATUS_CTL, 985 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 986 READ_BLUE_GAIN_FORMATTER, 987 pdev->vcinterface, 988 &buf, 1, HZ / 2); 989 990 if (ret < 0) 991 return ret; 992 993 return (buf << 8); 994} 995 996 997static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) 998{ 999 unsigned char buf; 1000 1001 /* useful range is 0x01..0x20 */ 1002 buf = speed / 0x7f0; 1003 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 1004 SET_CHROM_CTL, 1005 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1006 AWB_CONTROL_SPEED_FORMATTER, 1007 pdev->vcinterface, 1008 &buf, 1, HZ / 2); 1009} 1010 1011static inline int pwc_get_wb_speed(struct pwc_device *pdev) 1012{ 1013 unsigned char buf; 1014 int ret; 1015 1016 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1017 GET_CHROM_CTL, 1018 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1019 AWB_CONTROL_SPEED_FORMATTER, 1020 pdev->vcinterface, 1021 &buf, 1, HZ / 2); 1022 if (ret < 0) 1023 return ret; 1024 return (buf * 0x7f0); 1025} 1026 1027 1028static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) 1029{ 1030 unsigned char buf; 1031 1032 /* useful range is 0x01..0x3F */ 1033 buf = (delay >> 10); 1034 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 1035 SET_CHROM_CTL, 1036 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1037 AWB_CONTROL_DELAY_FORMATTER, 1038 pdev->vcinterface, 1039 &buf, 1, HZ / 2); 1040} 1041 1042static inline int pwc_get_wb_delay(struct pwc_device *pdev) 1043{ 1044 unsigned char buf; 1045 int ret; 1046 1047 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1048 GET_CHROM_CTL, 1049 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1050 AWB_CONTROL_DELAY_FORMATTER, 1051 pdev->vcinterface, 1052 &buf, 1, HZ / 2); 1053 if (ret < 0) 1054 return ret; 1055 return (buf << 10); 1056} 1057 1058 1059int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) 1060{ 1061 unsigned char buf[2]; 1062 1063 if (pdev->type < 730) 1064 return 0; 1065 on_value /= 100; 1066 off_value /= 100; 1067 if (on_value < 0) 1068 on_value = 0; 1069 if (on_value > 0xff) 1070 on_value = 0xff; 1071 if (off_value < 0) 1072 off_value = 0; 1073 if (off_value > 0xff) 1074 off_value = 0xff; 1075 1076 buf[0] = on_value; 1077 buf[1] = off_value; 1078 1079 return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); 1080} 1081 1082int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) 1083{ 1084 unsigned char buf[2]; 1085 int ret; 1086 1087 if (pdev->type < 730) { 1088 *on_value = -1; 1089 *off_value = -1; 1090 return 0; 1091 } 1092 1093 ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2); 1094 if (ret < 0) 1095 return ret; 1096 *on_value = buf[0] * 100; 1097 *off_value = buf[1] * 100; 1098 return 0; 1099} 1100 1101static inline int pwc_set_contour(struct pwc_device *pdev, int contour) 1102{ 1103 unsigned char buf; 1104 int ret; 1105 1106 if (contour < 0) 1107 buf = 0xff; /* auto contour on */ 1108 else 1109 buf = 0x0; /* auto contour off */ 1110 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 1111 SET_LUM_CTL, 1112 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1113 AUTO_CONTOUR_FORMATTER, 1114 pdev->vcinterface, 1115 &buf, 1, HZ / 2); 1116 if (ret < 0) 1117 return ret; 1118 1119 if (contour < 0) 1120 return 0; 1121 if (contour > 0xffff) 1122 contour = 0xffff; 1123 1124 buf = (contour >> 10); /* contour preset is [0..3f] */ 1125 ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 1126 SET_LUM_CTL, 1127 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1128 PRESET_CONTOUR_FORMATTER, 1129 pdev->vcinterface, 1130 &buf, 1, HZ / 2); 1131 if (ret < 0) 1132 return ret; 1133 return 0; 1134} 1135 1136static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) 1137{ 1138 unsigned char buf; 1139 int ret; 1140 1141 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1142 GET_LUM_CTL, 1143 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1144 AUTO_CONTOUR_FORMATTER, 1145 pdev->vcinterface, 1146 &buf, 1, HZ / 2); 1147 if (ret < 0) 1148 return ret; 1149 1150 if (buf == 0) { 1151 /* auto mode off, query current preset value */ 1152 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1153 GET_LUM_CTL, 1154 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1155 PRESET_CONTOUR_FORMATTER, 1156 pdev->vcinterface, 1157 &buf, 1, HZ / 2); 1158 if (ret < 0) 1159 return ret; 1160 *contour = (buf << 10); 1161 } 1162 else 1163 *contour = -1; 1164 return 0; 1165} 1166 1167 1168static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) 1169{ 1170 unsigned char buf; 1171 1172 if (backlight) 1173 buf = 0xff; 1174 else 1175 buf = 0x0; 1176 return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), 1177 SET_LUM_CTL, 1178 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1179 BACK_LIGHT_COMPENSATION_FORMATTER, 1180 pdev->vcinterface, 1181 &buf, 1, HZ / 2); 1182} 1183 1184static inline int pwc_get_backlight(struct pwc_device *pdev) 1185{ 1186 int ret; 1187 unsigned char buf; 1188 1189 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1190 GET_LUM_CTL, 1191 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1192 BACK_LIGHT_COMPENSATION_FORMATTER, 1193 pdev->vcinterface, 1194 &buf, 1, HZ / 2); 1195 if (ret < 0) 1196 return ret; 1197 return buf; 1198} 1199 1200 1201static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) 1202{ 1203 unsigned char buf; 1204 1205 if (flicker) 1206 buf = 0xff; 1207 else 1208 buf = 0x0; 1209 return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); 1210} 1211 1212static inline int pwc_get_flicker(struct pwc_device *pdev) 1213{ 1214 int ret; 1215 unsigned char buf; 1216 1217 ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); 1218 if (ret < 0) 1219 return ret; 1220 return buf; 1221} 1222 1223 1224static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise) 1225{ 1226 unsigned char buf; 1227 1228 if (noise < 0) 1229 noise = 0; 1230 if (noise > 3) 1231 noise = 3; 1232 buf = noise; 1233 return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); 1234} 1235 1236static inline int pwc_get_dynamic_noise(struct pwc_device *pdev) 1237{ 1238 int ret; 1239 unsigned char buf; 1240 1241 ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); 1242 if (ret < 0) 1243 return ret; 1244 return buf; 1245} 1246 1247 1248int pwc_get_cmos_sensor(struct pwc_device *pdev) 1249{ 1250 unsigned char buf; 1251 int ret = -1, request; 1252 1253 if (pdev->type < 675) 1254 request = SENSOR_TYPE_FORMATTER1; 1255 else if (pdev->type < 730) 1256 return -1; /* The Vesta series doesn't have this call */ 1257 else 1258 request = SENSOR_TYPE_FORMATTER2; 1259 1260 ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), 1261 GET_STATUS_CTL, 1262 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1263 request, 1264 pdev->vcinterface, 1265 &buf, 1, HZ / 2); 1266 if (ret < 0) 1267 return ret; 1268 if (pdev->type < 675) 1269 return buf | 0x100; 1270 else 1271 return buf; 1272} 1273 1274 1275 /* End of Add-Ons */ 1276 /* ************************************************* */ 1277 1278int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) 1279{ 1280 int ret = 0; 1281 1282 switch(cmd) { 1283 case VIDIOCPWCRUSER: 1284 { 1285 if (pwc_restore_user(pdev)) 1286 ret = -EINVAL; 1287 break; 1288 } 1289 1290 case VIDIOCPWCSUSER: 1291 { 1292 if (pwc_save_user(pdev)) 1293 ret = -EINVAL; 1294 break; 1295 } 1296 1297 case VIDIOCPWCFACTORY: 1298 { 1299 if (pwc_restore_factory(pdev)) 1300 ret = -EINVAL; 1301 break; 1302 } 1303 1304 case VIDIOCPWCSCQUAL: 1305 { 1306 int qual; 1307 1308 if (copy_from_user(&qual, arg, sizeof(int))) 1309 ret = -EFAULT; 1310 else { 1311 if (qual < 0 || qual > 3) 1312 ret = -EINVAL; 1313 else 1314 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot); 1315 if (ret >= 0) 1316 pdev->vcompression = qual; 1317 } 1318 break; 1319 } 1320 1321 case VIDIOCPWCGCQUAL: 1322 { 1323 if (copy_to_user(arg, &pdev->vcompression, sizeof(int))) 1324 ret = -EFAULT; 1325 break; 1326 } 1327 1328 case VIDIOCPWCPROBE: 1329 { 1330 struct pwc_probe probe; 1331 1332 strcpy(probe.name, pdev->vdev.name); 1333 probe.type = pdev->type; 1334 if (copy_to_user(arg, &probe, sizeof(probe))) 1335 ret = -EFAULT; 1336 break; 1337 } 1338 1339 case VIDIOCPWCSAGC: 1340 { 1341 int agc; 1342 1343 if (copy_from_user(&agc, arg, sizeof(agc))) 1344 ret = -EFAULT; 1345 else { 1346 if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc)) 1347 ret = -EINVAL; 1348 } 1349 break; 1350 } 1351 1352 case VIDIOCPWCGAGC: 1353 { 1354 int agc; 1355 1356 if (pwc_get_agc(pdev, &agc)) 1357 ret = -EINVAL; 1358 else 1359 if (copy_to_user(arg, &agc, sizeof(agc))) 1360 ret = -EFAULT; 1361 break; 1362 } 1363 1364 case VIDIOCPWCSSHUTTER: 1365 { 1366 int shutter_speed; 1367 1368 if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed))) 1369 ret = -EFAULT; 1370 else 1371 ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed); 1372 break; 1373 } 1374 1375 case VIDIOCPWCSAWB: 1376 { 1377 struct pwc_whitebalance wb; 1378 1379 if (copy_from_user(&wb, arg, sizeof(wb))) 1380 ret = -EFAULT; 1381 else { 1382 ret = pwc_set_awb(pdev, wb.mode); 1383 if (ret >= 0 && wb.mode == PWC_WB_MANUAL) { 1384 pwc_set_red_gain(pdev, wb.manual_red); 1385 pwc_set_blue_gain(pdev, wb.manual_blue); 1386 } 1387 } 1388 break; 1389 } 1390 1391 case VIDIOCPWCGAWB: 1392 { 1393 struct pwc_whitebalance wb; 1394 1395 memset(&wb, 0, sizeof(wb)); 1396 wb.mode = pwc_get_awb(pdev); 1397 if (wb.mode < 0) 1398 ret = -EINVAL; 1399 else { 1400 if (wb.mode == PWC_WB_MANUAL) { 1401 wb.manual_red = pwc_get_red_gain(pdev); 1402 wb.manual_blue = pwc_get_blue_gain(pdev); 1403 } 1404 if (wb.mode == PWC_WB_AUTO) { 1405 wb.read_red = pwc_read_red_gain(pdev); 1406 wb.read_blue = pwc_read_blue_gain(pdev); 1407 } 1408 if (copy_to_user(arg, &wb, sizeof(wb))) 1409 ret= -EFAULT; 1410 } 1411 break; 1412 } 1413 1414 case VIDIOCPWCSAWBSPEED: 1415 { 1416 struct pwc_wb_speed wbs; 1417 1418 if (copy_from_user(&wbs, arg, sizeof(wbs))) 1419 ret = -EFAULT; 1420 else { 1421 if (wbs.control_speed > 0) { 1422 ret = pwc_set_wb_speed(pdev, wbs.control_speed); 1423 } 1424 if (wbs.control_delay > 0) { 1425 ret = pwc_set_wb_delay(pdev, wbs.control_delay); 1426 } 1427 } 1428 break; 1429 } 1430 1431 case VIDIOCPWCGAWBSPEED: 1432 { 1433 struct pwc_wb_speed wbs; 1434 1435 ret = pwc_get_wb_speed(pdev); 1436 if (ret < 0) 1437 break; 1438 wbs.control_speed = ret; 1439 ret = pwc_get_wb_delay(pdev); 1440 if (ret < 0) 1441 break; 1442 wbs.control_delay = ret; 1443 if (copy_to_user(arg, &wbs, sizeof(wbs))) 1444 ret = -EFAULT; 1445 break; 1446 } 1447 1448 case VIDIOCPWCSLED: 1449 { 1450 struct pwc_leds leds; 1451 1452 if (copy_from_user(&leds, arg, sizeof(leds))) 1453 ret = -EFAULT; 1454 else 1455 ret = pwc_set_leds(pdev, leds.led_on, leds.led_off); 1456 break; 1457 } 1458 1459 1460 case VIDIOCPWCGLED: 1461 { 1462 struct pwc_leds leds; 1463 1464 ret = pwc_get_leds(pdev, &leds.led_on, &leds.led_off); 1465 if (ret < 0) 1466 break; 1467 if (copy_to_user(arg, &leds, sizeof(leds))) 1468 ret = -EFAULT; 1469 break; 1470 } 1471 1472 case VIDIOCPWCSCONTOUR: 1473 { 1474 int contour; 1475 1476 if (copy_from_user(&contour, arg, sizeof(contour))) 1477 ret = -EFAULT; 1478 else 1479 ret = pwc_set_contour(pdev, contour); 1480 break; 1481 } 1482 1483 case VIDIOCPWCGCONTOUR: 1484 { 1485 int contour; 1486 1487 ret = pwc_get_contour(pdev, &contour); 1488 if (ret < 0) 1489 break; 1490 1491 if (copy_to_user(arg, &contour, sizeof(contour))) 1492 ret = -EFAULT; 1493 break; 1494 } 1495 1496 case VIDIOCPWCSBACKLIGHT: 1497 { 1498 int backlight; 1499 1500 if (copy_from_user(&backlight, arg, sizeof(backlight))) 1501 ret = -EFAULT; 1502 else 1503 ret = pwc_set_backlight(pdev, backlight); 1504 break; 1505 } 1506 1507 case VIDIOCPWCGBACKLIGHT: 1508 { 1509 ret = pwc_get_backlight(pdev); 1510 if (ret < 0) 1511 break; 1512 if (copy_to_user(arg, &ret, sizeof(ret))) 1513 ret = -EFAULT; 1514 break; 1515 } 1516 1517 case VIDIOCPWCSFLICKER: 1518 { 1519 int flicker; 1520 1521 if (copy_from_user(&flicker, arg, sizeof(flicker))) 1522 ret = -EFAULT; 1523 else 1524 ret = pwc_set_flicker(pdev, flicker); 1525 break; 1526 } 1527 1528 case VIDIOCPWCGFLICKER: 1529 { 1530 ret = pwc_get_flicker(pdev); 1531 if (ret < 0) 1532 break; 1533 if (copy_to_user(arg, &ret, sizeof(ret))) 1534 ret = -EFAULT; 1535 break; 1536 } 1537 1538 case VIDIOCPWCSDYNNOISE: 1539 { 1540 int dynnoise; 1541 1542 if (copy_from_user(&dynnoise, arg, sizeof(dynnoise))) 1543 ret = -EFAULT; 1544 else 1545 ret = pwc_set_dynamic_noise(pdev, dynnoise); 1546 break; 1547 } 1548 1549 case VIDIOCPWCGDYNNOISE: 1550 { 1551 ret = pwc_get_dynamic_noise(pdev); 1552 if (ret < 0) 1553 break; 1554 if (copy_to_user(arg, &ret, sizeof(ret))) 1555 ret = -EFAULT; 1556 break; 1557 } 1558 1559 case VIDIOCPWCGREALSIZE: 1560 { 1561 struct pwc_imagesize size; 1562 1563 size.width = pdev->image.x; 1564 size.height = pdev->image.y; 1565 if (copy_to_user(arg, &size, sizeof(size))) 1566 ret = -EFAULT; 1567 break; 1568 } 1569 1570 default: 1571 ret = -ENOIOCTLCMD; 1572 break; 1573 } 1574 1575 if (ret > 0) 1576 return 0; 1577 return ret; 1578} 1579 1580 1581 1582