OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [video/] [pwc/] [pwc-ctrl.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.