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
41#ifdef __KERNEL__
42#include <asm/uaccess.h>
43#endif
44#include <asm/errno.h>
45
46#include "pwc.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 GET_STATUS_B00 0x0B00
54#define SENSOR_TYPE_FORMATTER1 0x0C00
55#define GET_STATUS_3000 0x3000
56#define READ_RAW_Y_MEAN_FORMATTER 0x3100
57#define SET_POWER_SAVE_MODE_FORMATTER 0x3200
58#define MIRROR_IMAGE_FORMATTER 0x3300
59#define LED_FORMATTER 0x3400
60#define LOWLIGHT 0x3500
61#define GET_STATUS_3600 0x3600
62#define SENSOR_TYPE_FORMATTER2 0x3700
63#define GET_STATUS_3800 0x3800
64#define GET_STATUS_4000 0x4000
65#define GET_STATUS_4100 0x4100
66#define CTL_STATUS_4200 0x4200
67
68
69#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
70
71static const char *size2name[PSZ_MAX] =
72{
73 "subQCIF",
74 "QSIF",
75 "QCIF",
76 "SIF",
77 "CIF",
78 "VGA",
79};
80
81
82
83
84
85
86
87
88
89#define PWC_FPS_MAX_NALA 8
90
91struct Nala_table_entry {
92 char alternate;
93 int compressed;
94
95 unsigned char mode[3];
96};
97
98static unsigned int Nala_fps_vector[PWC_FPS_MAX_NALA] = { 4, 5, 7, 10, 12, 15, 20, 24 };
99
100static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] =
101{
102#include "pwc-nala.h"
103};
104
105static void pwc_set_image_buffer_size(struct pwc_device *pdev);
106
107
108
109static int _send_control_msg(struct pwc_device *pdev,
110 u8 request, u16 value, int index, void *buf, int buflen)
111{
112 int rc;
113 void *kbuf = NULL;
114
115 if (buflen) {
116 kbuf = kmalloc(buflen, GFP_KERNEL);
117 if (kbuf == NULL)
118 return -ENOMEM;
119 memcpy(kbuf, buf, buflen);
120 }
121
122 rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
123 request,
124 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
125 value,
126 index,
127 kbuf, buflen, USB_CTRL_SET_TIMEOUT);
128
129 kfree(kbuf);
130 return rc;
131}
132
133static int recv_control_msg(struct pwc_device *pdev,
134 u8 request, u16 value, void *buf, int buflen)
135{
136 int rc;
137 void *kbuf = kmalloc(buflen, GFP_KERNEL);
138
139 if (kbuf == NULL)
140 return -ENOMEM;
141
142 rc = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
143 request,
144 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
145 value,
146 pdev->vcinterface,
147 kbuf, buflen, USB_CTRL_GET_TIMEOUT);
148 memcpy(buf, kbuf, buflen);
149 kfree(kbuf);
150
151 if (rc < 0)
152 PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
153 rc, request, value);
154 return rc;
155}
156
157static inline int send_video_command(struct pwc_device *pdev,
158 int index, void *buf, int buflen)
159{
160 return _send_control_msg(pdev,
161 SET_EP_STREAM_CTL,
162 VIDEO_OUTPUT_CONTROL_FORMATTER,
163 index,
164 buf, buflen);
165}
166
167int send_control_msg(struct pwc_device *pdev,
168 u8 request, u16 value, void *buf, int buflen)
169{
170 return _send_control_msg(pdev,
171 request, value, pdev->vcinterface, buf, buflen);
172}
173
174static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
175{
176 unsigned char buf[3];
177 int ret, fps;
178 struct Nala_table_entry *pEntry;
179 int frames2frames[31] =
180 {
181 0, 0, 0, 0, 4,
182 5, 5, 7, 7, 10,
183 10, 10, 12, 12, 15,
184 15, 15, 15, 20, 20,
185 20, 20, 20, 24, 24,
186 24, 24, 24, 24, 24,
187 24
188 };
189 int frames2table[31] =
190 { 0, 0, 0, 0, 0,
191 1, 1, 1, 2, 2,
192 3, 3, 4, 4, 4,
193 5, 5, 5, 5, 5,
194 6, 6, 6, 6, 7,
195 7, 7, 7, 7, 7,
196 7
197 };
198
199 if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
200 return -EINVAL;
201 frames = frames2frames[frames];
202 fps = frames2table[frames];
203 pEntry = &Nala_table[size][fps];
204 if (pEntry->alternate == 0)
205 return -EINVAL;
206
207 memcpy(buf, pEntry->mode, 3);
208 ret = send_video_command(pdev, pdev->vendpoint, buf, 3);
209 if (ret < 0) {
210 PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
211 return ret;
212 }
213 if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
214 ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
215 if (ret < 0)
216 return ret;
217 }
218
219 pdev->cmd_len = 3;
220 memcpy(pdev->cmd_buf, buf, 3);
221
222
223 pdev->vframes = frames;
224 pdev->vsize = size;
225 pdev->valternate = pEntry->alternate;
226 pdev->image = pwc_image_sizes[size];
227 pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
228 if (pEntry->compressed) {
229 if (pdev->release < 5) {
230 pdev->vbandlength = 528;
231 pdev->frame_size /= 4;
232 }
233 else {
234 pdev->vbandlength = 704;
235 pdev->frame_size /= 3;
236 }
237 }
238 else
239 pdev->vbandlength = 0;
240 return 0;
241}
242
243
244static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
245{
246 unsigned char buf[13];
247 const struct Timon_table_entry *pChoose;
248 int ret, fps;
249
250 if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
251 return -EINVAL;
252 if (size == PSZ_VGA && frames > 15)
253 return -EINVAL;
254 fps = (frames / 5) - 1;
255
256
257
258
259 pChoose = NULL;
260 while (compression <= 3) {
261 pChoose = &Timon_table[size][fps][compression];
262 if (pChoose->alternate != 0)
263 break;
264 compression++;
265 }
266 if (pChoose == NULL || pChoose->alternate == 0)
267 return -ENOENT;
268
269 memcpy(buf, pChoose->mode, 13);
270 if (snapshot)
271 buf[0] |= 0x80;
272 ret = send_video_command(pdev, pdev->vendpoint, buf, 13);
273 if (ret < 0)
274 return ret;
275
276 if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
277 ret = pwc_dec23_init(pdev, pdev->type, buf);
278 if (ret < 0)
279 return ret;
280 }
281
282 pdev->cmd_len = 13;
283 memcpy(pdev->cmd_buf, buf, 13);
284
285
286 pdev->vframes = frames;
287 pdev->vsize = size;
288 pdev->vsnapshot = snapshot;
289 pdev->valternate = pChoose->alternate;
290 pdev->image = pwc_image_sizes[size];
291 pdev->vbandlength = pChoose->bandlength;
292 if (pChoose->bandlength > 0)
293 pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
294 else
295 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
296 return 0;
297}
298
299
300static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
301{
302 const struct Kiara_table_entry *pChoose = NULL;
303 int fps, ret;
304 unsigned char buf[12];
305 struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
306
307 if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
308 return -EINVAL;
309 if (size == PSZ_VGA && frames > 15)
310 return -EINVAL;
311 fps = (frames / 5) - 1;
312
313
314 if (size == PSZ_VGA && frames == 5 && snapshot && pdev->pixfmt != V4L2_PIX_FMT_YUV420)
315 {
316
317
318
319
320 PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
321 pChoose = &RawEntry;
322 }
323 else
324 {
325
326
327
328
329 snapshot = 0;
330 while (compression <= 3) {
331 pChoose = &Kiara_table[size][fps][compression];
332 if (pChoose->alternate != 0)
333 break;
334 compression++;
335 }
336 }
337 if (pChoose == NULL || pChoose->alternate == 0)
338 return -ENOENT;
339
340 PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
341
342
343 memcpy(buf, pChoose->mode, 12);
344 if (snapshot)
345 buf[0] |= 0x80;
346
347
348 ret = send_video_command(pdev, 4 , buf, 12);
349 if (ret < 0)
350 return ret;
351
352 if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
353 ret = pwc_dec23_init(pdev, pdev->type, buf);
354 if (ret < 0)
355 return ret;
356 }
357
358 pdev->cmd_len = 12;
359 memcpy(pdev->cmd_buf, buf, 12);
360
361 pdev->vframes = frames;
362 pdev->vsize = size;
363 pdev->vsnapshot = snapshot;
364 pdev->valternate = pChoose->alternate;
365 pdev->image = pwc_image_sizes[size];
366 pdev->vbandlength = pChoose->bandlength;
367 if (pdev->vbandlength > 0)
368 pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
369 else
370 pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
371 PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
372 pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
373 return 0;
374}
375
376
377
378
379
380
381
382
383
384
385
386int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
387{
388 int ret, size;
389
390 PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt);
391 size = pwc_decode_size(pdev, width, height);
392 if (size < 0) {
393 PWC_DEBUG_MODULE("Could not find suitable size.\n");
394 return -ERANGE;
395 }
396 PWC_TRACE("decode_size = %d.\n", size);
397
398 if (DEVICE_USE_CODEC1(pdev->type)) {
399 ret = set_video_mode_Nala(pdev, size, frames);
400
401 } else if (DEVICE_USE_CODEC3(pdev->type)) {
402 ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
403
404 } else {
405 ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
406 }
407 if (ret < 0) {
408 PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
409 return ret;
410 }
411 pdev->view.x = width;
412 pdev->view.y = height;
413 pdev->vcompression = compression;
414 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
415 pwc_set_image_buffer_size(pdev);
416 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);
417 return 0;
418}
419
420static unsigned int pwc_get_fps_Nala(struct pwc_device *pdev, unsigned int index, unsigned int size)
421{
422 unsigned int i;
423
424 for (i = 0; i < PWC_FPS_MAX_NALA; i++) {
425 if (Nala_table[size][i].alternate) {
426 if (index--==0) return Nala_fps_vector[i];
427 }
428 }
429 return 0;
430}
431
432static unsigned int pwc_get_fps_Kiara(struct pwc_device *pdev, unsigned int index, unsigned int size)
433{
434 unsigned int i;
435
436 for (i = 0; i < PWC_FPS_MAX_KIARA; i++) {
437 if (Kiara_table[size][i][3].alternate) {
438 if (index--==0) return Kiara_fps_vector[i];
439 }
440 }
441 return 0;
442}
443
444static unsigned int pwc_get_fps_Timon(struct pwc_device *pdev, unsigned int index, unsigned int size)
445{
446 unsigned int i;
447
448 for (i=0; i < PWC_FPS_MAX_TIMON; i++) {
449 if (Timon_table[size][i][3].alternate) {
450 if (index--==0) return Timon_fps_vector[i];
451 }
452 }
453 return 0;
454}
455
456unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size)
457{
458 unsigned int ret;
459
460 if (DEVICE_USE_CODEC1(pdev->type)) {
461 ret = pwc_get_fps_Nala(pdev, index, size);
462
463 } else if (DEVICE_USE_CODEC3(pdev->type)) {
464 ret = pwc_get_fps_Kiara(pdev, index, size);
465
466 } else {
467 ret = pwc_get_fps_Timon(pdev, index, size);
468 }
469
470 return ret;
471}
472
473static void pwc_set_image_buffer_size(struct pwc_device *pdev)
474{
475 int factor = 0;
476
477
478 switch (pdev->pixfmt) {
479 case V4L2_PIX_FMT_YUV420:
480 factor = 6;
481 break;
482 case V4L2_PIX_FMT_PWC1:
483 case V4L2_PIX_FMT_PWC2:
484 factor = 6;
485 break;
486 }
487
488
489 pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
490 pdev->view.size = pdev->view.x * pdev->view.y * factor / 4;
491
492
493
494
495
496
497 pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
498 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
499}
500
501int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
502{
503 int ret;
504 u8 buf;
505
506 ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
507 if (ret < 0)
508 return ret;
509
510 *data = buf;
511 return 0;
512}
513
514int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
515{
516 int ret;
517
518 ret = send_control_msg(pdev, request, value, &data, sizeof(data));
519 if (ret < 0)
520 return ret;
521
522 return 0;
523}
524
525int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
526{
527 int ret;
528 s8 buf;
529
530 ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
531 if (ret < 0)
532 return ret;
533
534 *data = buf;
535 return 0;
536}
537
538int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
539{
540 int ret;
541 u8 buf[2];
542
543 ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
544 if (ret < 0)
545 return ret;
546
547 *data = (buf[1] << 8) | buf[0];
548 return 0;
549}
550
551int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
552{
553 int ret;
554 u8 buf[2];
555
556 buf[0] = data & 0xff;
557 buf[1] = data >> 8;
558 ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
559 if (ret < 0)
560 return ret;
561
562 return 0;
563}
564
565int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
566{
567 int ret;
568
569 ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
570 if (ret < 0)
571 return ret;
572
573 return 0;
574}
575
576
577void pwc_camera_power(struct pwc_device *pdev, int power)
578{
579 char buf;
580 int r;
581
582 if (!pdev->power_save)
583 return;
584
585 if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
586 return;
587
588 if (power)
589 buf = 0x00;
590 else
591 buf = 0xFF;
592 r = send_control_msg(pdev,
593 SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
594 &buf, sizeof(buf));
595
596 if (r < 0)
597 PWC_ERROR("Failed to power %s camera (%d)\n",
598 power ? "on" : "off", r);
599}
600
601static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
602{
603 unsigned char buf;
604
605
606 buf = speed / 0x7f0;
607 return send_control_msg(pdev,
608 SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
609}
610
611static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
612{
613 unsigned char buf;
614 int ret;
615
616 ret = recv_control_msg(pdev,
617 GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf));
618 if (ret < 0)
619 return ret;
620 *value = buf * 0x7f0;
621 return 0;
622}
623
624
625static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
626{
627 unsigned char buf;
628
629
630 buf = (delay >> 10);
631 return send_control_msg(pdev,
632 SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
633}
634
635static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
636{
637 unsigned char buf;
638 int ret;
639
640 ret = recv_control_msg(pdev,
641 GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf));
642 if (ret < 0)
643 return ret;
644 *value = buf << 10;
645 return 0;
646}
647
648
649int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
650{
651 unsigned char buf[2];
652 int r;
653
654 if (pdev->type < 730)
655 return 0;
656 on_value /= 100;
657 off_value /= 100;
658 if (on_value < 0)
659 on_value = 0;
660 if (on_value > 0xff)
661 on_value = 0xff;
662 if (off_value < 0)
663 off_value = 0;
664 if (off_value > 0xff)
665 off_value = 0xff;
666
667 buf[0] = on_value;
668 buf[1] = off_value;
669
670 r = send_control_msg(pdev,
671 SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
672 if (r < 0)
673 PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
674
675 return r;
676}
677
678static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
679{
680 unsigned char buf[2];
681 int ret;
682
683 if (pdev->type < 730) {
684 *on_value = -1;
685 *off_value = -1;
686 return 0;
687 }
688
689 ret = recv_control_msg(pdev,
690 GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
691 if (ret < 0)
692 return ret;
693 *on_value = buf[0] * 100;
694 *off_value = buf[1] * 100;
695 return 0;
696}
697
698static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
699{
700 unsigned char buf;
701
702 buf = flags & 0x03;
703 return send_control_msg(pdev,
704 SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf));
705}
706
707int pwc_mpt_reset(struct pwc_device *pdev, int flags)
708{
709 int ret;
710 ret = _pwc_mpt_reset(pdev, flags);
711 if (ret >= 0) {
712 pdev->pan_angle = 0;
713 pdev->tilt_angle = 0;
714 }
715 return ret;
716}
717
718static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
719{
720 unsigned char buf[4];
721
722
723
724
725
726
727 pan = 64 * pan / 100;
728 tilt = -64 * tilt / 100;
729 buf[0] = pan & 0xFF;
730 buf[1] = (pan >> 8) & 0xFF;
731 buf[2] = tilt & 0xFF;
732 buf[3] = (tilt >> 8) & 0xFF;
733 return send_control_msg(pdev,
734 SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf));
735}
736
737int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
738{
739 int ret;
740
741
742 if (pan < pdev->angle_range.pan_min ||
743 pan > pdev->angle_range.pan_max ||
744 tilt < pdev->angle_range.tilt_min ||
745 tilt > pdev->angle_range.tilt_max)
746 return -ERANGE;
747
748
749 pan -= pdev->pan_angle;
750 tilt -= pdev->tilt_angle;
751
752 if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
753 return -ERANGE;
754
755 ret = _pwc_mpt_set_angle(pdev, pan, tilt);
756 if (ret >= 0) {
757 pdev->pan_angle += pan;
758 pdev->tilt_angle += tilt;
759 }
760 if (ret == -EPIPE)
761 ret = -ERANGE;
762 return ret;
763}
764
765static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
766{
767 int ret;
768 unsigned char buf[5];
769
770 ret = recv_control_msg(pdev,
771 GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf));
772 if (ret < 0)
773 return ret;
774 status->status = buf[0] & 0x7;
775 status->time_pan = (buf[1] << 8) + buf[2];
776 status->time_tilt = (buf[3] << 8) + buf[4];
777 return 0;
778}
779
780#ifdef CONFIG_USB_PWC_DEBUG
781int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
782{
783 unsigned char buf;
784 int ret = -1, request;
785
786 if (pdev->type < 675)
787 request = SENSOR_TYPE_FORMATTER1;
788 else if (pdev->type < 730)
789 return -1;
790 else
791 request = SENSOR_TYPE_FORMATTER2;
792
793 ret = recv_control_msg(pdev,
794 GET_STATUS_CTL, request, &buf, sizeof(buf));
795 if (ret < 0)
796 return ret;
797 if (pdev->type < 675)
798 *sensor = buf | 0x100;
799 else
800 *sensor = buf;
801 return 0;
802}
803#endif
804
805
806
807
808
809
810
811
812
813
814
815
816#define ARG_DEF(ARG_type, ARG_name)\
817 ARG_type *ARG_name = arg;
818
819#define ARG_IN(ARG_name)
820
821#define ARGR(ARG_name) (*ARG_name)
822
823#define ARGA(ARG_name) ARG_name
824
825#define ARG_OUT(ARG_name)
826
827
828
829
830static int pwc_ioctl_g_ctrl(struct v4l2_ctrl *ctrl)
831{
832 return v4l2_ctrl_g_ctrl(ctrl) * 65535 / ctrl->maximum;
833}
834
835static int pwc_ioctl_s_ctrl(struct v4l2_ctrl *ctrl, int val)
836{
837 return v4l2_ctrl_s_ctrl(ctrl, val * ctrl->maximum / 65535);
838}
839
840long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
841{
842 long ret = 0;
843
844 switch(cmd) {
845 case VIDIOCPWCRUSER:
846 ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
847 break;
848
849 case VIDIOCPWCSUSER:
850 ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
851 break;
852
853 case VIDIOCPWCFACTORY:
854 ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER);
855 break;
856
857 case VIDIOCPWCSCQUAL:
858 {
859 ARG_DEF(int, qual)
860
861 if (vb2_is_streaming(&pdev->vb_queue)) {
862 ret = -EBUSY;
863 break;
864 }
865
866 ARG_IN(qual)
867 if (ARGR(qual) < 0 || ARGR(qual) > 3)
868 ret = -EINVAL;
869 else
870 ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
871 break;
872 }
873
874 case VIDIOCPWCGCQUAL:
875 {
876 ARG_DEF(int, qual)
877
878 ARGR(qual) = pdev->vcompression;
879 ARG_OUT(qual)
880 break;
881 }
882
883 case VIDIOCPWCPROBE:
884 {
885 ARG_DEF(struct pwc_probe, probe)
886
887 strcpy(ARGR(probe).name, pdev->vdev.name);
888 ARGR(probe).type = pdev->type;
889 ARG_OUT(probe)
890 break;
891 }
892
893 case VIDIOCPWCGSERIAL:
894 {
895 ARG_DEF(struct pwc_serial, serial)
896
897 strcpy(ARGR(serial).serial, pdev->serial);
898 ARG_OUT(serial)
899 break;
900 }
901
902 case VIDIOCPWCSAGC:
903 {
904 ARG_DEF(int, agc)
905 ARG_IN(agc)
906 ret = v4l2_ctrl_s_ctrl(pdev->autogain, ARGR(agc) < 0);
907 if (ret == 0 && ARGR(agc) >= 0)
908 ret = pwc_ioctl_s_ctrl(pdev->gain, ARGR(agc));
909 break;
910 }
911
912 case VIDIOCPWCGAGC:
913 {
914 ARG_DEF(int, agc)
915 if (v4l2_ctrl_g_ctrl(pdev->autogain))
916 ARGR(agc) = -1;
917 else
918 ARGR(agc) = pwc_ioctl_g_ctrl(pdev->gain);
919 ARG_OUT(agc)
920 break;
921 }
922
923 case VIDIOCPWCSSHUTTER:
924 {
925 ARG_DEF(int, shutter)
926 ARG_IN(shutter)
927 ret = v4l2_ctrl_s_ctrl(pdev->exposure_auto,
928
929 ARGR(shutter) >= 0);
930 if (ret == 0 && ARGR(shutter) >= 0)
931 ret = pwc_ioctl_s_ctrl(pdev->exposure, ARGR(shutter));
932 break;
933 }
934
935 case VIDIOCPWCSAWB:
936 {
937 ARG_DEF(struct pwc_whitebalance, wb)
938 ARG_IN(wb)
939 ret = v4l2_ctrl_s_ctrl(pdev->auto_white_balance,
940 ARGR(wb).mode);
941 if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
942 ret = pwc_ioctl_s_ctrl(pdev->red_balance,
943 ARGR(wb).manual_red);
944 if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
945 ret = pwc_ioctl_s_ctrl(pdev->blue_balance,
946 ARGR(wb).manual_blue);
947 break;
948 }
949
950 case VIDIOCPWCGAWB:
951 {
952 ARG_DEF(struct pwc_whitebalance, wb)
953 ARGR(wb).mode = v4l2_ctrl_g_ctrl(pdev->auto_white_balance);
954 ARGR(wb).manual_red = ARGR(wb).read_red =
955 pwc_ioctl_g_ctrl(pdev->red_balance);
956 ARGR(wb).manual_blue = ARGR(wb).read_blue =
957 pwc_ioctl_g_ctrl(pdev->blue_balance);
958 ARG_OUT(wb)
959 break;
960 }
961
962 case VIDIOCPWCSAWBSPEED:
963 {
964 ARG_DEF(struct pwc_wb_speed, wbs)
965
966 if (ARGR(wbs).control_speed > 0) {
967 ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
968 }
969 if (ARGR(wbs).control_delay > 0) {
970 ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
971 }
972 break;
973 }
974
975 case VIDIOCPWCGAWBSPEED:
976 {
977 ARG_DEF(struct pwc_wb_speed, wbs)
978
979 ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
980 if (ret < 0)
981 break;
982 ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
983 if (ret < 0)
984 break;
985 ARG_OUT(wbs)
986 break;
987 }
988
989 case VIDIOCPWCSLED:
990 {
991 ARG_DEF(struct pwc_leds, leds)
992
993 ARG_IN(leds)
994 ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
995 break;
996 }
997
998
999 case VIDIOCPWCGLED:
1000 {
1001 ARG_DEF(struct pwc_leds, leds)
1002
1003 ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
1004 ARG_OUT(leds)
1005 break;
1006 }
1007
1008 case VIDIOCPWCSCONTOUR:
1009 {
1010 ARG_DEF(int, contour)
1011 ARG_IN(contour)
1012 ret = v4l2_ctrl_s_ctrl(pdev->autocontour, ARGR(contour) < 0);
1013 if (ret == 0 && ARGR(contour) >= 0)
1014 ret = pwc_ioctl_s_ctrl(pdev->contour, ARGR(contour));
1015 break;
1016 }
1017
1018 case VIDIOCPWCGCONTOUR:
1019 {
1020 ARG_DEF(int, contour)
1021 if (v4l2_ctrl_g_ctrl(pdev->autocontour))
1022 ARGR(contour) = -1;
1023 else
1024 ARGR(contour) = pwc_ioctl_g_ctrl(pdev->contour);
1025 ARG_OUT(contour)
1026 break;
1027 }
1028
1029 case VIDIOCPWCSBACKLIGHT:
1030 {
1031 ARG_DEF(int, backlight)
1032 ARG_IN(backlight)
1033 ret = v4l2_ctrl_s_ctrl(pdev->backlight, ARGR(backlight));
1034 break;
1035 }
1036
1037 case VIDIOCPWCGBACKLIGHT:
1038 {
1039 ARG_DEF(int, backlight)
1040 ARGR(backlight) = v4l2_ctrl_g_ctrl(pdev->backlight);
1041 ARG_OUT(backlight)
1042 break;
1043 }
1044
1045 case VIDIOCPWCSFLICKER:
1046 {
1047 ARG_DEF(int, flicker)
1048 ARG_IN(flicker)
1049 ret = v4l2_ctrl_s_ctrl(pdev->flicker, ARGR(flicker));
1050 break;
1051 }
1052
1053 case VIDIOCPWCGFLICKER:
1054 {
1055 ARG_DEF(int, flicker)
1056 ARGR(flicker) = v4l2_ctrl_g_ctrl(pdev->flicker);
1057 ARG_OUT(flicker)
1058 break;
1059 }
1060
1061 case VIDIOCPWCSDYNNOISE:
1062 {
1063 ARG_DEF(int, dynnoise)
1064 ARG_IN(dynnoise)
1065 ret = v4l2_ctrl_s_ctrl(pdev->noise_reduction, ARGR(dynnoise));
1066 break;
1067 }
1068
1069 case VIDIOCPWCGDYNNOISE:
1070 {
1071 ARG_DEF(int, dynnoise)
1072 ARGR(dynnoise) = v4l2_ctrl_g_ctrl(pdev->noise_reduction);
1073 ARG_OUT(dynnoise);
1074 break;
1075 }
1076
1077 case VIDIOCPWCGREALSIZE:
1078 {
1079 ARG_DEF(struct pwc_imagesize, size)
1080
1081 ARGR(size).width = pdev->image.x;
1082 ARGR(size).height = pdev->image.y;
1083 ARG_OUT(size)
1084 break;
1085 }
1086
1087 case VIDIOCPWCMPTRESET:
1088 {
1089 if (pdev->features & FEATURE_MOTOR_PANTILT)
1090 {
1091 ARG_DEF(int, flags)
1092
1093 ARG_IN(flags)
1094 ret = pwc_mpt_reset(pdev, ARGR(flags));
1095 }
1096 else
1097 {
1098 ret = -ENXIO;
1099 }
1100 break;
1101 }
1102
1103 case VIDIOCPWCMPTGRANGE:
1104 {
1105 if (pdev->features & FEATURE_MOTOR_PANTILT)
1106 {
1107 ARG_DEF(struct pwc_mpt_range, range)
1108
1109 ARGR(range) = pdev->angle_range;
1110 ARG_OUT(range)
1111 }
1112 else
1113 {
1114 ret = -ENXIO;
1115 }
1116 break;
1117 }
1118
1119 case VIDIOCPWCMPTSANGLE:
1120 {
1121 int new_pan, new_tilt;
1122
1123 if (pdev->features & FEATURE_MOTOR_PANTILT)
1124 {
1125 ARG_DEF(struct pwc_mpt_angles, angles)
1126
1127 ARG_IN(angles)
1128
1129
1130
1131 if (ARGR(angles).absolute)
1132 {
1133 new_pan = ARGR(angles).pan;
1134 new_tilt = ARGR(angles).tilt;
1135 }
1136 else
1137 {
1138 new_pan = pdev->pan_angle + ARGR(angles).pan;
1139 new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
1140 }
1141 ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
1142 }
1143 else
1144 {
1145 ret = -ENXIO;
1146 }
1147 break;
1148 }
1149
1150 case VIDIOCPWCMPTGANGLE:
1151 {
1152
1153 if (pdev->features & FEATURE_MOTOR_PANTILT)
1154 {
1155 ARG_DEF(struct pwc_mpt_angles, angles)
1156
1157 ARGR(angles).absolute = 1;
1158 ARGR(angles).pan = pdev->pan_angle;
1159 ARGR(angles).tilt = pdev->tilt_angle;
1160 ARG_OUT(angles)
1161 }
1162 else
1163 {
1164 ret = -ENXIO;
1165 }
1166 break;
1167 }
1168
1169 case VIDIOCPWCMPTSTATUS:
1170 {
1171 if (pdev->features & FEATURE_MOTOR_PANTILT)
1172 {
1173 ARG_DEF(struct pwc_mpt_status, status)
1174
1175 ret = pwc_mpt_get_status(pdev, ARGA(status));
1176 ARG_OUT(status)
1177 }
1178 else
1179 {
1180 ret = -ENXIO;
1181 }
1182 break;
1183 }
1184
1185 case VIDIOCPWCGVIDCMD:
1186 {
1187 ARG_DEF(struct pwc_video_command, vcmd);
1188
1189 ARGR(vcmd).type = pdev->type;
1190 ARGR(vcmd).release = pdev->release;
1191 ARGR(vcmd).command_len = pdev->cmd_len;
1192 memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
1193 ARGR(vcmd).bandlength = pdev->vbandlength;
1194 ARGR(vcmd).frame_size = pdev->frame_size;
1195 ARG_OUT(vcmd)
1196 break;
1197 }
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209 default:
1210 ret = -ENOIOCTLCMD;
1211 break;
1212 }
1213
1214 if (ret > 0)
1215 return 0;
1216 return ret;
1217}
1218
1219
1220
1221