Subversion Repositories shark

Rev

Rev 846 | Details | Compare with Previous | Last modification | View Log | RSS feed

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