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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [usb/] [pwc-ctrl.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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