File: /usr/src/linux/drivers/usb/pwc-ctrl.c

1     /* Driver for Philips webcam
2        Functions that send various control messages to the webcam, including
3        video modes.
4        (C) 1999-2001 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 READ_RAW_Y_MEAN_FORMATTER		0x3100
82     #define SET_POWER_SAVE_MODE_FORMATTER		0x3200
83     #define MIRROR_IMAGE_FORMATTER			0x3300
84     #define LED_FORMATTER				0x3400
85     
86     /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
87     #define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
88     
89     static char *size2name[PSZ_MAX] =
90     {
91     	"subQCIF",
92     	"QSIF",
93     	"QCIF",
94     	"SIF",
95     	"CIF",
96     	"VGA",
97     };  
98     
99     /********/
100     
101     /* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
102        preferences, so you either get compressed or non-compressed streams.
103        
104        An alternate value of 0 means this mode is not available at all.
105      */
106     
107     struct Nala_table_entry {
108     	char alternate;			/* USB alternate setting */
109     	int compressed;			/* Compressed yes/no */
110     
111     	unsigned char mode[3];		/* precomputed mode table */
112     };
113     
114     static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
115     {
116     #include "pwc_nala.h"
117     };
118     
119     /* This tables contains entries for the 675/680/690 (Timon) camera, with
120        4 different qualities (no compression, low, medium, high).
121        It lists the bandwidth requirements for said mode by its alternate interface 
122        number. An alternate of 0 means that the mode is unavailable.
123        
124        There are 6 * 4 * 4 entries: 
125          6 different resolutions subqcif, qsif, qcif, sif, cif, vga
126          6 framerates: 5, 10, 15, 20, 25, 30
127          4 compression modi: none, low, medium, high
128          
129        When an uncompressed mode is not available, the next available compressed mode 
130        will be choosen (unless the decompressor is absent). Sometimes there are only
131        1 or 2 compressed modes available; in that case entries are duplicated.
132     */
133     struct Timon_table_entry 
134     {
135     	char alternate;			/* USB alternate interface */
136     	unsigned short packetsize;	/* Normal packet size */
137     	unsigned short bandlength;	/* Bandlength when decompressing */
138     	unsigned char mode[13];		/* precomputed mode settings for cam */
139     };
140     
141     static struct Timon_table_entry Timon_table[PSZ_MAX][6][4] = 
142     {
143     #include "pwc_timon.h"
144     };
145     
146     /* Entries for the Kiara (730/740/750) camera */
147     
148     struct Kiara_table_entry
149     {
150     	char alternate;			/* USB alternate interface */
151     	unsigned short packetsize;	/* Normal packet size */
152     	unsigned short bandlength;	/* Bandlength when decompressing */
153     	unsigned char mode[12];		/* precomputed mode settings for cam */
154     };
155     
156     static struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
157     {
158     #include "pwc_kiara.h"
159     };
160     
161     
162     /****************************************************************************/
163     
164     
165     
166     
167     #if PWC_DEBUG
168     void pwc_hexdump(void *p, int len)
169     {
170     	int i;
171     	unsigned char *s;
172     	char buf[100], *d;
173     	
174     	s = (unsigned char *)p;
175     	d = buf;
176     	*d = '\0';
177     	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
178     	for (i = 0; i < len; i++) {
179     		d += sprintf(d, "%02X ", *s++);
180     		if ((i & 0xF) == 0xF) {
181     			Debug("%s\n", buf);
182     			d = buf;
183     			*d = '\0';
184     		}
185     	}
186     	if ((i & 0xF) != 0)
187     		Debug("%s\n", buf);
188     }
189     #endif
190     
191     static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
192     {
193     	return usb_control_msg(udev,
194     		usb_sndctrlpipe(udev, 0),
195     		SET_EP_STREAM_CTL,
196     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
197     		VIDEO_OUTPUT_CONTROL_FORMATTER,
198     		index,
199     		buf, buflen, HZ);
200     }
201     
202     
203     
204     static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
205     {
206     	unsigned char buf[3];
207     	int ret, fps;
208     	struct Nala_table_entry *pEntry;
209     	int frames2frames[31] = 
210     	{ /* closest match of framerate */
211     	   0,  0,  0,  0,  4,  /*  0-4  */
212     	   5,  5,  7,  7, 10,  /*  5-9  */
213               10, 10, 12, 12, 15,  /* 10-14 */
214               15, 15, 15, 20, 20,  /* 15-19 */
215               20, 20, 20, 24, 24,  /* 20-24 */
216               24, 24, 24, 24, 24,  /* 25-29 */
217               24                   /* 30    */
218     	};
219     	int frames2table[31] = 
220     	{ 0, 0, 0, 0, 0, /*  0-4  */
221     	  1, 1, 1, 2, 2, /*  5-9  */
222     	  3, 3, 4, 4, 4, /* 10-14 */
223     	  5, 5, 5, 5, 5, /* 15-19 */
224     	  6, 6, 6, 6, 7, /* 20-24 */
225     	  7, 7, 7, 7, 7, /* 25-29 */
226     	  7              /* 30    */
227     	};
228     	
229     	if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
230     		return -EINVAL;
231     	frames = frames2frames[frames];
232     	fps = frames2table[frames];
233     	pEntry = &Nala_table[size][fps];
234     	if (pEntry->alternate == 0)
235     		return -EINVAL;
236     
237     	if (pEntry->compressed && pdev->decompressor == NULL)
238     		return -ENOENT; /* Not supported. */
239     
240     	memcpy(buf, pEntry->mode, 3);	
241     	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
242     	if (ret < 0)
243     		return ret;
244     	if (pEntry->compressed)
245     		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
246     		
247     	/* Set various parameters */
248     	pdev->vframes = frames;
249     	pdev->vsize = size;
250     	pdev->valternate = pEntry->alternate;
251     	pdev->image = pwc_image_sizes[size];
252     	pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
253     	if (pEntry->compressed) {
254     		if (pdev->release < 5) { /* 4 fold compression */
255     			pdev->vbandlength = 528;
256     			pdev->frame_size /= 4;
257     		}
258     		else {
259     			pdev->vbandlength = 704;
260     			pdev->frame_size /= 3;
261     		}
262     	}
263     	else
264     		pdev->vbandlength = 0;
265     	return 0;
266     }
267     
268     
269     static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
270     {
271     	unsigned char buf[13];
272     	struct Timon_table_entry *pChoose;
273     	int ret, fps;
274     
275     	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
276     		return -EINVAL;
277     	if (size == PSZ_VGA && frames > 15)
278     		return -EINVAL;
279     	fps = (frames / 5) - 1;
280     	
281     	/* Find a supported framerate with progressively higher compression ratios
282     	   if the preferred ratio is not available.
283     	*/
284     	pChoose = NULL;
285     	if (pdev->decompressor == NULL) {
286     #if PWC_DEBUG	
287     		Debug("Trying to find uncompressed mode.\n");
288     #endif
289     		pChoose = &Timon_table[size][fps][0];
290     	}
291     	else {
292     		while (compression <= 3) {
293     			pChoose = &Timon_table[size][fps][compression];
294     			if (pChoose->alternate != 0)
295     				break;
296     			compression++;	
297     		}
298     	}
299     	if (pChoose == NULL || pChoose->alternate == 0)
300     		return -ENOENT; /* Not supported. */
301     
302     	memcpy(buf, pChoose->mode, 13);
303     	if (snapshot)
304     		buf[0] |= 0x80;
305     	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
306     	if (ret < 0)
307     		return ret;
308     
309     	if (pChoose->bandlength > 0)
310     		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
311     	
312     	/* Set various parameters */
313     	pdev->vframes = frames;
314     	pdev->vsize = size;
315     	pdev->vsnapshot = snapshot;
316     	pdev->valternate = pChoose->alternate;
317     	pdev->image = pwc_image_sizes[size];
318     	pdev->vbandlength = pChoose->bandlength;
319     	if (pChoose->bandlength > 0) 
320     		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
321     	else
322     		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
323     	return 0;
324     }
325     
326     
327     static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
328     {
329     	struct Kiara_table_entry *pChoose;
330     	int fps, ret;
331     	unsigned char buf[12];
332     	
333     	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
334     		return -EINVAL;
335     	if (size == PSZ_VGA && frames > 15)
336     		return -EINVAL;
337     	fps = (frames / 5) - 1;
338     	
339     	/* Find a supported framerate with progressively higher compression ratios
340     	   if the preferred ratio is not available.
341     	*/
342     	pChoose = NULL;
343     	if (pdev->decompressor == NULL) {
344     #if PWC_DEBUG	
345     		Debug("Trying to find uncompressed mode.\n");
346     #endif		
347     		pChoose = &Kiara_table[size][fps][0];
348     	}
349     	else {
350     		while (compression <= 3) {
351     			pChoose = &Kiara_table[size][fps][compression];
352     			if (pChoose->alternate != 0)
353     				break;
354     			compression++;	
355     		}
356     	}
357     	if (pChoose == NULL || pChoose->alternate == 0)
358     		return -ENOENT; /* Not supported. */
359     
360     	/* usb_control_msg won't take staticly allocated arrays as argument?? */
361     	memcpy(buf, pChoose->mode, 12);
362     	if (snapshot)
363     		buf[0] |= 0x80;
364     
365     	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
366     	ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
367     	if (ret < 0)
368     		return ret;
369     
370     	if (pChoose->bandlength > 0)
371     		pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
372     		
373     	/* All set and go */
374     	pdev->vframes = frames;
375     	pdev->vsize = size;
376     	pdev->vsnapshot = snapshot;
377     	pdev->valternate = pChoose->alternate;
378     	pdev->image = pwc_image_sizes[size];
379     	pdev->vbandlength = pChoose->bandlength;
380     	if (pChoose->bandlength > 0)
381     		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
382     	else 
383     		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
384     	pdev->frame_size += (pdev->frame_header_size + pdev->frame_trailer_size);
385     	return 0;
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     	size = pwc_decode_size(pdev, width, height);
402     	if (size < 0) {
403     		Debug("Could not find suitable size.\n");
404     		return -ERANGE;
405     	}
406     	ret = -EINVAL;	
407     	switch(pdev->type) {
408     	case 645:
409     	case 646:
410     		ret = set_video_mode_Nala(pdev, size, frames);
411     		break;
412     
413     	case 675:
414     	case 680:
415     	case 690:
416     		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
417     		break;
418     		
419     	case 730:
420     	case 740:
421     	case 750:
422     		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
423     		break;
424     	}
425     	if (ret < 0) {
426     		if (ret == -ENOENT)
427     			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
428     		else {
429     			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
430     			return ret;
431     		}
432     	}
433     	pdev->view.x = width;
434     	pdev->view.y = height;
435     	pwc_set_image_buffer_size(pdev);
436     	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d, palette = %d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y, pdev->vpalette);
437     	return 0;
438     }
439     
440     
441     void pwc_set_image_buffer_size(struct pwc_device *pdev)
442     {
443     	int factor, i, filler = 0;
444     
445     	switch(pdev->vpalette) {
446     	case VIDEO_PALETTE_RGB32 | 0x80:
447     	case VIDEO_PALETTE_RGB32:
448     		factor = 16;
449     		filler = 0;
450     		break;
451     	case VIDEO_PALETTE_RGB24 | 0x80:
452     	case VIDEO_PALETTE_RGB24:
453     		factor = 12;
454     		filler = 0;
455     		break;
456     	case VIDEO_PALETTE_YUYV:
457     	case VIDEO_PALETTE_YUV422:
458     		factor = 8;
459     		filler = 128;
460     		break;
461     	case VIDEO_PALETTE_YUV420:
462     	case VIDEO_PALETTE_YUV420P:
463     		factor = 6;
464     		filler = 128;
465     		break;
466     #if PWC_DEBUG		
467     	case VIDEO_PALETTE_RAW:
468     		pdev->image.size = pdev->frame_size;
469     		pdev->view.size = pdev->frame_size;
470     		return;
471     		break;
472     #endif	
473     	default:
474     		factor = 0;
475     		break;
476     	}
477     
478     	/* Set sizes in bytes */
479     	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
480     	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
481     
482     	/* Align offset, or you'll get some very weird results in
483     	   YUV420 mode... x must be multiple of 4 (to get the Y's in 
484     	   place), and y even (or you'll mixup U & V). This is less of a
485     	   problem for YUV420P.
486     	 */
487     	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
488     	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
489     	
490     	/* Fill buffers with gray or black */
491     	for (i = 0; i < MAX_IMAGES; i++) {
492     		if (pdev->image_ptr[i] != NULL)
493     			memset(pdev->image_ptr[i], filler, pdev->view.size);
494     	}
495     }
496     
497     
498     #ifdef __KERNEL__
499     /* BRIGHTNESS */
500     
501     int pwc_get_brightness(struct pwc_device *pdev)
502     {
503     	char buf;
504     	int ret;
505     	
506     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
507     		GET_LUM_CTL,
508     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
509     		BRIGHTNESS_FORMATTER,
510     		pdev->vcinterface,
511     		&buf, 1, HZ / 2);
512     	if (ret < 0)
513     		return ret;
514     	return buf << 9;
515     }
516     
517     int pwc_set_brightness(struct pwc_device *pdev, int value)
518     {
519     	char buf;
520     
521     	if (value < 0)
522     		value = 0;
523     	if (value > 0xffff)
524     		value = 0xffff;
525     	buf = (value >> 9) & 0x7f;
526     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
527     		SET_LUM_CTL,
528     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
529     		BRIGHTNESS_FORMATTER,
530     		pdev->vcinterface,
531     		&buf, 1, HZ / 2);
532     }
533     
534     /* CONTRAST */
535     
536     int pwc_get_contrast(struct pwc_device *pdev)
537     {
538     	char buf;
539     	int ret;
540     	
541     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
542     		GET_LUM_CTL,
543     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
544     		CONTRAST_FORMATTER,
545     		pdev->vcinterface,
546     		&buf, 1, HZ / 2);
547     	if (ret < 0)
548     		return ret;
549     	return buf << 10;
550     }
551     
552     int pwc_set_contrast(struct pwc_device *pdev, int value)
553     {
554     	char buf;
555     
556     	if (value < 0)
557     		value = 0;
558     	if (value > 0xffff)
559     		value = 0xffff;
560     	buf = (value >> 10) & 0x3f;
561     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
562     		SET_LUM_CTL,
563     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
564     		CONTRAST_FORMATTER,
565     		pdev->vcinterface,
566     		&buf, 1, HZ / 2);
567     }
568     
569     /* GAMMA */
570     
571     int pwc_get_gamma(struct pwc_device *pdev)
572     {
573     	char buf;
574     	int ret;
575     	
576     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
577     		GET_LUM_CTL,
578     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
579     		GAMMA_FORMATTER,
580     		pdev->vcinterface,
581     		&buf, 1, HZ / 2);
582     	if (ret < 0)
583     		return ret;
584     	return buf << 11;
585     }
586     
587     int pwc_set_gamma(struct pwc_device *pdev, int value)
588     {
589     	char buf;
590     
591     	if (value < 0)
592     		value = 0;
593     	if (value > 0xffff)
594     		value = 0xffff;
595     	buf = (value >> 11) & 0x1f;
596     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
597     		SET_LUM_CTL,
598     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
599     		GAMMA_FORMATTER,
600     		pdev->vcinterface,
601     		&buf, 1, HZ / 2);
602     }
603     
604     
605     /* SATURATION */
606     
607     int pwc_get_saturation(struct pwc_device *pdev)
608     {
609     	char buf;
610     	int ret;
611     
612     	if (pdev->type < 675)
613     		return -1;
614     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
615     		GET_CHROM_CTL,
616     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
617     		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
618     		pdev->vcinterface,
619     		&buf, 1, HZ / 2);
620     	if (ret < 0)
621     		return ret;
622     	return 32768 + buf * 327;
623     }
624     
625     int pwc_set_saturation(struct pwc_device *pdev, int value)
626     {
627     	char buf;
628     
629     	if (pdev->type < 675)
630     		return -EINVAL;
631     	if (value < 0)
632     		value = 0;
633     	if (value > 0xffff)
634     		value = 0xffff;
635     	/* saturation ranges from -100 to +100 */
636     	buf = (value - 32768) / 327;
637     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
638     		SET_CHROM_CTL,
639     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
640     		pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1,
641     		pdev->vcinterface,
642     		&buf, 1, HZ / 2);
643     }
644     
645     /* AGC */
646     
647     static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
648     {
649     	char buf;
650     	int ret;
651     	
652     	if (mode)
653     		buf = 0x0; /* auto */
654     	else
655     		buf = 0xff; /* fixed */
656     
657     	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
658     		SET_LUM_CTL,
659     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
660     		AGC_MODE_FORMATTER,
661     		pdev->vcinterface,
662     		&buf, 1, HZ / 2);
663     	
664     	if (!mode && ret >= 0) {
665     		if (value < 0)
666     			value = 0;
667     		if (value > 0xffff)
668     			value = 0xffff;
669     		buf = (value >> 10) & 0x3F;
670     		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
671     			SET_LUM_CTL,
672     			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
673     			PRESET_AGC_FORMATTER,
674     			pdev->vcinterface,
675     			&buf, 1, HZ / 2);
676     	}
677     	if (ret < 0)
678     		return ret;
679     	return 0;
680     }
681     
682     static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
683     {
684     	unsigned char buf;
685     	int ret;
686     	
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     		AGC_MODE_FORMATTER,
691     		pdev->vcinterface,
692     		&buf, 1, HZ / 2);
693     	if (ret < 0)
694     		return ret;
695     
696     	if (buf != 0) { /* fixed */
697     		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
698     			GET_LUM_CTL,
699     			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
700     			PRESET_AGC_FORMATTER,
701     			pdev->vcinterface,
702     			&buf, 1, HZ / 2);
703     		if (ret < 0)
704     			return ret;
705     		if (buf > 0x3F)
706     			buf = 0x3F;
707     		*value = (buf << 10);		
708     	}
709     	else { /* auto */
710     		ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
711     			GET_STATUS_CTL,
712     			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
713     			READ_AGC_FORMATTER,
714     			pdev->vcinterface,
715     			&buf, 1, HZ / 2);
716     		if (ret < 0)
717     			return ret;
718     		/* Gah... this value ranges from 0x00 ... 0x9F */
719     		if (buf > 0x9F)
720     			buf = 0x9F;
721     		*value = -(48 + buf * 409);
722     	}
723     
724     	return 0;
725     }
726     
727     static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
728     {
729     	char buf[2];
730     	int speed, ret;
731     
732     
733     	if (mode)
734     		buf[0] = 0x0;	/* auto */
735     	else
736     		buf[0] = 0xff; /* fixed */
737     	
738     	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
739     		SET_LUM_CTL,
740     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
741     		SHUTTER_MODE_FORMATTER,
742     		pdev->vcinterface,
743     		buf, 1, HZ / 2);
744     
745     	if (!mode && ret >= 0) {
746     		if (value < 0)
747     			value = 0;
748     		if (value > 0xffff)
749     			value = 0xffff;
750     		switch(pdev->type) {
751     		case 675:
752     		case 680:
753     		case 690:
754     			/* speed ranges from 0x0 to 0x290 (656) */
755     			speed = (value / 100);
756     			buf[1] = speed >> 8;
757     			buf[0] = speed & 0xff;
758     			break;
759     		case 730:
760     		case 740:
761     		case 750:
762     			/* speed seems to range from 0x0 to 0xff */
763     			buf[1] = 0;
764     			buf[0] = value >> 8;
765     			break;
766     		}
767     
768     		ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
769     			SET_LUM_CTL,
770     			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
771     			PRESET_SHUTTER_FORMATTER,
772     			pdev->vcinterface,
773     			&buf, 2, HZ / 2);
774     	}
775     	return ret;
776     }	
777     
778     
779     /* POWER */
780     
781     int pwc_camera_power(struct pwc_device *pdev, int power)
782     {
783     	char buf;
784     
785     	if (pdev->type < 675 || pdev->release < 6)
786     		return 0;	/* Not supported by Nala or Timon < release 6 */
787     
788     	if (power)
789     		buf = 0x00; /* active */
790     	else
791     		buf = 0xFF; /* power save */
792     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
793     		SET_STATUS_CTL,
794     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
795     		SET_POWER_SAVE_MODE_FORMATTER,
796     		pdev->vcinterface,
797     		&buf, 1, HZ / 2);
798     }
799     
800     
801     
802     /* private calls */
803     
804     static inline int pwc_restore_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     		RESTORE_USER_DEFAULTS_FORMATTER,
810     		pdev->vcinterface,
811     		NULL, 0, HZ / 2);
812     }
813     
814     static inline int pwc_save_user(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     		SAVE_USER_DEFAULTS_FORMATTER,
820     		pdev->vcinterface,
821     		NULL, 0, HZ / 2);
822     }
823     
824     static inline int pwc_restore_factory(struct pwc_device *pdev)
825     {
826     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
827     		SET_STATUS_CTL,
828     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
829     		RESTORE_FACTORY_DEFAULTS_FORMATTER,
830     		pdev->vcinterface,
831     		NULL, 0, HZ / 2);
832     }
833     
834      /* ************************************************* */
835      /* Patch by Alvarado: (not in the original version   */
836     
837      /*
838       * the camera recognizes modes from 0 to 4:
839       *
840       * 00: indoor (incandescant lighting)
841       * 01: outdoor (sunlight)
842       * 02: fluorescent lighting
843       * 03: manual
844       * 04: auto
845       */ 
846     static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
847     {
848     	char buf;
849     	int ret;
850     	
851     	if (mode < 0)
852     	    mode = 0;
853     	
854     	if (mode > 4)
855     	    mode = 4;
856     	
857     	buf = mode & 0x07; /* just the lowest three bits */
858     	
859     	ret = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
860     		SET_CHROM_CTL,
861     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
862     		WB_MODE_FORMATTER,
863     		pdev->vcinterface,
864     		&buf, 1, HZ / 2);
865     	
866     	if (ret < 0)
867     		return ret;
868     	return 0;
869     }
870     
871     static inline int pwc_get_awb(struct pwc_device *pdev)
872     {
873     	unsigned char buf;
874     	int ret;
875     	
876     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
877     		GET_CHROM_CTL,
878     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
879     		WB_MODE_FORMATTER,
880     		pdev->vcinterface,
881     		&buf, 1, HZ / 2);
882     
883     	if (ret < 0) 
884     		return ret;
885     	return buf;
886     }
887     
888     static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
889     {
890             unsigned char buf;
891     
892     	if (value < 0)
893     		value = 0;
894     	if (value > 0xffff)
895     		value = 0xffff;
896     
897     	/* only the msb are considered */
898     	buf = value >> 8;
899     
900     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
901     		SET_CHROM_CTL,
902     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
903     		PRESET_MANUAL_RED_GAIN_FORMATTER,
904     		pdev->vcinterface,
905     		&buf, 1, HZ / 2);
906     }
907     
908     static inline int pwc_get_red_gain(struct pwc_device *pdev)
909     {
910     	unsigned char buf;
911     	int ret;
912     	
913     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
914      	        GET_STATUS_CTL, 
915     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
916     	        PRESET_MANUAL_RED_GAIN_FORMATTER,
917     		pdev->vcinterface,
918     		&buf, 1, HZ / 2);
919     
920     	if (ret < 0)
921     	    return ret;
922     	
923     	return (buf << 8);
924     }
925     
926     
927     static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
928     {
929     	unsigned char buf;
930     
931     	if (value < 0)
932     		value = 0;
933     	if (value > 0xffff)
934     		value = 0xffff;
935     
936     	/* linear mapping of 0..0xffff to -0x80..0x7f */
937     	buf = (value >> 8);
938     
939     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
940     		SET_CHROM_CTL,
941     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
942     		PRESET_MANUAL_BLUE_GAIN_FORMATTER,
943     		pdev->vcinterface,
944     		&buf, 1, HZ / 2);
945     }
946     
947     static inline int pwc_get_blue_gain(struct pwc_device *pdev)
948     {
949     	unsigned char buf;
950     	int ret;
951     	
952     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
953        	        GET_STATUS_CTL,
954     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
955     		PRESET_MANUAL_BLUE_GAIN_FORMATTER,
956     		pdev->vcinterface,
957     		&buf, 1, HZ / 2);
958     
959     	if (ret < 0)
960     	    return ret;
961     	
962     	return (buf << 8);
963     }
964     
965     /* The following two functions are different, since they only read the
966        internal red/blue gains, which may be different from the manual 
967        gains set or read above.
968      */   
969     static inline int pwc_read_red_gain(struct pwc_device *pdev)
970     {
971     	unsigned char buf;
972     	int ret;
973     	
974     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
975      	        GET_STATUS_CTL, 
976     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
977     	        READ_RED_GAIN_FORMATTER,
978     		pdev->vcinterface,
979     		&buf, 1, HZ / 2);
980     
981     	if (ret < 0)
982     	    return ret;
983     	
984     	return (buf << 8);
985     }
986     static inline int pwc_read_blue_gain(struct pwc_device *pdev)
987     {
988     	unsigned char buf;
989     	int ret;
990     	
991     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
992        	        GET_STATUS_CTL,
993     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
994     		READ_BLUE_GAIN_FORMATTER,
995     		pdev->vcinterface,
996     		&buf, 1, HZ / 2);
997     
998     	if (ret < 0)
999     	    return ret;
1000     	
1001     	return (buf << 8);
1002     }
1003     
1004     /* still unused (it doesn't work yet...) */
1005     static inline int pwc_set_led(struct pwc_device *pdev, int value)
1006     {
1007     	unsigned char buf;
1008     
1009     	if (value < 0)
1010     		value = 0;
1011     	if (value > 0xffff)
1012     		value = 0xffff;
1013     
1014     	buf = (value >> 8);
1015     
1016     	return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
1017     		SET_STATUS_CTL,
1018     		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1019     		LED_FORMATTER,
1020     		pdev->vcinterface,
1021     		&buf, 1, HZ / 2);
1022     }
1023     
1024     /* still unused (it doesn't work yet...) */
1025     static inline int pwc_get_led(struct pwc_device *pdev)
1026     {
1027     	unsigned char buf;
1028     	int ret;
1029     	
1030     	ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
1031        	        GET_STATUS_CTL,
1032     		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
1033     		LED_FORMATTER,
1034     		pdev->vcinterface,
1035     		&buf, 1, HZ / 2);
1036     
1037     	if (ret < 0)
1038     	    return ret;
1039     	
1040     	return (buf << 8);
1041     }
1042     
1043      /* End of Add-Ons                                    */
1044      /* ************************************************* */
1045     
1046     int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1047     {
1048     	switch(cmd) {
1049     	case VIDIOCPWCRUSER:
1050     	{
1051     		if (pwc_restore_user(pdev))
1052     			return -EINVAL;
1053     		break;
1054     	}
1055     	
1056     	case VIDIOCPWCSUSER:
1057     	{
1058     		if (pwc_save_user(pdev))
1059     			return -EINVAL;
1060     		break;
1061     	}
1062     		
1063     	case VIDIOCPWCFACTORY:
1064     	{
1065     		if (pwc_restore_factory(pdev))
1066     			return -EINVAL;
1067     		break;
1068     	}
1069     	
1070     	case VIDIOCPWCSCQUAL:
1071     	{	
1072     		int qual, ret;
1073     
1074     		if (copy_from_user(&qual, arg, sizeof(int)))
1075     			return -EFAULT;
1076     			
1077     		if (qual < 0 || qual > 3)
1078     			return -EINVAL;
1079     		ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, qual, pdev->vsnapshot);
1080     		if (ret < 0)
1081     			return ret;
1082     		pdev->vcompression = qual;
1083     		break;
1084     	}
1085     	
1086     	case VIDIOCPWCGCQUAL:
1087     	{
1088     		if (copy_to_user(arg, &pdev->vcompression, sizeof(int)))
1089     			return -EFAULT;
1090     		break;
1091     	}
1092     
1093     	case VIDIOCPWCSAGC:
1094     	{
1095     		int agc;
1096     		
1097     		if (copy_from_user(&agc, arg, sizeof(agc)))
1098     			return -EFAULT;	
1099     		else {
1100     			if (pwc_set_agc(pdev, agc < 0 ? 1 : 0, agc))
1101     				return -EINVAL;
1102     		}
1103     		break;
1104     	}
1105     	
1106     	case VIDIOCPWCGAGC:
1107     	{
1108     		int agc;
1109     		
1110     		if (pwc_get_agc(pdev, &agc))
1111     			return -EINVAL;
1112     		if (copy_to_user(arg, &agc, sizeof(agc)))
1113     			return -EFAULT;
1114     		break;
1115     	}
1116     	
1117     	case VIDIOCPWCSSHUTTER:
1118     	{
1119     		int shutter_speed, ret;
1120     
1121     		if (copy_from_user(&shutter_speed, arg, sizeof(shutter_speed)))
1122     			return -EFAULT;
1123     		else {
1124     			ret = pwc_set_shutter_speed(pdev, shutter_speed < 0 ? 1 : 0, shutter_speed);
1125     			if (ret < 0)
1126     				return ret;
1127     		}
1128     		break;
1129     	}
1130     	
1131     
1132      /* ************************************************* */
1133      /* Begin of Add-Ons for color compensation           */
1134     
1135             case VIDIOCPWCSAWB:
1136     	{
1137     		struct pwc_whitebalance wb;
1138     		int ret;
1139     		
1140     		if (copy_from_user(&wb, arg, sizeof(wb)))
1141     			return -EFAULT;
1142     	
1143     		ret = pwc_set_awb(pdev, wb.mode);
1144     		if (ret >= 0 && wb.mode == PWC_WB_MANUAL) {
1145     			pwc_set_red_gain(pdev, wb.manual_red);
1146     			pwc_set_blue_gain(pdev, wb.manual_blue);
1147     		}
1148     		break;
1149     	}
1150     
1151     	case VIDIOCPWCGAWB:
1152     	{
1153     		struct pwc_whitebalance wb;
1154     		
1155     		memset(&wb, 0, sizeof(wb));
1156     		wb.mode = pwc_get_awb(pdev);
1157     		if (wb.mode < 0)
1158     			return -EINVAL;
1159     		wb.manual_red = pwc_get_red_gain(pdev);
1160     		wb.manual_blue = pwc_get_blue_gain(pdev);
1161     		if (wb.mode == PWC_WB_AUTO) {
1162     			wb.read_red = pwc_read_red_gain(pdev);
1163     			wb.read_blue = pwc_read_blue_gain(pdev);
1164     		}
1165     		break;
1166     	}
1167     
1168             case VIDIOCPWCSLED:
1169     	{
1170     	    int led, ret;
1171     	    if (copy_from_user(&led,arg,sizeof(led)))
1172     		return -EFAULT;
1173     	    else {
1174     		/* ret = pwc_set_led(pdev, led); */
1175     		ret = 0;
1176     		if (ret<0)
1177     		    return ret;
1178     	    }
1179     	    break;
1180     	}
1181     
1182     
1183     
1184     	case VIDIOCPWCGLED:
1185     	{
1186     		int led;
1187     		
1188     		led = pwc_get_led(pdev); 
1189     		if (led < 0)
1190     			return -EINVAL;
1191     		if (copy_to_user(arg, &led, sizeof(led)))
1192     			return -EFAULT;
1193     		break;
1194     	}
1195     
1196      /* End of Add-Ons                                    */
1197      /* ************************************************* */
1198     
1199     	default:
1200     		return -ENOIOCTLCMD;
1201     		break;
1202     	}
1203     	return 0;
1204     }
1205     
1206     #endif
1207     
1208     
1209     
1210     
1211