aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc/pwc-ctrl.c
diff options
context:
space:
mode:
authorLuc Saillard <luc@saillard.org>2006-04-24 09:29:46 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-06-25 00:58:20 -0400
commit2b455db6d456ef2d44808a8377fd3bc832e08317 (patch)
treeb7b7bcabd53f9bb58d7f69eb6d012735dacd31c7 /drivers/media/video/pwc/pwc-ctrl.c
parentd9e12f25cf538d103426946121d214dff332efbb (diff)
V4L/DVB (3835): [PATCH] update pwc driver
Add v4l2 compatibility Include the decompressor (legal problem has been resolv by Alan Cox) Faster decoder and easier to maintain, optimize, ... Can export to userland compressed stream Support more cameras, lot of bugs are fixed. Signed-off-by: Luc Saillard <luc@saillard.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/pwc/pwc-ctrl.c')
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c699
1 files changed, 387 insertions, 312 deletions
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 4ba549bfa0e0..93306c717279 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -2,7 +2,7 @@
2 Functions that send various control messages to the webcam, including 2 Functions that send various control messages to the webcam, including
3 video modes. 3 video modes.
4 (C) 1999-2003 Nemosoft Unv. 4 (C) 1999-2003 Nemosoft Unv.
5 (C) 2004 Luc Saillard (luc@saillard.org) 5 (C) 2004-2006 Luc Saillard (luc@saillard.org)
6 6
7 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx 7 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
8 driver and thus may have bugs that are not present in the original version. 8 driver and thus may have bugs that are not present in the original version.
@@ -41,12 +41,14 @@
41#include <asm/uaccess.h> 41#include <asm/uaccess.h>
42#endif 42#endif
43#include <asm/errno.h> 43#include <asm/errno.h>
44#include <linux/version.h>
44 45
45#include "pwc.h" 46#include "pwc.h"
46#include "pwc-ioctl.h"
47#include "pwc-uncompress.h" 47#include "pwc-uncompress.h"
48#include "pwc-kiara.h" 48#include "pwc-kiara.h"
49#include "pwc-timon.h" 49#include "pwc-timon.h"
50#include "pwc-dec1.h"
51#include "pwc-dec23.h"
50 52
51/* Request types: video */ 53/* Request types: video */
52#define SET_LUM_CTL 0x01 54#define SET_LUM_CTL 0x01
@@ -57,6 +59,10 @@
57#define GET_STATUS_CTL 0x06 59#define GET_STATUS_CTL 0x06
58#define SET_EP_STREAM_CTL 0x07 60#define SET_EP_STREAM_CTL 0x07
59#define GET_EP_STREAM_CTL 0x08 61#define GET_EP_STREAM_CTL 0x08
62#define GET_XX_CTL 0x09
63#define SET_XX_CTL 0x0A
64#define GET_XY_CTL 0x0B
65#define SET_XY_CTL 0x0C
60#define SET_MPT_CTL 0x0D 66#define SET_MPT_CTL 0x0D
61#define GET_MPT_CTL 0x0E 67#define GET_MPT_CTL 0x0E
62 68
@@ -93,12 +99,20 @@
93#define READ_SHUTTER_FORMATTER 0x0600 99#define READ_SHUTTER_FORMATTER 0x0600
94#define READ_RED_GAIN_FORMATTER 0x0700 100#define READ_RED_GAIN_FORMATTER 0x0700
95#define READ_BLUE_GAIN_FORMATTER 0x0800 101#define READ_BLUE_GAIN_FORMATTER 0x0800
102#define GET_STATUS_B00 0x0B00
96#define SENSOR_TYPE_FORMATTER1 0x0C00 103#define SENSOR_TYPE_FORMATTER1 0x0C00
104#define GET_STATUS_3000 0x3000
97#define READ_RAW_Y_MEAN_FORMATTER 0x3100 105#define READ_RAW_Y_MEAN_FORMATTER 0x3100
98#define SET_POWER_SAVE_MODE_FORMATTER 0x3200 106#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
99#define MIRROR_IMAGE_FORMATTER 0x3300 107#define MIRROR_IMAGE_FORMATTER 0x3300
100#define LED_FORMATTER 0x3400 108#define LED_FORMATTER 0x3400
109#define LOWLIGHT 0x3500
110#define GET_STATUS_3600 0x3600
101#define SENSOR_TYPE_FORMATTER2 0x3700 111#define SENSOR_TYPE_FORMATTER2 0x3700
112#define GET_STATUS_3800 0x3800
113#define GET_STATUS_4000 0x4000
114#define GET_STATUS_4100 0x4100 /* Get */
115#define CTL_STATUS_4200 0x4200 /* [GS] 1 */
102 116
103/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ 117/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
104#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 118#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
@@ -138,6 +152,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
138#include "pwc-nala.h" 152#include "pwc-nala.h"
139}; 153};
140 154
155static void pwc_set_image_buffer_size(struct pwc_device *pdev);
141 156
142/****************************************************************************/ 157/****************************************************************************/
143 158
@@ -159,31 +174,7 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
159 &buf, buflen, 500) 174 &buf, buflen, 500)
160 175
161 176
162#if PWC_DEBUG 177static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
163void pwc_hexdump(void *p, int len)
164{
165 int i;
166 unsigned char *s;
167 char buf[100], *d;
168
169 s = (unsigned char *)p;
170 d = buf;
171 *d = '\0';
172 Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
173 for (i = 0; i < len; i++) {
174 d += sprintf(d, "%02X ", *s++);
175 if ((i & 0xF) == 0xF) {
176 Debug("%s\n", buf);
177 d = buf;
178 *d = '\0';
179 }
180 }
181 if ((i & 0xF) != 0)
182 Debug("%s\n", buf);
183}
184#endif
185
186static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
187{ 178{
188 return usb_control_msg(udev, 179 return usb_control_msg(udev,
189 usb_sndctrlpipe(udev, 0), 180 usb_sndctrlpipe(udev, 0),
@@ -196,7 +187,7 @@ static inline int send_video_command(struct usb_device *udev, int index, void *b
196 187
197 188
198 189
199static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) 190static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
200{ 191{
201 unsigned char buf[3]; 192 unsigned char buf[3];
202 int ret, fps; 193 int ret, fps;
@@ -229,34 +220,14 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
229 if (pEntry->alternate == 0) 220 if (pEntry->alternate == 0)
230 return -EINVAL; 221 return -EINVAL;
231 222
232 if (pEntry->compressed)
233 return -ENOENT; /* Not supported. */
234
235 memcpy(buf, pEntry->mode, 3); 223 memcpy(buf, pEntry->mode, 3);
236 ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3); 224 ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
237 if (ret < 0) { 225 if (ret < 0) {
238 Debug("Failed to send video command... %d\n", ret); 226 PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
239 return ret; 227 return ret;
240 } 228 }
241 if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW) 229 if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
242 { 230 pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
243 switch(pdev->type) {
244 case 645:
245 case 646:
246/* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
247 break;
248
249 case 675:
250 case 680:
251 case 690:
252 case 720:
253 case 730:
254 case 740:
255 case 750:
256/* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
257 break;
258 }
259 }
260 231
261 pdev->cmd_len = 3; 232 pdev->cmd_len = 3;
262 memcpy(pdev->cmd_buf, buf, 3); 233 memcpy(pdev->cmd_buf, buf, 3);
@@ -283,7 +254,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
283} 254}
284 255
285 256
286static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) 257static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
287{ 258{
288 unsigned char buf[13]; 259 unsigned char buf[13];
289 const struct Timon_table_entry *pChoose; 260 const struct Timon_table_entry *pChoose;
@@ -315,8 +286,8 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
315 if (ret < 0) 286 if (ret < 0)
316 return ret; 287 return ret;
317 288
318/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) 289 if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
319 pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ 290 pwc_dec23_init(pdev, pdev->type, buf);
320 291
321 pdev->cmd_len = 13; 292 pdev->cmd_len = 13;
322 memcpy(pdev->cmd_buf, buf, 13); 293 memcpy(pdev->cmd_buf, buf, 13);
@@ -336,7 +307,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
336} 307}
337 308
338 309
339static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) 310static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
340{ 311{
341 const struct Kiara_table_entry *pChoose = NULL; 312 const struct Kiara_table_entry *pChoose = NULL;
342 int fps, ret; 313 int fps, ret;
@@ -350,21 +321,14 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
350 fps = (frames / 5) - 1; 321 fps = (frames / 5) - 1;
351 322
352 /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ 323 /* special case: VGA @ 5 fps and snapshot is raw bayer mode */
353 if (size == PSZ_VGA && frames == 5 && snapshot) 324 if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
354 { 325 {
355 /* Only available in case the raw palette is selected or 326 /* Only available in case the raw palette is selected or
356 we have the decompressor available. This mode is 327 we have the decompressor available. This mode is
357 only available in compressed form 328 only available in compressed form
358 */ 329 */
359 if (pdev->vpalette == VIDEO_PALETTE_RAW) 330 PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
360 { 331 pChoose = &RawEntry;
361 Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
362 pChoose = &RawEntry;
363 }
364 else
365 {
366 Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
367 }
368 } 332 }
369 else 333 else
370 { 334 {
@@ -372,6 +336,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
372 if the preferred ratio is not available. 336 if the preferred ratio is not available.
373 Skip this step when using RAW modes. 337 Skip this step when using RAW modes.
374 */ 338 */
339 snapshot = 0;
375 while (compression <= 3) { 340 while (compression <= 3) {
376 pChoose = &Kiara_table[size][fps][compression]; 341 pChoose = &Kiara_table[size][fps][compression];
377 if (pChoose->alternate != 0) 342 if (pChoose->alternate != 0)
@@ -382,7 +347,7 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
382 if (pChoose == NULL || pChoose->alternate == 0) 347 if (pChoose == NULL || pChoose->alternate == 0)
383 return -ENOENT; /* Not supported. */ 348 return -ENOENT; /* Not supported. */
384 349
385 Debug("Using alternate setting %d.\n", pChoose->alternate); 350 PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
386 351
387 /* usb_control_msg won't take staticly allocated arrays as argument?? */ 352 /* usb_control_msg won't take staticly allocated arrays as argument?? */
388 memcpy(buf, pChoose->mode, 12); 353 memcpy(buf, pChoose->mode, 12);
@@ -394,8 +359,8 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
394 if (ret < 0) 359 if (ret < 0)
395 return ret; 360 return ret;
396 361
397/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW) 362 if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
398 pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */ 363 pwc_dec23_init(pdev, pdev->type, buf);
399 364
400 pdev->cmd_len = 12; 365 pdev->cmd_len = 12;
401 memcpy(pdev->cmd_buf, buf, 12); 366 memcpy(pdev->cmd_buf, buf, 12);
@@ -410,49 +375,13 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
410 pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; 375 pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
411 else 376 else
412 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; 377 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
378 PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
379 pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
413 return 0; 380 return 0;
414} 381}
415 382
416 383
417 384
418static void pwc_set_image_buffer_size(struct pwc_device *pdev)
419{
420 int i, factor = 0, filler = 0;
421
422 /* for PALETTE_YUV420P */
423 switch(pdev->vpalette)
424 {
425 case VIDEO_PALETTE_YUV420P:
426 factor = 6;
427 filler = 128;
428 break;
429 case VIDEO_PALETTE_RAW:
430 factor = 6; /* can be uncompressed YUV420P */
431 filler = 0;
432 break;
433 }
434
435 /* Set sizes in bytes */
436 pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
437 pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
438
439 /* Align offset, or you'll get some very weird results in
440 YUV420 mode... x must be multiple of 4 (to get the Y's in
441 place), and y even (or you'll mixup U & V). This is less of a
442 problem for YUV420P.
443 */
444 pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
445 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
446
447 /* Fill buffers with gray or black */
448 for (i = 0; i < MAX_IMAGES; i++) {
449 if (pdev->image_ptr[i] != NULL)
450 memset(pdev->image_ptr[i], filler, pdev->view.size);
451 }
452}
453
454
455
456/** 385/**
457 @pdev: device structure 386 @pdev: device structure
458 @width: viewport width 387 @width: viewport width
@@ -465,50 +394,78 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
465{ 394{
466 int ret, size; 395 int ret, size;
467 396
468 Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette); 397 PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
469 size = pwc_decode_size(pdev, width, height); 398 size = pwc_decode_size(pdev, width, height);
470 if (size < 0) { 399 if (size < 0) {
471 Debug("Could not find suitable size.\n"); 400 PWC_DEBUG_MODULE("Could not find suitable size.\n");
472 return -ERANGE; 401 return -ERANGE;
473 } 402 }
474 Debug("decode_size = %d.\n", size); 403 PWC_TRACE("decode_size = %d.\n", size);
475 404
476 ret = -EINVAL; 405 if (DEVICE_USE_CODEC1(pdev->type)) {
477 switch(pdev->type) {
478 case 645:
479 case 646:
480 ret = set_video_mode_Nala(pdev, size, frames); 406 ret = set_video_mode_Nala(pdev, size, frames);
481 break;
482
483 case 675:
484 case 680:
485 case 690:
486 ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
487 break;
488 407
489 case 720: 408 } else if (DEVICE_USE_CODEC3(pdev->type)) {
490 case 730:
491 case 740:
492 case 750:
493 ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); 409 ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
494 break; 410
411 } else {
412 ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
495 } 413 }
496 if (ret < 0) { 414 if (ret < 0) {
497 if (ret == -ENOENT) 415 PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
498 Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
499 else {
500 Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
501 }
502 return ret; 416 return ret;
503 } 417 }
504 pdev->view.x = width; 418 pdev->view.x = width;
505 pdev->view.y = height; 419 pdev->view.y = height;
506 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; 420 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
507 pwc_set_image_buffer_size(pdev); 421 pwc_set_image_buffer_size(pdev);
508 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); 422 PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
509 return 0; 423 return 0;
510} 424}
511 425
426#define BLACK_Y 0
427#define BLACK_U 128
428#define BLACK_V 128
429
430static void pwc_set_image_buffer_size(struct pwc_device *pdev)
431{
432 int i, factor = 0;
433
434 /* for PALETTE_YUV420P */
435 switch(pdev->vpalette)
436 {
437 case VIDEO_PALETTE_YUV420P:
438 factor = 6;
439 break;
440 case VIDEO_PALETTE_RAW:
441 factor = 6; /* can be uncompressed YUV420P */
442 break;
443 }
444
445 /* Set sizes in bytes */
446 pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
447 pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
448
449 /* Align offset, or you'll get some very weird results in
450 YUV420 mode... x must be multiple of 4 (to get the Y's in
451 place), and y even (or you'll mixup U & V). This is less of a
452 problem for YUV420P.
453 */
454 pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
455 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
456
457 /* Fill buffers with black colors */
458 for (i = 0; i < pwc_mbufs; i++) {
459 unsigned char *p = pdev->image_data + pdev->images[i].offset;
460 memset(p, BLACK_Y, pdev->view.x * pdev->view.y);
461 p += pdev->view.x * pdev->view.y;
462 memset(p, BLACK_U, pdev->view.x * pdev->view.y/4);
463 p += pdev->view.x * pdev->view.y/4;
464 memset(p, BLACK_V, pdev->view.x * pdev->view.y/4);
465 }
466}
467
468
512 469
513/* BRIGHTNESS */ 470/* BRIGHTNESS */
514 471
@@ -520,7 +477,7 @@ int pwc_get_brightness(struct pwc_device *pdev)
520 ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1); 477 ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
521 if (ret < 0) 478 if (ret < 0)
522 return ret; 479 return ret;
523 return buf << 9; 480 return buf;
524} 481}
525 482
526int pwc_set_brightness(struct pwc_device *pdev, int value) 483int pwc_set_brightness(struct pwc_device *pdev, int value)
@@ -545,7 +502,7 @@ int pwc_get_contrast(struct pwc_device *pdev)
545 ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1); 502 ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
546 if (ret < 0) 503 if (ret < 0)
547 return ret; 504 return ret;
548 return buf << 10; 505 return buf;
549} 506}
550 507
551int pwc_set_contrast(struct pwc_device *pdev, int value) 508int pwc_set_contrast(struct pwc_device *pdev, int value)
@@ -570,7 +527,7 @@ int pwc_get_gamma(struct pwc_device *pdev)
570 ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1); 527 ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
571 if (ret < 0) 528 if (ret < 0)
572 return ret; 529 return ret;
573 return buf << 11; 530 return buf;
574} 531}
575 532
576int pwc_set_gamma(struct pwc_device *pdev, int value) 533int pwc_set_gamma(struct pwc_device *pdev, int value)
@@ -588,37 +545,47 @@ int pwc_set_gamma(struct pwc_device *pdev, int value)
588 545
589/* SATURATION */ 546/* SATURATION */
590 547
591int pwc_get_saturation(struct pwc_device *pdev) 548/* return a value between [-100 , 100] */
549int pwc_get_saturation(struct pwc_device *pdev, int *value)
592{ 550{
593 char buf; 551 char buf;
594 int ret; 552 int ret, saturation_register;
595 553
596 if (pdev->type < 675) 554 if (pdev->type < 675)
597 return -1; 555 return -EINVAL;
598 ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); 556 if (pdev->type < 730)
557 saturation_register = SATURATION_MODE_FORMATTER2;
558 else
559 saturation_register = SATURATION_MODE_FORMATTER1;
560 ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1);
599 if (ret < 0) 561 if (ret < 0)
600 return ret; 562 return ret;
601 return 32768 + buf * 327; 563 *value = (signed)buf;
564 return 0;
602} 565}
603 566
567/* @param value saturation color between [-100 , 100] */
604int pwc_set_saturation(struct pwc_device *pdev, int value) 568int pwc_set_saturation(struct pwc_device *pdev, int value)
605{ 569{
606 char buf; 570 char buf;
571 int saturation_register;
607 572
608 if (pdev->type < 675) 573 if (pdev->type < 675)
609 return -EINVAL; 574 return -EINVAL;
610 if (value < 0) 575 if (value < -100)
611 value = 0; 576 value = -100;
612 if (value > 0xffff) 577 if (value > 100)
613 value = 0xffff; 578 value = 100;
614 /* saturation ranges from -100 to +100 */ 579 if (pdev->type < 730)
615 buf = (value - 32768) / 327; 580 saturation_register = SATURATION_MODE_FORMATTER2;
616 return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1); 581 else
582 saturation_register = SATURATION_MODE_FORMATTER1;
583 return SendControlMsg(SET_CHROM_CTL, saturation_register, 1);
617} 584}
618 585
619/* AGC */ 586/* AGC */
620 587
621static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value) 588int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
622{ 589{
623 char buf; 590 char buf;
624 int ret; 591 int ret;
@@ -643,7 +610,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
643 return 0; 610 return 0;
644} 611}
645 612
646static inline int pwc_get_agc(struct pwc_device *pdev, int *value) 613int pwc_get_agc(struct pwc_device *pdev, int *value)
647{ 614{
648 unsigned char buf; 615 unsigned char buf;
649 int ret; 616 int ret;
@@ -673,7 +640,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
673 return 0; 640 return 0;
674} 641}
675 642
676static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) 643int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
677{ 644{
678 char buf[2]; 645 char buf[2];
679 int speed, ret; 646 int speed, ret;
@@ -691,23 +658,16 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
691 value = 0; 658 value = 0;
692 if (value > 0xffff) 659 if (value > 0xffff)
693 value = 0xffff; 660 value = 0xffff;
694 switch(pdev->type) { 661
695 case 675: 662 if (DEVICE_USE_CODEC2(pdev->type)) {
696 case 680:
697 case 690:
698 /* speed ranges from 0x0 to 0x290 (656) */ 663 /* speed ranges from 0x0 to 0x290 (656) */
699 speed = (value / 100); 664 speed = (value / 100);
700 buf[1] = speed >> 8; 665 buf[1] = speed >> 8;
701 buf[0] = speed & 0xff; 666 buf[0] = speed & 0xff;
702 break; 667 } else if (DEVICE_USE_CODEC3(pdev->type)) {
703 case 720:
704 case 730:
705 case 740:
706 case 750:
707 /* speed seems to range from 0x0 to 0xff */ 668 /* speed seems to range from 0x0 to 0xff */
708 buf[1] = 0; 669 buf[1] = 0;
709 buf[0] = value >> 8; 670 buf[0] = value >> 8;
710 break;
711 } 671 }
712 672
713 ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2); 673 ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
@@ -715,6 +675,25 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
715 return ret; 675 return ret;
716} 676}
717 677
678/* This function is not exported to v4l1, so output values between 0 -> 256 */
679int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
680{
681 unsigned char buf[2];
682 int ret;
683
684 ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2);
685 if (ret < 0)
686 return ret;
687 *value = buf[0] + (buf[1] << 8);
688 if (DEVICE_USE_CODEC2(pdev->type)) {
689 /* speed ranges from 0x0 to 0x290 (656) */
690 *value *= 256/656;
691 } else if (DEVICE_USE_CODEC3(pdev->type)) {
692 /* speed seems to range from 0x0 to 0xff */
693 }
694 return 0;
695}
696
718 697
719/* POWER */ 698/* POWER */
720 699
@@ -736,19 +715,19 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
736 715
737/* private calls */ 716/* private calls */
738 717
739static inline int pwc_restore_user(struct pwc_device *pdev) 718int pwc_restore_user(struct pwc_device *pdev)
740{ 719{
741 char buf; /* dummy */ 720 char buf; /* dummy */
742 return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0); 721 return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
743} 722}
744 723
745static inline int pwc_save_user(struct pwc_device *pdev) 724int pwc_save_user(struct pwc_device *pdev)
746{ 725{
747 char buf; /* dummy */ 726 char buf; /* dummy */
748 return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0); 727 return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
749} 728}
750 729
751static inline int pwc_restore_factory(struct pwc_device *pdev) 730int pwc_restore_factory(struct pwc_device *pdev)
752{ 731{
753 char buf; /* dummy */ 732 char buf; /* dummy */
754 return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0); 733 return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
@@ -766,7 +745,7 @@ static inline int pwc_restore_factory(struct pwc_device *pdev)
766 * 03: manual 745 * 03: manual
767 * 04: auto 746 * 04: auto
768 */ 747 */
769static inline int pwc_set_awb(struct pwc_device *pdev, int mode) 748int pwc_set_awb(struct pwc_device *pdev, int mode)
770{ 749{
771 char buf; 750 char buf;
772 int ret; 751 int ret;
@@ -786,7 +765,7 @@ static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
786 return 0; 765 return 0;
787} 766}
788 767
789static inline int pwc_get_awb(struct pwc_device *pdev) 768int pwc_get_awb(struct pwc_device *pdev)
790{ 769{
791 unsigned char buf; 770 unsigned char buf;
792 int ret; 771 int ret;
@@ -798,7 +777,7 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
798 return buf; 777 return buf;
799} 778}
800 779
801static inline int pwc_set_red_gain(struct pwc_device *pdev, int value) 780int pwc_set_red_gain(struct pwc_device *pdev, int value)
802{ 781{
803 unsigned char buf; 782 unsigned char buf;
804 783
@@ -811,7 +790,7 @@ static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
811 return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1); 790 return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
812} 791}
813 792
814static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value) 793int pwc_get_red_gain(struct pwc_device *pdev, int *value)
815{ 794{
816 unsigned char buf; 795 unsigned char buf;
817 int ret; 796 int ret;
@@ -824,7 +803,7 @@ static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
824} 803}
825 804
826 805
827static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value) 806int pwc_set_blue_gain(struct pwc_device *pdev, int value)
828{ 807{
829 unsigned char buf; 808 unsigned char buf;
830 809
@@ -837,7 +816,7 @@ static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
837 return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1); 816 return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
838} 817}
839 818
840static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value) 819int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
841{ 820{
842 unsigned char buf; 821 unsigned char buf;
843 int ret; 822 int ret;
@@ -854,7 +833,7 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
854 internal red/blue gains, which may be different from the manual 833 internal red/blue gains, which may be different from the manual
855 gains set or read above. 834 gains set or read above.
856 */ 835 */
857static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value) 836static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
858{ 837{
859 unsigned char buf; 838 unsigned char buf;
860 int ret; 839 int ret;
@@ -866,7 +845,7 @@ static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
866 return 0; 845 return 0;
867} 846}
868 847
869static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value) 848static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
870{ 849{
871 unsigned char buf; 850 unsigned char buf;
872 int ret; 851 int ret;
@@ -879,7 +858,7 @@ static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
879} 858}
880 859
881 860
882static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed) 861static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
883{ 862{
884 unsigned char buf; 863 unsigned char buf;
885 864
@@ -888,7 +867,7 @@ static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
888 return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1); 867 return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
889} 868}
890 869
891static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value) 870static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
892{ 871{
893 unsigned char buf; 872 unsigned char buf;
894 int ret; 873 int ret;
@@ -901,7 +880,7 @@ static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
901} 880}
902 881
903 882
904static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay) 883static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
905{ 884{
906 unsigned char buf; 885 unsigned char buf;
907 886
@@ -910,7 +889,7 @@ static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
910 return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1); 889 return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
911} 890}
912 891
913static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value) 892static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
914{ 893{
915 unsigned char buf; 894 unsigned char buf;
916 int ret; 895 int ret;
@@ -946,7 +925,7 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
946 return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2); 925 return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
947} 926}
948 927
949static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) 928int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
950{ 929{
951 unsigned char buf[2]; 930 unsigned char buf[2];
952 int ret; 931 int ret;
@@ -965,7 +944,7 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
965 return 0; 944 return 0;
966} 945}
967 946
968static inline int pwc_set_contour(struct pwc_device *pdev, int contour) 947int pwc_set_contour(struct pwc_device *pdev, int contour)
969{ 948{
970 unsigned char buf; 949 unsigned char buf;
971 int ret; 950 int ret;
@@ -990,7 +969,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
990 return 0; 969 return 0;
991} 970}
992 971
993static inline int pwc_get_contour(struct pwc_device *pdev, int *contour) 972int pwc_get_contour(struct pwc_device *pdev, int *contour)
994{ 973{
995 unsigned char buf; 974 unsigned char buf;
996 int ret; 975 int ret;
@@ -1012,7 +991,7 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
1012} 991}
1013 992
1014 993
1015static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight) 994int pwc_set_backlight(struct pwc_device *pdev, int backlight)
1016{ 995{
1017 unsigned char buf; 996 unsigned char buf;
1018 997
@@ -1023,7 +1002,7 @@ static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
1023 return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); 1002 return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
1024} 1003}
1025 1004
1026static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight) 1005int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
1027{ 1006{
1028 int ret; 1007 int ret;
1029 unsigned char buf; 1008 unsigned char buf;
@@ -1031,12 +1010,35 @@ static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
1031 ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); 1010 ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
1032 if (ret < 0) 1011 if (ret < 0)
1033 return ret; 1012 return ret;
1034 *backlight = buf; 1013 *backlight = !!buf;
1014 return 0;
1015}
1016
1017int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
1018{
1019 unsigned char buf;
1020
1021 if (colour)
1022 buf = 0xff;
1023 else
1024 buf = 0x0;
1025 return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
1026}
1027
1028int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
1029{
1030 int ret;
1031 unsigned char buf;
1032
1033 ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
1034 if (ret < 0)
1035 return ret;
1036 *colour = !!buf;
1035 return 0; 1037 return 0;
1036} 1038}
1037 1039
1038 1040
1039static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker) 1041int pwc_set_flicker(struct pwc_device *pdev, int flicker)
1040{ 1042{
1041 unsigned char buf; 1043 unsigned char buf;
1042 1044
@@ -1047,7 +1049,7 @@ static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
1047 return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); 1049 return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
1048} 1050}
1049 1051
1050static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker) 1052int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
1051{ 1053{
1052 int ret; 1054 int ret;
1053 unsigned char buf; 1055 unsigned char buf;
@@ -1055,12 +1057,11 @@ static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
1055 ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); 1057 ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
1056 if (ret < 0) 1058 if (ret < 0)
1057 return ret; 1059 return ret;
1058 *flicker = buf; 1060 *flicker = !!buf;
1059 return 0; 1061 return 0;
1060} 1062}
1061 1063
1062 1064int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
1063static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
1064{ 1065{
1065 unsigned char buf; 1066 unsigned char buf;
1066 1067
@@ -1072,7 +1073,7 @@ static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
1072 return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); 1073 return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
1073} 1074}
1074 1075
1075static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise) 1076int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
1076{ 1077{
1077 int ret; 1078 int ret;
1078 unsigned char buf; 1079 unsigned char buf;
@@ -1084,7 +1085,7 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
1084 return 0; 1085 return 0;
1085} 1086}
1086 1087
1087static int pwc_mpt_reset(struct pwc_device *pdev, int flags) 1088static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
1088{ 1089{
1089 unsigned char buf; 1090 unsigned char buf;
1090 1091
@@ -1092,7 +1093,18 @@ static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
1092 return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1); 1093 return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
1093} 1094}
1094 1095
1095static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) 1096int pwc_mpt_reset(struct pwc_device *pdev, int flags)
1097{
1098 int ret;
1099 ret = _pwc_mpt_reset(pdev, flags);
1100 if (ret >= 0) {
1101 pdev->pan_angle = 0;
1102 pdev->tilt_angle = 0;
1103 }
1104 return ret;
1105}
1106
1107static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
1096{ 1108{
1097 unsigned char buf[4]; 1109 unsigned char buf[4];
1098 1110
@@ -1110,7 +1122,35 @@ static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
1110 return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4); 1122 return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
1111} 1123}
1112 1124
1113static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) 1125int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
1126{
1127 int ret;
1128
1129 /* check absolute ranges */
1130 if (pan < pdev->angle_range.pan_min ||
1131 pan > pdev->angle_range.pan_max ||
1132 tilt < pdev->angle_range.tilt_min ||
1133 tilt > pdev->angle_range.tilt_max)
1134 return -ERANGE;
1135
1136 /* go to relative range, check again */
1137 pan -= pdev->pan_angle;
1138 tilt -= pdev->tilt_angle;
1139 /* angles are specified in degrees * 100, thus the limit = 36000 */
1140 if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
1141 return -ERANGE;
1142
1143 ret = _pwc_mpt_set_angle(pdev, pan, tilt);
1144 if (ret >= 0) {
1145 pdev->pan_angle += pan;
1146 pdev->tilt_angle += tilt;
1147 }
1148 if (ret == -EPIPE) /* stall -> out of range */
1149 ret = -ERANGE;
1150 return ret;
1151}
1152
1153static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
1114{ 1154{
1115 int ret; 1155 int ret;
1116 unsigned char buf[5]; 1156 unsigned char buf[5];
@@ -1151,6 +1191,26 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1151 /* End of Add-Ons */ 1191 /* End of Add-Ons */
1152 /* ************************************************* */ 1192 /* ************************************************* */
1153 1193
1194/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
1195 ioctl() calls. With 2.4, you have to do tedious copy_from_user()
1196 and copy_to_user() calls. With these macros we circumvent this,
1197 and let me maintain only one source file. The functionality is
1198 exactly the same otherwise.
1199 */
1200
1201
1202/* define local variable for arg */
1203#define ARG_DEF(ARG_type, ARG_name)\
1204 ARG_type *ARG_name = arg;
1205/* copy arg to local variable */
1206#define ARG_IN(ARG_name) /* nothing */
1207/* argument itself (referenced) */
1208#define ARGR(ARG_name) (*ARG_name)
1209/* argument address */
1210#define ARGA(ARG_name) ARG_name
1211/* copy local variable to arg */
1212#define ARG_OUT(ARG_name) /* nothing */
1213
1154 1214
1155int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) 1215int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1156{ 1216{
@@ -1180,206 +1240,243 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1180 1240
1181 case VIDIOCPWCSCQUAL: 1241 case VIDIOCPWCSCQUAL:
1182 { 1242 {
1183 int *qual = arg; 1243 ARG_DEF(int, qual)
1184 1244
1185 if (*qual < 0 || *qual > 3) 1245 ARG_IN(qual)
1246 if (ARGR(qual) < 0 || ARGR(qual) > 3)
1186 ret = -EINVAL; 1247 ret = -EINVAL;
1187 else 1248 else
1188 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); 1249 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
1189 if (ret >= 0) 1250 if (ret >= 0)
1190 pdev->vcompression = *qual; 1251 pdev->vcompression = ARGR(qual);
1191 break; 1252 break;
1192 } 1253 }
1193 1254
1194 case VIDIOCPWCGCQUAL: 1255 case VIDIOCPWCGCQUAL:
1195 { 1256 {
1196 int *qual = arg; 1257 ARG_DEF(int, qual)
1197 *qual = pdev->vcompression; 1258
1259 ARGR(qual) = pdev->vcompression;
1260 ARG_OUT(qual)
1198 break; 1261 break;
1199 } 1262 }
1200 1263
1201 case VIDIOCPWCPROBE: 1264 case VIDIOCPWCPROBE:
1202 { 1265 {
1203 struct pwc_probe *probe = arg; 1266 ARG_DEF(struct pwc_probe, probe)
1204 strcpy(probe->name, pdev->vdev->name); 1267
1205 probe->type = pdev->type; 1268 strcpy(ARGR(probe).name, pdev->vdev->name);
1269 ARGR(probe).type = pdev->type;
1270 ARG_OUT(probe)
1206 break; 1271 break;
1207 } 1272 }
1208 1273
1209 case VIDIOCPWCGSERIAL: 1274 case VIDIOCPWCGSERIAL:
1210 { 1275 {
1211 struct pwc_serial *serial = arg; 1276 ARG_DEF(struct pwc_serial, serial)
1212 strcpy(serial->serial, pdev->serial); 1277
1278 strcpy(ARGR(serial).serial, pdev->serial);
1279 ARG_OUT(serial)
1213 break; 1280 break;
1214 } 1281 }
1215 1282
1216 case VIDIOCPWCSAGC: 1283 case VIDIOCPWCSAGC:
1217 { 1284 {
1218 int *agc = arg; 1285 ARG_DEF(int, agc)
1219 if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) 1286
1287 ARG_IN(agc)
1288 if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
1220 ret = -EINVAL; 1289 ret = -EINVAL;
1221 break; 1290 break;
1222 } 1291 }
1223 1292
1224 case VIDIOCPWCGAGC: 1293 case VIDIOCPWCGAGC:
1225 { 1294 {
1226 int *agc = arg; 1295 ARG_DEF(int, agc)
1227 1296
1228 if (pwc_get_agc(pdev, agc)) 1297 if (pwc_get_agc(pdev, ARGA(agc)))
1229 ret = -EINVAL; 1298 ret = -EINVAL;
1299 ARG_OUT(agc)
1230 break; 1300 break;
1231 } 1301 }
1232 1302
1233 case VIDIOCPWCSSHUTTER: 1303 case VIDIOCPWCSSHUTTER:
1234 { 1304 {
1235 int *shutter_speed = arg; 1305 ARG_DEF(int, shutter_speed)
1236 ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); 1306
1307 ARG_IN(shutter_speed)
1308 ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
1237 break; 1309 break;
1238 } 1310 }
1239 1311
1240 case VIDIOCPWCSAWB: 1312 case VIDIOCPWCSAWB:
1241 { 1313 {
1242 struct pwc_whitebalance *wb = arg; 1314 ARG_DEF(struct pwc_whitebalance, wb)
1243 1315
1244 ret = pwc_set_awb(pdev, wb->mode); 1316 ARG_IN(wb)
1245 if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { 1317 ret = pwc_set_awb(pdev, ARGR(wb).mode);
1246 pwc_set_red_gain(pdev, wb->manual_red); 1318 if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
1247 pwc_set_blue_gain(pdev, wb->manual_blue); 1319 pwc_set_red_gain(pdev, ARGR(wb).manual_red);
1320 pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
1248 } 1321 }
1249 break; 1322 break;
1250 } 1323 }
1251 1324
1252 case VIDIOCPWCGAWB: 1325 case VIDIOCPWCGAWB:
1253 { 1326 {
1254 struct pwc_whitebalance *wb = arg; 1327 ARG_DEF(struct pwc_whitebalance, wb)
1255 1328
1256 memset(wb, 0, sizeof(struct pwc_whitebalance)); 1329 memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
1257 wb->mode = pwc_get_awb(pdev); 1330 ARGR(wb).mode = pwc_get_awb(pdev);
1258 if (wb->mode < 0) 1331 if (ARGR(wb).mode < 0)
1259 ret = -EINVAL; 1332 ret = -EINVAL;
1260 else { 1333 else {
1261 if (wb->mode == PWC_WB_MANUAL) { 1334 if (ARGR(wb).mode == PWC_WB_MANUAL) {
1262 ret = pwc_get_red_gain(pdev, &wb->manual_red); 1335 ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
1263 if (ret < 0) 1336 if (ret < 0)
1264 break; 1337 break;
1265 ret = pwc_get_blue_gain(pdev, &wb->manual_blue); 1338 ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
1266 if (ret < 0) 1339 if (ret < 0)
1267 break; 1340 break;
1268 } 1341 }
1269 if (wb->mode == PWC_WB_AUTO) { 1342 if (ARGR(wb).mode == PWC_WB_AUTO) {
1270 ret = pwc_read_red_gain(pdev, &wb->read_red); 1343 ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
1271 if (ret < 0) 1344 if (ret < 0)
1272 break; 1345 break;
1273 ret = pwc_read_blue_gain(pdev, &wb->read_blue); 1346 ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
1274 if (ret < 0) 1347 if (ret < 0)
1275 break; 1348 break;
1276 } 1349 }
1277 } 1350 }
1351 ARG_OUT(wb)
1278 break; 1352 break;
1279 } 1353 }
1280 1354
1281 case VIDIOCPWCSAWBSPEED: 1355 case VIDIOCPWCSAWBSPEED:
1282 { 1356 {
1283 struct pwc_wb_speed *wbs = arg; 1357 ARG_DEF(struct pwc_wb_speed, wbs)
1284 1358
1285 if (wbs->control_speed > 0) { 1359 if (ARGR(wbs).control_speed > 0) {
1286 ret = pwc_set_wb_speed(pdev, wbs->control_speed); 1360 ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
1287 } 1361 }
1288 if (wbs->control_delay > 0) { 1362 if (ARGR(wbs).control_delay > 0) {
1289 ret = pwc_set_wb_delay(pdev, wbs->control_delay); 1363 ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
1290 } 1364 }
1291 break; 1365 break;
1292 } 1366 }
1293 1367
1294 case VIDIOCPWCGAWBSPEED: 1368 case VIDIOCPWCGAWBSPEED:
1295 { 1369 {
1296 struct pwc_wb_speed *wbs = arg; 1370 ARG_DEF(struct pwc_wb_speed, wbs)
1297 1371
1298 ret = pwc_get_wb_speed(pdev, &wbs->control_speed); 1372 ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
1299 if (ret < 0) 1373 if (ret < 0)
1300 break; 1374 break;
1301 ret = pwc_get_wb_delay(pdev, &wbs->control_delay); 1375 ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
1302 if (ret < 0) 1376 if (ret < 0)
1303 break; 1377 break;
1378 ARG_OUT(wbs)
1304 break; 1379 break;
1305 } 1380 }
1306 1381
1307 case VIDIOCPWCSLED: 1382 case VIDIOCPWCSLED:
1308 { 1383 {
1309 struct pwc_leds *leds = arg; 1384 ARG_DEF(struct pwc_leds, leds)
1310 ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); 1385
1386 ARG_IN(leds)
1387 ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
1311 break; 1388 break;
1312 } 1389 }
1313 1390
1314 1391
1315 case VIDIOCPWCGLED: 1392 case VIDIOCPWCGLED:
1316 { 1393 {
1317 struct pwc_leds *leds = arg; 1394 ARG_DEF(struct pwc_leds, leds)
1318 ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); 1395
1396 ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
1397 ARG_OUT(leds)
1319 break; 1398 break;
1320 } 1399 }
1321 1400
1322 case VIDIOCPWCSCONTOUR: 1401 case VIDIOCPWCSCONTOUR:
1323 { 1402 {
1324 int *contour = arg; 1403 ARG_DEF(int, contour)
1325 ret = pwc_set_contour(pdev, *contour); 1404
1405 ARG_IN(contour)
1406 ret = pwc_set_contour(pdev, ARGR(contour));
1326 break; 1407 break;
1327 } 1408 }
1328 1409
1329 case VIDIOCPWCGCONTOUR: 1410 case VIDIOCPWCGCONTOUR:
1330 { 1411 {
1331 int *contour = arg; 1412 ARG_DEF(int, contour)
1332 ret = pwc_get_contour(pdev, contour); 1413
1414 ret = pwc_get_contour(pdev, ARGA(contour));
1415 ARG_OUT(contour)
1333 break; 1416 break;
1334 } 1417 }
1335 1418
1336 case VIDIOCPWCSBACKLIGHT: 1419 case VIDIOCPWCSBACKLIGHT:
1337 { 1420 {
1338 int *backlight = arg; 1421 ARG_DEF(int, backlight)
1339 ret = pwc_set_backlight(pdev, *backlight); 1422
1423 ARG_IN(backlight)
1424 ret = pwc_set_backlight(pdev, ARGR(backlight));
1340 break; 1425 break;
1341 } 1426 }
1342 1427
1343 case VIDIOCPWCGBACKLIGHT: 1428 case VIDIOCPWCGBACKLIGHT:
1344 { 1429 {
1345 int *backlight = arg; 1430 ARG_DEF(int, backlight)
1346 ret = pwc_get_backlight(pdev, backlight); 1431
1432 ret = pwc_get_backlight(pdev, ARGA(backlight));
1433 ARG_OUT(backlight)
1347 break; 1434 break;
1348 } 1435 }
1349 1436
1350 case VIDIOCPWCSFLICKER: 1437 case VIDIOCPWCSFLICKER:
1351 { 1438 {
1352 int *flicker = arg; 1439 ARG_DEF(int, flicker)
1353 ret = pwc_set_flicker(pdev, *flicker); 1440
1441 ARG_IN(flicker)
1442 ret = pwc_set_flicker(pdev, ARGR(flicker));
1354 break; 1443 break;
1355 } 1444 }
1356 1445
1357 case VIDIOCPWCGFLICKER: 1446 case VIDIOCPWCGFLICKER:
1358 { 1447 {
1359 int *flicker = arg; 1448 ARG_DEF(int, flicker)
1360 ret = pwc_get_flicker(pdev, flicker); 1449
1450 ret = pwc_get_flicker(pdev, ARGA(flicker));
1451 ARG_OUT(flicker)
1361 break; 1452 break;
1362 } 1453 }
1363 1454
1364 case VIDIOCPWCSDYNNOISE: 1455 case VIDIOCPWCSDYNNOISE:
1365 { 1456 {
1366 int *dynnoise = arg; 1457 ARG_DEF(int, dynnoise)
1367 ret = pwc_set_dynamic_noise(pdev, *dynnoise); 1458
1459 ARG_IN(dynnoise)
1460 ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
1368 break; 1461 break;
1369 } 1462 }
1370 1463
1371 case VIDIOCPWCGDYNNOISE: 1464 case VIDIOCPWCGDYNNOISE:
1372 { 1465 {
1373 int *dynnoise = arg; 1466 ARG_DEF(int, dynnoise)
1374 ret = pwc_get_dynamic_noise(pdev, dynnoise); 1467
1468 ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
1469 ARG_OUT(dynnoise);
1375 break; 1470 break;
1376 } 1471 }
1377 1472
1378 case VIDIOCPWCGREALSIZE: 1473 case VIDIOCPWCGREALSIZE:
1379 { 1474 {
1380 struct pwc_imagesize *size = arg; 1475 ARG_DEF(struct pwc_imagesize, size)
1381 size->width = pdev->image.x; 1476
1382 size->height = pdev->image.y; 1477 ARGR(size).width = pdev->image.x;
1478 ARGR(size).height = pdev->image.y;
1479 ARG_OUT(size)
1383 break; 1480 break;
1384 } 1481 }
1385 1482
@@ -1387,14 +1484,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1387 { 1484 {
1388 if (pdev->features & FEATURE_MOTOR_PANTILT) 1485 if (pdev->features & FEATURE_MOTOR_PANTILT)
1389 { 1486 {
1390 int *flags = arg; 1487 ARG_DEF(int, flags)
1391 1488
1392 ret = pwc_mpt_reset(pdev, *flags); 1489 ARG_IN(flags)
1393 if (ret >= 0) 1490 ret = pwc_mpt_reset(pdev, ARGR(flags));
1394 {
1395 pdev->pan_angle = 0;
1396 pdev->tilt_angle = 0;
1397 }
1398 } 1491 }
1399 else 1492 else
1400 { 1493 {
@@ -1407,8 +1500,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1407 { 1500 {
1408 if (pdev->features & FEATURE_MOTOR_PANTILT) 1501 if (pdev->features & FEATURE_MOTOR_PANTILT)
1409 { 1502 {
1410 struct pwc_mpt_range *range = arg; 1503 ARG_DEF(struct pwc_mpt_range, range)
1411 *range = pdev->angle_range; 1504
1505 ARGR(range) = pdev->angle_range;
1506 ARG_OUT(range)
1412 } 1507 }
1413 else 1508 else
1414 { 1509 {
@@ -1423,48 +1518,23 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1423 1518
1424 if (pdev->features & FEATURE_MOTOR_PANTILT) 1519 if (pdev->features & FEATURE_MOTOR_PANTILT)
1425 { 1520 {
1426 struct pwc_mpt_angles *angles = arg; 1521 ARG_DEF(struct pwc_mpt_angles, angles)
1522
1523 ARG_IN(angles)
1427 /* The camera can only set relative angles, so 1524 /* The camera can only set relative angles, so
1428 do some calculations when getting an absolute angle . 1525 do some calculations when getting an absolute angle .
1429 */ 1526 */
1430 if (angles->absolute) 1527 if (ARGR(angles).absolute)
1431 { 1528 {
1432 new_pan = angles->pan; 1529 new_pan = ARGR(angles).pan;
1433 new_tilt = angles->tilt; 1530 new_tilt = ARGR(angles).tilt;
1434 } 1531 }
1435 else 1532 else
1436 { 1533 {
1437 new_pan = pdev->pan_angle + angles->pan; 1534 new_pan = pdev->pan_angle + ARGR(angles).pan;
1438 new_tilt = pdev->tilt_angle + angles->tilt; 1535 new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
1439 }
1440 /* check absolute ranges */
1441 if (new_pan < pdev->angle_range.pan_min ||
1442 new_pan > pdev->angle_range.pan_max ||
1443 new_tilt < pdev->angle_range.tilt_min ||
1444 new_tilt > pdev->angle_range.tilt_max)
1445 {
1446 ret = -ERANGE;
1447 }
1448 else
1449 {
1450 /* go to relative range, check again */
1451 new_pan -= pdev->pan_angle;
1452 new_tilt -= pdev->tilt_angle;
1453 /* angles are specified in degrees * 100, thus the limit = 36000 */
1454 if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
1455 ret = -ERANGE;
1456 }
1457 if (ret == 0) /* no errors so far */
1458 {
1459 ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
1460 if (ret >= 0)
1461 {
1462 pdev->pan_angle += new_pan;
1463 pdev->tilt_angle += new_tilt;
1464 }
1465 if (ret == -EPIPE) /* stall -> out of range */
1466 ret = -ERANGE;
1467 } 1536 }
1537 ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
1468 } 1538 }
1469 else 1539 else
1470 { 1540 {
@@ -1478,11 +1548,12 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1478 1548
1479 if (pdev->features & FEATURE_MOTOR_PANTILT) 1549 if (pdev->features & FEATURE_MOTOR_PANTILT)
1480 { 1550 {
1481 struct pwc_mpt_angles *angles = arg; 1551 ARG_DEF(struct pwc_mpt_angles, angles)
1482 1552
1483 angles->absolute = 1; 1553 ARGR(angles).absolute = 1;
1484 angles->pan = pdev->pan_angle; 1554 ARGR(angles).pan = pdev->pan_angle;
1485 angles->tilt = pdev->tilt_angle; 1555 ARGR(angles).tilt = pdev->tilt_angle;
1556 ARG_OUT(angles)
1486 } 1557 }
1487 else 1558 else
1488 { 1559 {
@@ -1495,8 +1566,10 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1495 { 1566 {
1496 if (pdev->features & FEATURE_MOTOR_PANTILT) 1567 if (pdev->features & FEATURE_MOTOR_PANTILT)
1497 { 1568 {
1498 struct pwc_mpt_status *status = arg; 1569 ARG_DEF(struct pwc_mpt_status, status)
1499 ret = pwc_mpt_get_status(pdev, status); 1570
1571 ret = pwc_mpt_get_status(pdev, ARGA(status));
1572 ARG_OUT(status)
1500 } 1573 }
1501 else 1574 else
1502 { 1575 {
@@ -1507,22 +1580,24 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1507 1580
1508 case VIDIOCPWCGVIDCMD: 1581 case VIDIOCPWCGVIDCMD:
1509 { 1582 {
1510 struct pwc_video_command *cmd = arg; 1583 ARG_DEF(struct pwc_video_command, cmd);
1511 1584
1512 cmd->type = pdev->type; 1585 ARGR(cmd).type = pdev->type;
1513 cmd->release = pdev->release; 1586 ARGR(cmd).release = pdev->release;
1514 cmd->command_len = pdev->cmd_len; 1587 ARGR(cmd).command_len = pdev->cmd_len;
1515 memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); 1588 memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
1516 cmd->bandlength = pdev->vbandlength; 1589 ARGR(cmd).bandlength = pdev->vbandlength;
1517 cmd->frame_size = pdev->frame_size; 1590 ARGR(cmd).frame_size = pdev->frame_size;
1591 ARG_OUT(cmd)
1518 break; 1592 break;
1519 } 1593 }
1520 /* 1594 /*
1521 case VIDIOCPWCGVIDTABLE: 1595 case VIDIOCPWCGVIDTABLE:
1522 { 1596 {
1523 struct pwc_table_init_buffer *table = arg; 1597 ARG_DEF(struct pwc_table_init_buffer, table);
1524 table->len = pdev->cmd_len; 1598 ARGR(table).len = pdev->cmd_len;
1525 memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); 1599 memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
1600 ARG_OUT(table)
1526 break; 1601 break;
1527 } 1602 }
1528 */ 1603 */
@@ -1538,4 +1613,4 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1538} 1613}
1539 1614
1540 1615
1541 1616/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */