1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40#ifdef __KERNEL__
41#include <asm/uaccess.h>
42#endif
43#include <asm/errno.h>
44
45#include "pwc.h"
46#include "pwc-uncompress.h"
47#include "pwc-kiara.h"
48#include "pwc-timon.h"
49#include "pwc-dec1.h"
50#include "pwc-dec23.h"
51
52
53#define SET_LUM_CTL 0x01
54#define GET_LUM_CTL 0x02
55#define SET_CHROM_CTL 0x03
56#define GET_CHROM_CTL 0x04
57#define SET_STATUS_CTL 0x05
58#define GET_STATUS_CTL 0x06
59#define SET_EP_STREAM_CTL 0x07
60#define GET_EP_STREAM_CTL 0x08
61#define GET_XX_CTL 0x09
62#define SET_XX_CTL 0x0A
63#define GET_XY_CTL 0x0B
64#define SET_XY_CTL 0x0C
65#define SET_MPT_CTL 0x0D
66#define GET_MPT_CTL 0x0E
67
68
69#define AGC_MODE_FORMATTER 0x2000
70#define PRESET_AGC_FORMATTER 0x2100
71#define SHUTTER_MODE_FORMATTER 0x2200
72#define PRESET_SHUTTER_FORMATTER 0x2300
73#define PRESET_CONTOUR_FORMATTER 0x2400
74#define AUTO_CONTOUR_FORMATTER 0x2500
75#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
76#define CONTRAST_FORMATTER 0x2700
77#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
78#define FLICKERLESS_MODE_FORMATTER 0x2900
79#define AE_CONTROL_SPEED 0x2A00
80#define BRIGHTNESS_FORMATTER 0x2B00
81#define GAMMA_FORMATTER 0x2C00
82
83
84#define WB_MODE_FORMATTER 0x1000
85#define AWB_CONTROL_SPEED_FORMATTER 0x1100
86#define AWB_CONTROL_DELAY_FORMATTER 0x1200
87#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
88#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
89#define COLOUR_MODE_FORMATTER 0x1500
90#define SATURATION_MODE_FORMATTER1 0x1600
91#define SATURATION_MODE_FORMATTER2 0x1700
92
93
94#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
95#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
96#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
97#define READ_AGC_FORMATTER 0x0500
98#define READ_SHUTTER_FORMATTER 0x0600
99#define READ_RED_GAIN_FORMATTER 0x0700
100#define READ_BLUE_GAIN_FORMATTER 0x0800
101#define GET_STATUS_B00 0x0B00
102#define SENSOR_TYPE_FORMATTER1 0x0C00
103#define GET_STATUS_3000 0x3000
104#define READ_RAW_Y_MEAN_FORMATTER 0x3100
105#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
106#define MIRROR_IMAGE_FORMATTER 0x3300
107#define LED_FORMATTER 0x3400
108#define LOWLIGHT 0x3500
109#define GET_STATUS_3600 0x3600
110#define SENSOR_TYPE_FORMATTER2 0x3700
111#define GET_STATUS_3800 0x3800
112#define GET_STATUS_4000 0x4000
113#define GET_STATUS_4100 0x4100
114#define CTL_STATUS_4200 0x4200
115
116
117#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
118
119
120#define PT_RELATIVE_CONTROL_FORMATTER 0x01
121#define PT_RESET_CONTROL_FORMATTER 0x02
122#define PT_STATUS_FORMATTER 0x03
123
124static const char *size2name[PSZ_MAX] =
125{
126 "subQCIF",
127 "QSIF",
128 "QCIF",
129 "SIF",
130 "CIF",
131 "VGA",
132};
133
134
135
136
137
138
139
140
141
142#define PWC_FPS_MAX_NALA 8
143
144struct Nala_table_entry {
145 char alternate;
146 int compressed;
147
148 unsigned char mode[3];
149};
150
151static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
152
153static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
154{
155#include "pwc-nala.h"
156};
157
158static void pwc_set_image_buffer_size(struct pwc_device *pdev);
159
160
161
162static int _send_control_msg(struct pwc_device *pdev,
163 u8 request, u16 value, int index, void *buf, int buflen, int timeout)
164{
165 int rc;
166 void *kbuf = NULL;
167
168 if (buflen) {
169 kbuf = kmalloc(buflen, GFP_KERNEL);
170 if (kbuf == NULL)
171 return -ENOMEM;
172 memcpy(kbuf, buf, buflen);
173 }
174
175 rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
176 request,
177 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
178 value,
179 index,
180 kbuf, buflen, timeout);
181
182 kfree(kbuf);
183 return rc;
184}
185
186static int recv_control_msg(struct pwc_device *pdev,
187 u8 request, u16 value, void *buf, int buflen)
188{
189 int rc;
190 void *kbuf = kmalloc(buflen, GFP_KERNEL);
191
192 if (kbuf == NULL)
193 return -ENOMEM;
194
195 rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
196 request,
197 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
198 value,
199 pdev->vcinterface,
200 kbuf, buflen, 500);
201 memcpy(buf, kbuf, buflen);
202 kfree(kbuf);
203 return rc;
204}
205
206static inline int send_video_command(struct pwc_device *pdev,
207 int index, void *buf, int buflen)
208{
209 return _send_control_msg(pdev,
210 SET_EP_STREAM_CTL,
211 VIDEO_OUTPUT_CONTROL_FORMATTER,
212 index,
213 buf, buflen, 1000);
214}
215
216static inline int send_control_msg(struct pwc_device *pdev,
217 u8 request, u16 value, void *buf, int buflen)
218{
219 return _send_control_msg(pdev,
220 request, value, pdev->vcinterface, buf, buflen, 500);
221}
222
223
224
225static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
226{
227 unsigned char buf[3];
228 int ret, fps;
229 struct Nala_table_entry *pEntry;
230 int frames2frames[31] =
231 {
232 0, 0, 0, 0, 4,
233 5, 5, 7, 7, 10,
234 10, 10, 12, 12, 15,
235 15, 15, 15, 20, 20,
236 20, 20, 20, 24, 24,
237 24, 24, 24, 24, 24,
238 24
239 };
240 int frames2table[31] =
241 { 0, 0, 0, 0, 0,
242 1, 1, 1, 2, 2,
243 3, 3, 4, 4, 4,
244 5, 5, 5, 5, 5,
245 6, 6, 6, 6, 7,
246 7, 7, 7, 7, 7,
247 7
248 };
249
250 if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
251 return -EINVAL;
252 frames = frames2frames[frames];
253 fps = frames2table[frames];
254 pEntry = &Nala_table[size][fps];
255 if (pEntry->alternate == 0)
256 return -EINVAL;
257
258 memcpy(buf, pEntry->mode, 3);
259 ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
260 if (ret < 0) {
261 PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
262 return ret;
263 }
264 if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
265 pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
266
267 pdev->cmd_len = 3;
268 memcpy(pdev->cmd_buf, buf, 3);
269
270
271 pdev->vframes = frames;
272 pdev->vsize = size;
273 pdev->valternate = pEntry->alternate;
274 pdev->image = pwc_image_sizes[size];
275 pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
276 if (pEntry->compressed) {
277 if (pdev->release < 5) {
278 pdev->vbandlength = 528;
279 pdev->frame_size /= 4;
280 }
281 else {
282 pdev->vbandlength = 704;
283 pdev->frame_size /= 3;
284 }
285 }
286 else
287 pdev->vbandlength = 0;
288 return 0;
289}
290
291
292static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
293{
294 unsigned char buf[13];
295 const struct Timon_table_entry *pChoose;
296 int ret, fps;
297
298 if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
299 return -EINVAL;
300 if (size == PSZ_VGA && frames > 15)
301 return -EINVAL;
302 fps = (frames / 5) - 1;
303
304
305
306
307 pChoose = NULL;
308 while (compression <= 3) {
309 pChoose = &Timon_table[size][fps][compression];
310 if (pChoose->alternate != 0)
311 break;
312 compression++;
313 }
314 if (pChoose == NULL || pChoose->alternate == 0)
315 return -ENOENT;
316
317 memcpy(buf, pChoose->mode, 13);
318 if (snapshot)
319 buf[0] |= 0x80;
320 ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
321 if (ret < 0)
322 return ret;
323
324 if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
325 pwc_dec23_init(pdev, pdev->type, buf);
326
327 pdev->cmd_len = 13;
328 memcpy(pdev->cmd_buf, buf, 13);
329
330
331 pdev->vframes = frames;
332 pdev->vsize = size;
333 pdev->vsnapshot = snapshot;
334 pdev->valternate = pChoose->alternate;
335 pdev->image = pwc_image_sizes[size];
336 pdev->vbandlength = pChoose->bandlength;
337 if (pChoose->bandlength > 0)
338 pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
339 else
340 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
341 return 0;
342}
343
344
345static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
346{
347 const struct Kiara_table_entry *pChoose = NULL;
348 int fps, ret;
349 unsigned char buf[12];
350 struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
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
359 if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
360 {
361
362
363
364
365 PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
366 pChoose = &RawEntry;
367 }
368 else
369 {
370
371
372
373
374 snapshot = 0;
375 while (compression <= 3) {
376 pChoose = &Kiara_table[size][fps][compression];
377 if (pChoose->alternate != 0)
378 break;
379 compression++;
380 }
381 }
382 if (pChoose == NULL || pChoose->alternate == 0)
383 return -ENOENT;
384
385 PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
386
387
388 memcpy(buf, pChoose->mode, 12);
389 if (snapshot)
390 buf[0] |= 0x80;
391
392
393 ret = send_video_command(pdev, 4 , buf, 12);
394 if (ret < 0)
395 return ret;
396
397 if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
398 pwc_dec23_init(pdev, pdev->type, buf);
399
400 pdev->cmd_len = 12;
401 memcpy(pdev->cmd_buf, buf, 12);
402
403 pdev->vframes = frames;
404 pdev->vsize = size;
405 pdev->vsnapshot = snapshot;
406 pdev->valternate = pChoose->alternate;
407 pdev->image = pwc_image_sizes[size];
408 pdev->vbandlength = pChoose->bandlength;
409 if (pdev->vbandlength > 0)
410 pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
411 else
412 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
413 PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
414 pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
415 return 0;
416}
417
418
419
420
421
422
423
424
425
426
427
428int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
429{
430 int ret, size;
431
432 PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
433 size = pwc_decode_size(pdev, width, height);
434 if (size < 0) {
435 PWC_DEBUG_MODULE("Could not find suitable size.\n");
436 return -ERANGE;
437 }
438 PWC_TRACE("decode_size = %d.\n", size);
439
440 if (DEVICE_USE_CODEC1(pdev->type)) {
441 ret = set_video_mode_Nala(pdev, size, frames);
442
443 } else if (DEVICE_USE_CODEC3(pdev->type)) {
444 ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
445
446 } else {
447 ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
448 }
449 if (ret < 0) {
450 PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
451 return ret;
452 }
453 pdev->view.x = width;
454 pdev->view.y = height;
455 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
456 pwc_set_image_buffer_size(pdev);
457 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);
458 return 0;
459}
460
461static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
462{
463 unsigned int i;
464
465 for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
466 if (Nala_table[size][i].alternate) {
467 if (index--==0) return Nala_fps_vector[i];
468 }
469 }
470 return 0;
471}
472
473static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
474{
475 unsigned int i;
476
477 for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
478 if (Kiara_table[size][i][3].alternate) {
479 if (index--==0) return Kiara_fps_vector[i];
480 }
481 }
482 return 0;
483}
484
485static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
486{
487 unsigned int i;
488
489 for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
490 if (Timon_table[size][i][3].alternate) {
491 if (index--==0) return Timon_fps_vector[i];
492 }
493 }
494 return 0;
495}
496
497unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
498{
499 unsigned int ret;
500
501 if (DEVICE_USE_CODEC1(pdev->type)) {
502 ret = pwc_get_fps_Nala(pdev, index, size);
503
504 } else if (DEVICE_USE_CODEC3(pdev->type)) {
505 ret = pwc_get_fps_Kiara(pdev, index, size);
506
507 } else {
508 ret = pwc_get_fps_Timon(pdev, index, size);
509 }
510
511 return ret;
512}
513
514#define BLACK_Y 0
515#define BLACK_U 128
516#define BLACK_V 128
517
518static void pwc_set_image_buffer_size(struct pwc_device *pdev)
519{
520 int i, factor = 0;
521
522
523 switch(pdev->vpalette)
524 {
525 case VIDEO_PALETTE_YUV420P:
526 factor = 6;
527 break;
528 case VIDEO_PALETTE_RAW:
529 factor = 6;
530 break;
531 }
532
533
534 pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
535 pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
536
537
538
539
540
541
542 pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
543 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
544
545
546 for (i = 0; i < pwc_mbufs; i++) {
547 unsigned char *p = pdev->image_data + pdev->images[i].offset;
548 memset(p, BLACK_Y, pdev->view.x * pdev->view.y);
549 p += pdev->view.x * pdev->view.y;
550 memset(p, BLACK_U, pdev->view.x * pdev->view.y/4);
551 p += pdev->view.x * pdev->view.y/4;
552 memset(p, BLACK_V, pdev->view.x * pdev->view.y/4);
553 }
554}
555
556
557
558
559
560int pwc_get_brightness(struct pwc_device *pdev)
561{
562 char buf;
563 int ret;
564
565 ret = recv_control_msg(pdev,
566 GET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
567 if (ret < 0)
568 return ret;
569 return buf;
570}
571
572int pwc_set_brightness(struct pwc_device *pdev, int value)
573{
574 char buf;
575
576 if (value < 0)
577 value = 0;
578 if (value > 0xffff)
579 value = 0xffff;
580 buf = (value >> 9) & 0x7f;
581 return send_control_msg(pdev,
582 SET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
583}
584
585
586
587int pwc_get_contrast(struct pwc_device *pdev)
588{
589 char buf;
590 int ret;
591
592 ret = recv_control_msg(pdev,
593 GET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
594 if (ret < 0)
595 return ret;
596 return buf;
597}
598
599int pwc_set_contrast(struct pwc_device *pdev, int value)
600{
601 char buf;
602
603 if (value < 0)
604 value = 0;
605 if (value > 0xffff)
606 value = 0xffff;
607 buf = (value >> 10) & 0x3f;
608 return send_control_msg(pdev,
609 SET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
610}
611
612
613
614int pwc_get_gamma(struct pwc_device *pdev)
615{
616 char buf;
617 int ret;
618
619 ret = recv_control_msg(pdev,
620 GET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
621 if (ret < 0)
622 return ret;
623 return buf;
624}
625
626int pwc_set_gamma(struct pwc_device *pdev, int value)
627{
628 char buf;
629
630 if (value < 0)
631 value = 0;
632 if (value > 0xffff)
633 value = 0xffff;
634 buf = (value >> 11) & 0x1f;
635 return send_control_msg(pdev,
636 SET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
637}
638
639
640
641
642
643int pwc_get_saturation(struct pwc_device *pdev, int *value)
644{
645 char buf;
646 int ret, saturation_register;
647
648 if (pdev->type < 675)
649 return -EINVAL;
650 if (pdev->type < 730)
651 saturation_register = SATURATION_MODE_FORMATTER2;
652 else
653 saturation_register = SATURATION_MODE_FORMATTER1;
654 ret = recv_control_msg(pdev,
655 GET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
656 if (ret < 0)
657 return ret;
658 *value = (signed)buf;
659 return 0;
660}
661
662
663int pwc_set_saturation(struct pwc_device *pdev, int value)
664{
665 char buf;
666 int saturation_register;
667
668 if (pdev->type < 675)
669 return -EINVAL;
670 if (value < -100)
671 value = -100;
672 if (value > 100)
673 value = 100;
674 if (pdev->type < 730)
675 saturation_register = SATURATION_MODE_FORMATTER2;
676 else
677 saturation_register = SATURATION_MODE_FORMATTER1;
678 return send_control_msg(pdev,
679 SET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
680}
681
682
683
684int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
685{
686 char buf;
687 int ret;
688
689 if (mode)
690 buf = 0x0;
691 else
692 buf = 0xff;
693
694 ret = send_control_msg(pdev,
695 SET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
696
697 if (!mode && ret >= 0) {
698 if (value < 0)
699 value = 0;
700 if (value > 0xffff)
701 value = 0xffff;
702 buf = (value >> 10) & 0x3F;
703 ret = send_control_msg(pdev,
704 SET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
705 }
706 if (ret < 0)
707 return ret;
708 return 0;
709}
710
711int pwc_get_agc(struct pwc_device *pdev, int *value)
712{
713 unsigned char buf;
714 int ret;
715
716 ret = recv_control_msg(pdev,
717 GET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
718 if (ret < 0)
719 return ret;
720
721 if (buf != 0) {
722 ret = recv_control_msg(pdev,
723 GET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
724 if (ret < 0)
725 return ret;
726 if (buf > 0x3F)
727 buf = 0x3F;
728 *value = (buf << 10);
729 }
730 else {
731 ret = recv_control_msg(pdev,
732 GET_STATUS_CTL, READ_AGC_FORMATTER, &buf, sizeof(buf));
733 if (ret < 0)
734 return ret;
735
736 if (buf > 0x9F)
737 buf = 0x9F;
738 *value = -(48 + buf * 409);
739 }
740
741 return 0;
742}
743
744int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
745{
746 char buf[2];
747 int speed, ret;
748
749
750 if (mode)
751 buf[0] = 0x0;
752 else
753 buf[0] = 0xff;
754
755 ret = send_control_msg(pdev,
756 SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, sizeof(buf));
757
758 if (!mode && ret >= 0) {
759 if (value < 0)
760 value = 0;
761 if (value > 0xffff)
762 value = 0xffff;
763
764 if (DEVICE_USE_CODEC2(pdev->type)) {
765
766 speed = (value / 100);
767 buf[1] = speed >> 8;
768 buf[0] = speed & 0xff;
769 } else if (DEVICE_USE_CODEC3(pdev->type)) {
770
771 buf[1] = 0;
772 buf[0] = value >> 8;
773 }
774
775 ret = send_control_msg(pdev,
776 SET_LUM_CTL, PRESET_SHUTTER_FORMATTER,
777 &buf, sizeof(buf));
778 }
779 return ret;
780}
781
782
783int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
784{
785 unsigned char buf[2];
786 int ret;
787
788 ret = recv_control_msg(pdev,
789 GET_STATUS_CTL, READ_SHUTTER_FORMATTER, &buf, sizeof(buf));
790 if (ret < 0)
791 return ret;
792 *value = buf[0] + (buf[1] << 8);
793 if (DEVICE_USE_CODEC2(pdev->type)) {
794
795 *value *= 256/656;
796 } else if (DEVICE_USE_CODEC3(pdev->type)) {
797
798 }
799 return 0;
800}
801
802
803
804
805int pwc_camera_power(struct pwc_device *pdev, int power)
806{
807 char buf;
808
809 if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
810 return 0;
811
812 if (power)
813 buf = 0x00;
814 else
815 buf = 0xFF;
816 return send_control_msg(pdev,
817 SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
818 &buf, sizeof(buf));
819}
820
821
822
823
824
825int pwc_restore_user(struct pwc_device *pdev)
826{
827 return send_control_msg(pdev,
828 SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, NULL, 0);
829}
830
831int pwc_save_user(struct pwc_device *pdev)
832{
833 return send_control_msg(pdev,
834 SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, NULL, 0);
835}
836
837int pwc_restore_factory(struct pwc_device *pdev)
838{
839 return send_control_msg(pdev,
840 SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, NULL, 0);
841}
842
843
844
845
846
847
848
849
850
851
852
853
854
855int pwc_set_awb(struct pwc_device *pdev, int mode)
856{
857 char buf;
858 int ret;
859
860 if (mode < 0)
861 mode = 0;
862
863 if (mode > 4)
864 mode = 4;
865
866 buf = mode & 0x07;
867
868 ret = send_control_msg(pdev,
869 SET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
870
871 if (ret < 0)
872 return ret;
873 return 0;
874}
875
876int pwc_get_awb(struct pwc_device *pdev)
877{
878 unsigned char buf;
879 int ret;
880
881 ret = recv_control_msg(pdev,
882 GET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
883
884 if (ret < 0)
885 return ret;
886 return buf;
887}
888
889int pwc_set_red_gain(struct pwc_device *pdev, int value)
890{
891 unsigned char buf;
892
893 if (value < 0)
894 value = 0;
895 if (value > 0xffff)
896 value = 0xffff;
897
898 buf = value >> 8;
899 return send_control_msg(pdev,
900 SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
901 &buf, sizeof(buf));
902}
903
904int pwc_get_red_gain(struct pwc_device *pdev, int *value)
905{
906 unsigned char buf;
907 int ret;
908
909 ret = recv_control_msg(pdev,
910 GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
911 &buf, sizeof(buf));
912 if (ret < 0)
913 return ret;
914 *value = buf << 8;
915 return 0;
916}
917
918
919int pwc_set_blue_gain(struct pwc_device *pdev, int value)
920{
921 unsigned char buf;
922
923 if (value < 0)
924 value = 0;
925 if (value > 0xffff)
926 value = 0xffff;
927
928 buf = value >> 8;
929 return send_control_msg(pdev,
930 SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
931 &buf, sizeof(buf));
932}
933
934int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
935{
936 unsigned char buf;
937 int ret;
938
939 ret = recv_control_msg(pdev,
940 GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
941 &buf, sizeof(buf));
942 if (ret < 0)
943 return ret;
944 *value = buf << 8;
945 return 0;
946}
947
948
949
950
951
952
953static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
954{
955 unsigned char buf;
956 int ret;
957
958 ret = recv_control_msg(pdev,
959 GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, &buf, sizeof(buf));
960 if (ret < 0)
961 return ret;
962 *value = buf << 8;
963 return 0;
964}
965
966static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
967{
968 unsigned char buf;
969 int ret;
970
971 ret = recv_control_msg(pdev,
972 GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, &buf, sizeof(buf));
973 if (ret < 0)
974 return ret;
975 *value = buf << 8;
976 return 0;
977}
978
979
980static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
981{
982 unsigned char buf;
983
984
985 buf = speed / 0x7f0;
986 return send_control_msg(pdev,
987 SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
988}
989
990static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
991{
992 unsigned char buf;
993 int ret;
994
995 ret = recv_control_msg(pdev,
996 GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
997 if (ret < 0)
998 return ret;
999 *value = buf * 0x7f0;
1000 return 0;
1001}
1002
1003
1004static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
1005{
1006 unsigned char buf;
1007
1008
1009 buf = (delay >> 10);
1010 return send_control_msg(pdev,
1011 SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
1012}
1013
1014static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
1015{
1016 unsigned char buf;
1017 int ret;
1018
1019 ret = recv_control_msg(pdev,
1020 GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
1021 if (ret < 0)
1022 return ret;
1023 *value = buf << 10;
1024 return 0;
1025}
1026
1027
1028int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
1029{
1030 unsigned char buf[2];
1031
1032 if (pdev->type < 730)
1033 return 0;
1034 on_value /= 100;
1035 off_value /= 100;
1036 if (on_value < 0)
1037 on_value = 0;
1038 if (on_value > 0xff)
1039 on_value = 0xff;
1040 if (off_value < 0)
1041 off_value = 0;
1042 if (off_value > 0xff)
1043 off_value = 0xff;
1044
1045 buf[0] = on_value;
1046 buf[1] = off_value;
1047
1048 return send_control_msg(pdev,
1049 SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
1050}
1051
1052static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
1053{
1054 unsigned char buf[2];
1055 int ret;
1056
1057 if (pdev->type < 730) {
1058 *on_value = -1;
1059 *off_value = -1;
1060 return 0;
1061 }
1062
1063 ret = recv_control_msg(pdev,
1064 GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
1065 if (ret < 0)
1066 return ret;
1067 *on_value = buf[0] * 100;
1068 *off_value = buf[1] * 100;
1069 return 0;
1070}
1071
1072int pwc_set_contour(struct pwc_device *pdev, int contour)
1073{
1074 unsigned char buf;
1075 int ret;
1076
1077 if (contour < 0)
1078 buf = 0xff;
1079 else
1080 buf = 0x0;
1081 ret = send_control_msg(pdev,
1082 SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
1083 if (ret < 0)
1084 return ret;
1085
1086 if (contour < 0)
1087 return 0;
1088 if (contour > 0xffff)
1089 contour = 0xffff;
1090
1091 buf = (contour >> 10);
1092 ret = send_control_msg(pdev,
1093 SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &buf, sizeof(buf));
1094 if (ret < 0)
1095 return ret;
1096 return 0;
1097}
1098
1099int pwc_get_contour(struct pwc_device *pdev, int *contour)
1100{
1101 unsigned char buf;
1102 int ret;
1103
1104 ret = recv_control_msg(pdev,
1105 GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
1106 if (ret < 0)
1107 return ret;
1108
1109 if (buf == 0) {
1110
1111 ret = recv_control_msg(pdev,
1112 GET_LUM_CTL, PRESET_CONTOUR_FORMATTER,
1113 &buf, sizeof(buf));
1114 if (ret < 0)
1115 return ret;
1116 *contour = buf << 10;
1117 }
1118 else
1119 *contour = -1;
1120 return 0;
1121}
1122
1123
1124int pwc_set_backlight(struct pwc_device *pdev, int backlight)
1125{
1126 unsigned char buf;
1127
1128 if (backlight)
1129 buf = 0xff;
1130 else
1131 buf = 0x0;
1132 return send_control_msg(pdev,
1133 SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
1134 &buf, sizeof(buf));
1135}
1136
1137int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
1138{
1139 int ret;
1140 unsigned char buf;
1141
1142 ret = recv_control_msg(pdev,
1143 GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
1144 &buf, sizeof(buf));
1145 if (ret < 0)
1146 return ret;
1147 *backlight = !!buf;
1148 return 0;
1149}
1150
1151int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
1152{
1153 unsigned char buf;
1154
1155 if (colour)
1156 buf = 0xff;
1157 else
1158 buf = 0x0;
1159 return send_control_msg(pdev,
1160 SET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
1161}
1162
1163int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
1164{
1165 int ret;
1166 unsigned char buf;
1167
1168 ret = recv_control_msg(pdev,
1169 GET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
1170 if (ret < 0)
1171 return ret;
1172 *colour = !!buf;
1173 return 0;
1174}
1175
1176
1177int pwc_set_flicker(struct pwc_device *pdev, int flicker)
1178{
1179 unsigned char buf;
1180
1181 if (flicker)
1182 buf = 0xff;
1183 else
1184 buf = 0x0;
1185 return send_control_msg(pdev,
1186 SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
1187}
1188
1189int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
1190{
1191 int ret;
1192 unsigned char buf;
1193
1194 ret = recv_control_msg(pdev,
1195 GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
1196 if (ret < 0)
1197 return ret;
1198 *flicker = !!buf;
1199 return 0;
1200}
1201
1202int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
1203{
1204 unsigned char buf;
1205
1206 if (noise < 0)
1207 noise = 0;
1208 if (noise > 3)
1209 noise = 3;
1210 buf = noise;
1211 return send_control_msg(pdev,
1212 SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
1213 &buf, sizeof(buf));
1214}
1215
1216int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
1217{
1218 int ret;
1219 unsigned char buf;
1220
1221 ret = recv_control_msg(pdev,
1222 GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
1223 &buf, sizeof(buf));
1224 if (ret < 0)
1225 return ret;
1226 *noise = buf;
1227 return 0;
1228}
1229
1230static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
1231{
1232 unsigned char buf;
1233
1234 buf = flags & 0x03;
1235 return send_control_msg(pdev,
1236 SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf));
1237}
1238
1239int pwc_mpt_reset(struct pwc_device *pdev, int flags)
1240{
1241 int ret;
1242 ret = _pwc_mpt_reset(pdev, flags);
1243 if (ret >= 0) {
1244 pdev->pan_angle = 0;
1245 pdev->tilt_angle = 0;
1246 }
1247 return ret;
1248}
1249
1250static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
1251{
1252 unsigned char buf[4];
1253
1254
1255
1256
1257
1258
1259 pan = 64 * pan / 100;
1260 tilt = -64 * tilt / 100;
1261 buf[0] = pan & 0xFF;
1262 buf[1] = (pan >> 8) & 0xFF;
1263 buf[2] = tilt & 0xFF;
1264 buf[3] = (tilt >> 8) & 0xFF;
1265 return send_control_msg(pdev,
1266 SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf));
1267}
1268
1269int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
1270{
1271 int ret;
1272
1273
1274 if (pan < pdev->angle_range.pan_min ||
1275 pan > pdev->angle_range.pan_max ||
1276 tilt < pdev->angle_range.tilt_min ||
1277 tilt > pdev->angle_range.tilt_max)
1278 return -ERANGE;
1279
1280
1281 pan -= pdev->pan_angle;
1282 tilt -= pdev->tilt_angle;
1283
1284 if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
1285 return -ERANGE;
1286
1287 ret = _pwc_mpt_set_angle(pdev, pan, tilt);
1288 if (ret >= 0) {
1289 pdev->pan_angle += pan;
1290 pdev->tilt_angle += tilt;
1291 }
1292 if (ret == -EPIPE)
1293 ret = -ERANGE;
1294 return ret;
1295}
1296
1297static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
1298{
1299 int ret;
1300 unsigned char buf[5];
1301
1302 ret = recv_control_msg(pdev,
1303 GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf));
1304 if (ret < 0)
1305 return ret;
1306 status->status = buf[0] & 0x7;
1307 status->time_pan = (buf[1] << 8) + buf[2];
1308 status->time_tilt = (buf[3] << 8) + buf[4];
1309 return 0;
1310}
1311
1312
1313int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1314{
1315 unsigned char buf;
1316 int ret = -1, request;
1317
1318 if (pdev->type < 675)
1319 request = SENSOR_TYPE_FORMATTER1;
1320 else if (pdev->type < 730)
1321 return -1;
1322 else
1323 request = SENSOR_TYPE_FORMATTER2;
1324
1325 ret = recv_control_msg(pdev,
1326 GET_STATUS_CTL, request, &buf, sizeof(buf));
1327 if (ret < 0)
1328 return ret;
1329 if (pdev->type < 675)
1330 *sensor = buf | 0x100;
1331 else
1332 *sensor = buf;
1333 return 0;
1334}
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348#define ARG_DEF(ARG_type, ARG_name)\
1349 ARG_type *ARG_name = arg;
1350
1351#define ARG_IN(ARG_name)
1352
1353#define ARGR(ARG_name) (*ARG_name)
1354
1355#define ARGA(ARG_name) ARG_name
1356
1357#define ARG_OUT(ARG_name)
1358
1359long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1360{
1361 long ret = 0;
1362
1363 switch(cmd) {
1364 case VIDIOCPWCRUSER:
1365 {
1366 if (pwc_restore_user(pdev))
1367 ret = -EINVAL;
1368 break;
1369 }
1370
1371 case VIDIOCPWCSUSER:
1372 {
1373 if (pwc_save_user(pdev))
1374 ret = -EINVAL;
1375 break;
1376 }
1377
1378 case VIDIOCPWCFACTORY:
1379 {
1380 if (pwc_restore_factory(pdev))
1381 ret = -EINVAL;
1382 break;
1383 }
1384
1385 case VIDIOCPWCSCQUAL:
1386 {
1387 ARG_DEF(int, qual)
1388
1389 ARG_IN(qual)
1390 if (ARGR(qual) < 0 || ARGR(qual) > 3)
1391 ret = -EINVAL;
1392 else
1393 ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
1394 if (ret >= 0)
1395 pdev->vcompression = ARGR(qual);
1396 break;
1397 }
1398
1399 case VIDIOCPWCGCQUAL:
1400 {
1401 ARG_DEF(int, qual)
1402
1403 ARGR(qual) = pdev->vcompression;
1404 ARG_OUT(qual)
1405 break;
1406 }
1407
1408 case VIDIOCPWCPROBE:
1409 {
1410 ARG_DEF(struct pwc_probe, probe)
1411
1412 strcpy(ARGR(probe).name, pdev->vdev->name);
1413 ARGR(probe).type = pdev->type;
1414 ARG_OUT(probe)
1415 break;
1416 }
1417
1418 case VIDIOCPWCGSERIAL:
1419 {
1420 ARG_DEF(struct pwc_serial, serial)
1421
1422 strcpy(ARGR(serial).serial, pdev->serial);
1423 ARG_OUT(serial)
1424 break;
1425 }
1426
1427 case VIDIOCPWCSAGC:
1428 {
1429 ARG_DEF(int, agc)
1430
1431 ARG_IN(agc)
1432 if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
1433 ret = -EINVAL;
1434 break;
1435 }
1436
1437 case VIDIOCPWCGAGC:
1438 {
1439 ARG_DEF(int, agc)
1440
1441 if (pwc_get_agc(pdev, ARGA(agc)))
1442 ret = -EINVAL;
1443 ARG_OUT(agc)
1444 break;
1445 }
1446
1447 case VIDIOCPWCSSHUTTER:
1448 {
1449 ARG_DEF(int, shutter_speed)
1450
1451 ARG_IN(shutter_speed)
1452 ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
1453 break;
1454 }
1455
1456 case VIDIOCPWCSAWB:
1457 {
1458 ARG_DEF(struct pwc_whitebalance, wb)
1459
1460 ARG_IN(wb)
1461 ret = pwc_set_awb(pdev, ARGR(wb).mode);
1462 if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
1463 pwc_set_red_gain(pdev, ARGR(wb).manual_red);
1464 pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
1465 }
1466 break;
1467 }
1468
1469 case VIDIOCPWCGAWB:
1470 {
1471 ARG_DEF(struct pwc_whitebalance, wb)
1472
1473 memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
1474 ARGR(wb).mode = pwc_get_awb(pdev);
1475 if (ARGR(wb).mode < 0)
1476 ret = -EINVAL;
1477 else {
1478 if (ARGR(wb).mode == PWC_WB_MANUAL) {
1479 ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
1480 if (ret < 0)
1481 break;
1482 ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
1483 if (ret < 0)
1484 break;
1485 }
1486 if (ARGR(wb).mode == PWC_WB_AUTO) {
1487 ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
1488 if (ret < 0)
1489 break;
1490 ret = pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
1491 if (ret < 0)
1492 break;
1493 }
1494 }
1495 ARG_OUT(wb)
1496 break;
1497 }
1498
1499 case VIDIOCPWCSAWBSPEED:
1500 {
1501 ARG_DEF(struct pwc_wb_speed, wbs)
1502
1503 if (ARGR(wbs).control_speed > 0) {
1504 ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
1505 }
1506 if (ARGR(wbs).control_delay > 0) {
1507 ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
1508 }
1509 break;
1510 }
1511
1512 case VIDIOCPWCGAWBSPEED:
1513 {
1514 ARG_DEF(struct pwc_wb_speed, wbs)
1515
1516 ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
1517 if (ret < 0)
1518 break;
1519 ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
1520 if (ret < 0)
1521 break;
1522 ARG_OUT(wbs)
1523 break;
1524 }
1525
1526 case VIDIOCPWCSLED:
1527 {
1528 ARG_DEF(struct pwc_leds, leds)
1529
1530 ARG_IN(leds)
1531 ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
1532 break;
1533 }
1534
1535
1536 case VIDIOCPWCGLED:
1537 {
1538 ARG_DEF(struct pwc_leds, leds)
1539
1540 ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
1541 ARG_OUT(leds)
1542 break;
1543 }
1544
1545 case VIDIOCPWCSCONTOUR:
1546 {
1547 ARG_DEF(int, contour)
1548
1549 ARG_IN(contour)
1550 ret = pwc_set_contour(pdev, ARGR(contour));
1551 break;
1552 }
1553
1554 case VIDIOCPWCGCONTOUR:
1555 {
1556 ARG_DEF(int, contour)
1557
1558 ret = pwc_get_contour(pdev, ARGA(contour));
1559 ARG_OUT(contour)
1560 break;
1561 }
1562
1563 case VIDIOCPWCSBACKLIGHT:
1564 {
1565 ARG_DEF(int, backlight)
1566
1567 ARG_IN(backlight)
1568 ret = pwc_set_backlight(pdev, ARGR(backlight));
1569 break;
1570 }
1571
1572 case VIDIOCPWCGBACKLIGHT:
1573 {
1574 ARG_DEF(int, backlight)
1575
1576 ret = pwc_get_backlight(pdev, ARGA(backlight));
1577 ARG_OUT(backlight)
1578 break;
1579 }
1580
1581 case VIDIOCPWCSFLICKER:
1582 {
1583 ARG_DEF(int, flicker)
1584
1585 ARG_IN(flicker)
1586 ret = pwc_set_flicker(pdev, ARGR(flicker));
1587 break;
1588 }
1589
1590 case VIDIOCPWCGFLICKER:
1591 {
1592 ARG_DEF(int, flicker)
1593
1594 ret = pwc_get_flicker(pdev, ARGA(flicker));
1595 ARG_OUT(flicker)
1596 break;
1597 }
1598
1599 case VIDIOCPWCSDYNNOISE:
1600 {
1601 ARG_DEF(int, dynnoise)
1602
1603 ARG_IN(dynnoise)
1604 ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
1605 break;
1606 }
1607
1608 case VIDIOCPWCGDYNNOISE:
1609 {
1610 ARG_DEF(int, dynnoise)
1611
1612 ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
1613 ARG_OUT(dynnoise);
1614 break;
1615 }
1616
1617 case VIDIOCPWCGREALSIZE:
1618 {
1619 ARG_DEF(struct pwc_imagesize, size)
1620
1621 ARGR(size).width = pdev->image.x;
1622 ARGR(size).height = pdev->image.y;
1623 ARG_OUT(size)
1624 break;
1625 }
1626
1627 case VIDIOCPWCMPTRESET:
1628 {
1629 if (pdev->features & FEATURE_MOTOR_PANTILT)
1630 {
1631 ARG_DEF(int, flags)
1632
1633 ARG_IN(flags)
1634 ret = pwc_mpt_reset(pdev, ARGR(flags));
1635 }
1636 else
1637 {
1638 ret = -ENXIO;
1639 }
1640 break;
1641 }
1642
1643 case VIDIOCPWCMPTGRANGE:
1644 {
1645 if (pdev->features & FEATURE_MOTOR_PANTILT)
1646 {
1647 ARG_DEF(struct pwc_mpt_range, range)
1648
1649 ARGR(range) = pdev->angle_range;
1650 ARG_OUT(range)
1651 }
1652 else
1653 {
1654 ret = -ENXIO;
1655 }
1656 break;
1657 }
1658
1659 case VIDIOCPWCMPTSANGLE:
1660 {
1661 int new_pan, new_tilt;
1662
1663 if (pdev->features & FEATURE_MOTOR_PANTILT)
1664 {
1665 ARG_DEF(struct pwc_mpt_angles, angles)
1666
1667 ARG_IN(angles)
1668
1669
1670
1671 if (ARGR(angles).absolute)
1672 {
1673 new_pan = ARGR(angles).pan;
1674 new_tilt = ARGR(angles).tilt;
1675 }
1676 else
1677 {
1678 new_pan = pdev->pan_angle + ARGR(angles).pan;
1679 new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
1680 }
1681 ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
1682 }
1683 else
1684 {
1685 ret = -ENXIO;
1686 }
1687 break;
1688 }
1689
1690 case VIDIOCPWCMPTGANGLE:
1691 {
1692
1693 if (pdev->features & FEATURE_MOTOR_PANTILT)
1694 {
1695 ARG_DEF(struct pwc_mpt_angles, angles)
1696
1697 ARGR(angles).absolute = 1;
1698 ARGR(angles).pan = pdev->pan_angle;
1699 ARGR(angles).tilt = pdev->tilt_angle;
1700 ARG_OUT(angles)
1701 }
1702 else
1703 {
1704 ret = -ENXIO;
1705 }
1706 break;
1707 }
1708
1709 case VIDIOCPWCMPTSTATUS:
1710 {
1711 if (pdev->features & FEATURE_MOTOR_PANTILT)
1712 {
1713 ARG_DEF(struct pwc_mpt_status, status)
1714
1715 ret = pwc_mpt_get_status(pdev, ARGA(status));
1716 ARG_OUT(status)
1717 }
1718 else
1719 {
1720 ret = -ENXIO;
1721 }
1722 break;
1723 }
1724
1725 case VIDIOCPWCGVIDCMD:
1726 {
1727 ARG_DEF(struct pwc_video_command, vcmd);
1728
1729 ARGR(vcmd).type = pdev->type;
1730 ARGR(vcmd).release = pdev->release;
1731 ARGR(vcmd).command_len = pdev->cmd_len;
1732 memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
1733 ARGR(vcmd).bandlength = pdev->vbandlength;
1734 ARGR(vcmd).frame_size = pdev->frame_size;
1735 ARG_OUT(vcmd)
1736 break;
1737 }
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 default:
1750 ret = -ENOIOCTLCMD;
1751 break;
1752 }
1753
1754 if (ret > 0)
1755 return 0;
1756 return ret;
1757}
1758
1759
1760
1761