VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / usb / media / vicam.c
1 /*
2  * USB ViCam WebCam driver
3  * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
4  *                    Christopher L Cheney (ccheney@cheney.cx),
5  *                    Pavel Machek (pavel@suse.cz),
6  *                    John Tyner (jtyner@cs.ucr.edu),
7  *                    Monroe Williams (monroe@pobox.com)
8  *
9  * Supports 3COM HomeConnect PC Digital WebCam
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * This source code is based heavily on the CPiA webcam driver which was
26  * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
27  *
28  * Portions of this code were also copied from usbvideo.c
29  *
30  * Special thanks to the the whole team at Sourceforge for help making
31  * this driver become a reality.  Notably:
32  * Andy Armstrong who reverse engineered the color encoding and
33  * Pavel Machek and Chris Cheney who worked on reverse engineering the
34  *    camera controls and wrote the first generation driver.
35  */
36
37 #include <linux/kernel.h>
38 #include <linux/module.h>
39 #include <linux/init.h>
40 #include <linux/videodev.h>
41 #include <linux/usb.h>
42 #include <linux/vmalloc.h>
43 #include <linux/slab.h>
44 #include <linux/proc_fs.h>
45 #include "usbvideo.h"
46
47 // #define VICAM_DEBUG
48
49 #ifdef VICAM_DEBUG
50 #define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
51 #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
52 #else
53 #define DBG(fmn,args...) do {} while(0)
54 #endif
55
56 #define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
57 #define DRIVER_DESC             "ViCam WebCam Driver"
58
59 /* Define these values to match your device */
60 #define USB_VICAM_VENDOR_ID     0x04c1
61 #define USB_VICAM_PRODUCT_ID    0x009d
62
63 #define VICAM_BYTES_PER_PIXEL   3
64 #define VICAM_MAX_READ_SIZE     (512*242+128)
65 #define VICAM_MAX_FRAME_SIZE    (VICAM_BYTES_PER_PIXEL*320*240)
66 #define VICAM_FRAMES            2
67
68 #define VICAM_HEADER_SIZE       64
69
70 #define clamp( x, l, h )        max_t( __typeof__( x ),         \
71                                        ( l ),                   \
72                                        min_t( __typeof__( x ),  \
73                                               ( h ),            \
74                                               ( x ) ) )
75
76 /* Not sure what all the bytes in these char
77  * arrays do, but they're necessary to make
78  * the camera work.
79  */
80
81 static unsigned char setup1[] = {
82         0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67,
83         0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00,
84         0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17,
85         0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00,
86         0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
87 };
88
89 static unsigned char setup2[] = {
90         0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00,
91         0x00, 0x00
92 };
93
94 static unsigned char setup3[] = {
95         0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00
96 };
97
98 static unsigned char setup4[] = {
99         0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07,
100         0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00,
101         0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00,
102         0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07,
103         0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00,
104         0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00,
105         0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07,
106         0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF,
107         0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0,
108         0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07,
109         0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00,
110         0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0,
111         0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1,
112         0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09,
113         0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00,
114         0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF,
115         0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02,
116         0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00,
117         0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF,
118         0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00,
119         0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00,
120         0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05,
121         0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA,
122         0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06,
123         0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF,
124         0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05,
125         0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01,
126         0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09,
127         0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06,
128         0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05,
129         0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA,
130         0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05,
131         0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
132         0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00,
133         0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF,
134         0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00,
135         0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0,
136         0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06,
137         0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00,
138         0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07,
139         0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF,
140         0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00,
141         0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
142         0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57,
143         0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57,
144         0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00,
145         0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0,
146         0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B,
147         0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06,
148         0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06,
149         0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E,
150         0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00,
151         0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05,
152         0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00,
153         0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
154         0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF,
155         0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0,
156         0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
157         0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05,
158         0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF,
159         0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0,
160         0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07,
161         0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07,
162         0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF,
163         0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF,
164         0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
165         0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
166         0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1,
167         0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
168         0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00,
169         0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07,
170         0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07,
171         0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07,
172         0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00,
173         0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06,
174         0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67,
175         0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8,
176         0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0,
177         0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF,
178         0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02,
179         0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
180         0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06,
181         0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05,
182         0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
183         0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00,
184         0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06,
185         0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
186         0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05,
187         0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05,
188         0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
189         0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04,
190         0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF,
191         0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06,
192         0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
193         0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00,
194         0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05,
195         0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07,
196         0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07,
197         0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07,
198         0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF,
199         0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07,
200         0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06,
201         0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05,
202         0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07,
203         0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00,
204         0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00,
205         0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77,
206         0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04,
207         0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0,
208         0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1,
209         0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07,
210         0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF,
211         0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
212         0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
213         0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
214         0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77,
215         0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1,
216         0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07,
217         0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF,
218         0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06,
219         0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
220         0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07,
221         0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07,
222         0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00,
223         0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00,
224         0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
225         0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
226         0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F,
227         0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00,
228         0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00,
229         0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA,
230         0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
231         0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06,
232         0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF,
233         0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B,
234         0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
235         0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09,
236         0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05,
237         0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07,
238         0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00,
239         0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF,
240         0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05,
241         0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00,
242         0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00,
243         0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05,
244         0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05,
245         0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00,
246         0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF,
247         0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09,
248         0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
249         0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1,
250         0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00,
251         0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05,
252         0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00,
253         0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00,
254         0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05,
255         0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0,
256         0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67,
257         0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87,
258         0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9,
259         0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1,
260         0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF,
261         0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00,
262         0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0,
263         0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87,
264         0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
265         0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67,
266         0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
267         0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
268         0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67,
269         0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
270         0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
271         0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
272         0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00,
273         0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF,
274         0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
275         0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
276         0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09,
277         0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
278         0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA,
279         0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87,
280         0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
281         0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
282         0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
283         0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
284         0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02,
285         0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09,
286         0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
287         0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x00,
288         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
289         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309         0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 };
311
312 static unsigned char setup5[] = {
313         0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00,
314         0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00,
315         0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00,
316         0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00,
317         0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00,
318         0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00,
319         0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00,
320         0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01,
321         0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01,
322         0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01,
323         0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01,
324         0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01,
325         0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01,
326         0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01,
327         0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01,
328         0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02,
329         0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02,
330         0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02,
331         0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02,
332         0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02,
333         0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02,
334         0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02,
335         0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02,
336         0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03,
337         0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03,
338         0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03,
339         0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03,
340         0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03,
341         0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03,
342         0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03,
343         0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04,
344         0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04,
345         0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04,
346         0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04,
347         0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04,
348         0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04,
349         0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04,
350         0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05,
351         0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
352 };
353
354 static unsigned long kvirt_to_pa(unsigned long adr)
355 {
356         unsigned long kva, ret;
357
358         kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
359         kva |= adr & (PAGE_SIZE-1); /* restore the offset */
360         ret = __pa(kva);
361         return ret;
362 }
363
364 /* rvmalloc / rvfree copied from usbvideo.c
365  *
366  * Not sure why these are not yet non-statics which I can reference through
367  * usbvideo.h the same as it is in 2.4.20.  I bet this will get fixed sometime
368  * in the future.
369  * 
370 */
371 static void *rvmalloc(unsigned long size)
372 {
373         void *mem;
374         unsigned long adr;
375
376         size = PAGE_ALIGN(size);
377         mem = vmalloc_32(size);
378         if (!mem)
379                 return NULL;
380
381         memset(mem, 0, size); /* Clear the ram out, no junk to the user */
382         adr = (unsigned long) mem;
383         while (size > 0) {
384                 SetPageReserved(vmalloc_to_page((void *)adr));
385                 adr += PAGE_SIZE;
386                 size -= PAGE_SIZE;
387         }
388
389         return mem;
390 }
391
392 static void rvfree(void *mem, unsigned long size)
393 {
394         unsigned long adr;
395
396         if (!mem)
397                 return;
398
399         adr = (unsigned long) mem;
400         while ((long) size > 0) {
401                 ClearPageReserved(vmalloc_to_page((void *)adr));
402                 adr += PAGE_SIZE;
403                 size -= PAGE_SIZE;
404         }
405         vfree(mem);
406 }
407
408 struct vicam_camera {
409         u16 shutter_speed;      // capture shutter speed
410         u16 gain;               // capture gain
411
412         u8 *raw_image;          // raw data captured from the camera
413         u8 *framebuf;           // processed data in RGB24 format
414         u8 *cntrlbuf;           // area used to send control msgs
415
416         struct video_device vdev;       // v4l video device
417         struct usb_device *udev;        // usb device
418
419         /* guard against simultaneous accesses to the camera */
420         struct semaphore cam_lock;
421
422         int is_initialized;
423         u8 open_count;
424         u8 bulkEndpoint;
425         int needsDummyRead;
426
427 #if defined(CONFIG_VIDEO_PROC_FS)
428         struct proc_dir_entry *proc_dir;
429 #endif
430
431 };
432
433 static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
434 static void vicam_disconnect(struct usb_interface *intf);
435 static void read_frame(struct vicam_camera *cam, int framenum);
436 static void vicam_decode_color(const u8 *, u8 *);
437
438 static int __send_control_msg(struct vicam_camera *cam,
439                               u8 request,
440                               u16 value,
441                               u16 index,
442                               unsigned char *cp,
443                               u16 size)
444 {
445         int status;
446
447         /* cp must be memory that has been allocated by kmalloc */
448
449         status = usb_control_msg(cam->udev,
450                                  usb_sndctrlpipe(cam->udev, 0),
451                                  request,
452                                  USB_DIR_OUT | USB_TYPE_VENDOR |
453                                  USB_RECIP_DEVICE, value, index,
454                                  cp, size, HZ);
455
456         status = min(status, 0);
457
458         if (status < 0) {
459                 printk(KERN_INFO "Failed sending control message, error %d.\n",
460                        status);
461         }
462
463         return status;
464 }
465
466 static int send_control_msg(struct vicam_camera *cam,
467                             u8 request,
468                             u16 value,
469                             u16 index,
470                             unsigned char *cp,
471                             u16 size)
472 {
473         int status = -ENODEV;
474         down(&cam->cam_lock);
475         if (cam->udev) {
476                 status = __send_control_msg(cam, request, value,
477                                             index, cp, size);
478         }
479         up(&cam->cam_lock);
480         return status;
481 }
482 static int
483 initialize_camera(struct vicam_camera *cam)
484 {
485         const struct {
486                 u8 *data;
487                 u32 size;
488         } firmware[] = {
489                 { .data = setup1, .size = sizeof(setup1) },
490                 { .data = setup2, .size = sizeof(setup2) },
491                 { .data = setup3, .size = sizeof(setup3) },
492                 { .data = setup4, .size = sizeof(setup4) },
493                 { .data = setup5, .size = sizeof(setup5) },
494                 { .data = setup3, .size = sizeof(setup3) },
495                 { .data = NULL, .size = 0 }
496         };
497
498         int err, i;
499
500         for (i = 0, err = 0; firmware[i].data && !err; i++) {
501                 memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
502
503                 err = send_control_msg(cam, 0xff, 0, 0,
504                                        cam->cntrlbuf, firmware[i].size);
505         }
506
507         return err;
508 }
509
510 static int
511 set_camera_power(struct vicam_camera *cam, int state)
512 {
513         int status;
514
515         if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
516                 return status;
517
518         if (state) {
519                 send_control_msg(cam, 0x55, 1, 0, NULL, 0);
520         }
521
522         return 0;
523 }
524
525 static int
526 vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
527 {
528         void __user *user_arg = (void __user *)arg;
529         struct vicam_camera *cam = file->private_data;
530         int retval = 0;
531
532         if (!cam)
533                 return -ENODEV;
534
535         switch (ioctlnr) {
536                 /* query capabilities */
537         case VIDIOCGCAP:
538                 {
539                         struct video_capability b;
540
541                         DBG("VIDIOCGCAP\n");
542                         memset(&b, 0, sizeof(b));
543                         strcpy(b.name, "ViCam-based Camera");
544                         b.type = VID_TYPE_CAPTURE;
545                         b.channels = 1;
546                         b.audios = 0;
547                         b.maxwidth = 320;       /* VIDEOSIZE_CIF */
548                         b.maxheight = 240;
549                         b.minwidth = 320;       /* VIDEOSIZE_48_48 */
550                         b.minheight = 240;
551
552                         if (copy_to_user(user_arg, &b, sizeof(b)))
553                                 retval = -EFAULT;
554
555                         break;
556                 }
557                 /* get/set video source - we are a camera and nothing else */
558         case VIDIOCGCHAN:
559                 {
560                         struct video_channel v;
561
562                         DBG("VIDIOCGCHAN\n");
563                         if (copy_from_user(&v, user_arg, sizeof(v))) {
564                                 retval = -EFAULT;
565                                 break;
566                         }
567                         if (v.channel != 0) {
568                                 retval = -EINVAL;
569                                 break;
570                         }
571
572                         v.channel = 0;
573                         strcpy(v.name, "Camera");
574                         v.tuners = 0;
575                         v.flags = 0;
576                         v.type = VIDEO_TYPE_CAMERA;
577                         v.norm = 0;
578
579                         if (copy_to_user(user_arg, &v, sizeof(v)))
580                                 retval = -EFAULT;
581                         break;
582                 }
583
584         case VIDIOCSCHAN:
585                 {
586                         int v;
587
588                         if (copy_from_user(&v, user_arg, sizeof(v)))
589                                 retval = -EFAULT;
590                         DBG("VIDIOCSCHAN %d\n", v);
591
592                         if (retval == 0 && v != 0)
593                                 retval = -EINVAL;
594
595                         break;
596                 }
597
598                 /* image properties */
599         case VIDIOCGPICT:
600                 {
601                         struct video_picture vp;
602                         DBG("VIDIOCGPICT\n");
603                         memset(&vp, 0, sizeof (struct video_picture));
604                         vp.brightness = cam->gain << 8;
605                         vp.depth = 24;
606                         vp.palette = VIDEO_PALETTE_RGB24;
607                         if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
608                                 retval = -EFAULT;
609                         break;
610                 }
611
612         case VIDIOCSPICT:
613                 {
614                         struct video_picture vp;
615                         
616                         if (copy_from_user(&vp, user_arg, sizeof(vp))) {
617                                 retval = -EFAULT;
618                                 break;
619                         }
620                         
621                         DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
622                             vp.palette);
623
624                         cam->gain = vp.brightness >> 8;
625
626                         if (vp.depth != 24
627                             || vp.palette != VIDEO_PALETTE_RGB24)
628                                 retval = -EINVAL;
629
630                         break;
631                 }
632
633                 /* get/set capture window */
634         case VIDIOCGWIN:
635                 {
636                         struct video_window vw;
637                         vw.x = 0;
638                         vw.y = 0;
639                         vw.width = 320;
640                         vw.height = 240;
641                         vw.chromakey = 0;
642                         vw.flags = 0;
643                         vw.clips = NULL;
644                         vw.clipcount = 0;
645
646                         DBG("VIDIOCGWIN\n");
647
648                         if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
649                                 retval = -EFAULT;
650
651                         // I'm not sure what the deal with a capture window is, it is very poorly described
652                         // in the doc.  So I won't support it now.
653                         break;
654                 }
655
656         case VIDIOCSWIN:
657                 {
658
659                         struct video_window vw;
660
661                         if (copy_from_user(&vw, user_arg, sizeof(vw))) {
662                                 retval = -EFAULT;
663                                 break;
664                         }
665
666                         DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
667                         
668                         if ( vw.width != 320 || vw.height != 240 )
669                                 retval = -EFAULT;
670
671                         break;
672                 }
673
674                 /* mmap interface */
675         case VIDIOCGMBUF:
676                 {
677                         struct video_mbuf vm;
678                         int i;
679
680                         DBG("VIDIOCGMBUF\n");
681                         memset(&vm, 0, sizeof (vm));
682                         vm.size =
683                             VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
684                         vm.frames = VICAM_FRAMES;
685                         for (i = 0; i < VICAM_FRAMES; i++)
686                                 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
687
688                         if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
689                                 retval = -EFAULT;
690
691                         break;
692                 }
693
694         case VIDIOCMCAPTURE:
695                 {
696                         struct video_mmap vm;
697                         // int video_size;
698
699                         if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
700                                 retval = -EFAULT;
701                                 break;
702                         }
703
704                         DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
705
706                         if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
707                                 retval = -EINVAL;
708
709                         // in theory right here we'd start the image capturing
710                         // (fill in a bulk urb and submit it asynchronously)
711                         //
712                         // Instead we're going to do a total hack job for now and
713                         // retrieve the frame in VIDIOCSYNC
714
715                         break;
716                 }
717
718         case VIDIOCSYNC:
719                 {
720                         int frame;
721
722                         if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
723                                 retval = -EFAULT;
724                                 break;
725                         }
726                         DBG("VIDIOCSYNC: %d\n", frame);
727
728                         read_frame(cam, frame);
729                         vicam_decode_color(cam->raw_image,
730                                            cam->framebuf +
731                                            frame * VICAM_MAX_FRAME_SIZE );
732
733                         break;
734                 }
735
736                 /* pointless to implement overlay with this camera */
737         case VIDIOCCAPTURE:
738         case VIDIOCGFBUF:
739         case VIDIOCSFBUF:
740         case VIDIOCKEY:
741                 retval = -EINVAL;
742                 break;
743
744                 /* tuner interface - we have none */
745         case VIDIOCGTUNER:
746         case VIDIOCSTUNER:
747         case VIDIOCGFREQ:
748         case VIDIOCSFREQ:
749                 retval = -EINVAL;
750                 break;
751
752                 /* audio interface - we have none */
753         case VIDIOCGAUDIO:
754         case VIDIOCSAUDIO:
755                 retval = -EINVAL;
756                 break;
757         default:
758                 retval = -ENOIOCTLCMD;
759                 break;
760         }
761
762         return retval;
763 }
764
765 static int
766 vicam_open(struct inode *inode, struct file *file)
767 {
768         struct video_device *dev = video_devdata(file);
769         struct vicam_camera *cam =
770             (struct vicam_camera *) dev->priv;
771         DBG("open\n");
772
773         if (!cam) {
774                 printk(KERN_ERR
775                        "vicam video_device improperly initialized");
776         }
777
778         /* the videodev_lock held above us protects us from
779          * simultaneous opens...for now. we probably shouldn't
780          * rely on this fact forever.
781          */
782
783         if (cam->open_count > 0) {
784                 printk(KERN_INFO
785                        "vicam_open called on already opened camera");
786                 return -EBUSY;
787         }
788
789         cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
790         if (!cam->raw_image) {
791                 return -ENOMEM;
792         }
793
794         cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
795         if (!cam->framebuf) {
796                 kfree(cam->raw_image);
797                 return -ENOMEM;
798         }
799
800         cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
801         if (!cam->cntrlbuf) {
802                 kfree(cam->raw_image);
803                 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
804                 return -ENOMEM;
805         }
806
807         // First upload firmware, then turn the camera on
808
809         if (!cam->is_initialized) {
810                 initialize_camera(cam);
811
812                 cam->is_initialized = 1;
813         }
814
815         set_camera_power(cam, 1);
816
817         cam->needsDummyRead = 1;
818         cam->open_count++;
819
820         file->private_data = cam;       
821         
822         return 0;
823 }
824
825 static int 
826 vicam_close(struct inode *inode, struct file *file)
827 {
828         struct vicam_camera *cam = file->private_data;
829         int open_count;
830         struct usb_device *udev;
831
832         DBG("close\n");
833
834         /* it's not the end of the world if
835          * we fail to turn the camera off.
836          */
837
838         set_camera_power(cam, 0);
839
840         kfree(cam->raw_image);
841         rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
842         kfree(cam->cntrlbuf);
843
844         down(&cam->cam_lock);
845
846         cam->open_count--;
847         open_count = cam->open_count;
848         udev = cam->udev;
849
850         up(&cam->cam_lock);
851
852         if (!open_count && !udev) {
853                 kfree(cam);
854         }
855
856         return 0;
857 }
858
859 static void vicam_decode_color(const u8 *data, u8 *rgb)
860 {
861         /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
862          * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
863          */
864
865         int i, prevY, nextY;
866
867         prevY = 512;
868         nextY = 512;
869
870         data += VICAM_HEADER_SIZE;
871
872         for( i = 0; i < 240; i++, data += 512 ) {
873                 const int y = ( i * 242 ) / 240;
874
875                 int j, prevX, nextX;
876                 int Y, Cr, Cb;
877
878                 if ( y == 242 - 1 ) {
879                         nextY = -512;
880                 }
881
882                 prevX = 1;
883                 nextX = 1;
884
885                 for ( j = 0; j < 320; j++, rgb += 3 ) {
886                         const int x = ( j * 512 ) / 320;
887                         const u8 * const src = &data[x];
888
889                         if ( x == 512 - 1 ) {
890                                 nextX = -1;
891                         }
892
893                         Cr = ( src[prevX] - src[0] ) +
894                                 ( src[nextX] - src[0] );
895                         Cr /= 2;
896
897                         Cb = ( src[prevY] - src[prevX + prevY] ) +
898                                 ( src[prevY] - src[nextX + prevY] ) +
899                                 ( src[nextY] - src[prevX + nextY] ) +
900                                 ( src[nextY] - src[nextX + nextY] );
901                         Cb /= 4;
902
903                         Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
904
905                         if ( i & 1 ) {
906                                 int Ct = Cr;
907                                 Cr = Cb;
908                                 Cb = Ct;
909                         }
910
911                         if ( ( x ^ i ) & 1 ) {
912                                 Cr = -Cr;
913                                 Cb = -Cb;
914                         }
915
916                         rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
917                                         500 ) / 900, 0, 255 );
918                         rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
919                                           ( 813 * Cr ) ) +
920                                           500 ) / 1000, 0, 255 );
921                         rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
922                                         500 ) / 1300, 0, 255 );
923
924                         prevX = -1;
925                 }
926
927                 prevY = -512;
928         }
929 }
930
931 static void
932 read_frame(struct vicam_camera *cam, int framenum)
933 {
934         unsigned char *request = cam->cntrlbuf;
935         int realShutter;
936         int n;
937         int actual_length;
938
939         if (cam->needsDummyRead) {
940                 cam->needsDummyRead = 0;
941                 read_frame(cam, framenum);
942         }
943
944         memset(request, 0, 16);
945         request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
946
947         request[1] = 0; // 512x242 capture
948
949         request[2] = 0x90;      // the function of these two bytes
950         request[3] = 0x07;      // is not yet understood
951
952         if (cam->shutter_speed > 60) {
953                 // Short exposure
954                 realShutter =
955                     ((-15631900 / cam->shutter_speed) + 260533) / 1000;
956                 request[4] = realShutter & 0xFF;
957                 request[5] = (realShutter >> 8) & 0xFF;
958                 request[6] = 0x03;
959                 request[7] = 0x01;
960         } else {
961                 // Long exposure
962                 realShutter = 15600 / cam->shutter_speed - 1;
963                 request[4] = 0;
964                 request[5] = 0;
965                 request[6] = realShutter & 0xFF;
966                 request[7] = realShutter >> 8;
967         }
968
969         // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
970         request[8] = 0;
971         // bytes 9-15 do not seem to affect exposure or image quality
972
973         down(&cam->cam_lock);
974
975         if (!cam->udev) {
976                 goto done;
977         }
978
979         n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
980
981         if (n < 0) {
982                 printk(KERN_ERR
983                        " Problem sending frame capture control message");
984                 goto done;
985         }
986
987         n = usb_bulk_msg(cam->udev,
988                          usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
989                          cam->raw_image,
990                          512 * 242 + 128, &actual_length, HZ*10);
991
992         if (n < 0) {
993                 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
994                        n);
995         }
996
997  done:
998         up(&cam->cam_lock);
999 }
1000
1001 static ssize_t
1002 vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
1003 {
1004         struct vicam_camera *cam = file->private_data;
1005
1006         DBG("read %d bytes.\n", (int) count);
1007
1008         if (*ppos >= VICAM_MAX_FRAME_SIZE) {
1009                 *ppos = 0;
1010                 return 0;
1011         }
1012
1013         if (*ppos == 0) {
1014                 read_frame(cam, 0);
1015                 vicam_decode_color(cam->raw_image,
1016                                    cam->framebuf +
1017                                    0 * VICAM_MAX_FRAME_SIZE);
1018         }
1019
1020         count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
1021
1022         if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
1023                 count = -EFAULT;
1024         } else {
1025                 *ppos += count;
1026         }
1027
1028         if (count == VICAM_MAX_FRAME_SIZE) {
1029                 *ppos = 0;
1030         }
1031
1032         return count;
1033 }
1034
1035
1036 static int
1037 vicam_mmap(struct file *file, struct vm_area_struct *vma)
1038 {
1039         // TODO: allocate the raw frame buffer if necessary
1040         unsigned long page, pos;
1041         unsigned long start = vma->vm_start;
1042         unsigned long size  = vma->vm_end-vma->vm_start;
1043         struct vicam_camera *cam = file->private_data;
1044
1045         if (!cam)
1046                 return -ENODEV;
1047
1048         DBG("vicam_mmap: %ld\n", size);
1049
1050         /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1051          * to the size the application requested for mmap and it was screwing apps up.
1052          if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1053          return -EINVAL;
1054          */
1055
1056         pos = (unsigned long)cam->framebuf;
1057         while (size > 0) {
1058                 page = kvirt_to_pa(pos);
1059                 if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1060                         return -EAGAIN;
1061
1062                 start += PAGE_SIZE;
1063                 pos += PAGE_SIZE;
1064                 if (size > PAGE_SIZE)
1065                         size -= PAGE_SIZE;
1066                 else
1067                         size = 0;
1068         }
1069
1070         return 0;
1071 }
1072
1073 #if defined(CONFIG_VIDEO_PROC_FS)
1074
1075 static struct proc_dir_entry *vicam_proc_root = NULL;
1076
1077 static int vicam_read_helper(char *page, char **start, off_t off,
1078                                 int count, int *eof, int value)
1079 {
1080         char *out = page;
1081         int len;
1082
1083         out += sprintf(out, "%d",value);
1084
1085         len = out - page;
1086         len -= off;
1087         if (len < count) {
1088                 *eof = 1;
1089                 if (len <= 0)
1090                         return 0;
1091         } else
1092                 len = count;
1093
1094         *start = page + off;
1095         return len;
1096 }
1097
1098 static int vicam_read_proc_shutter(char *page, char **start, off_t off,
1099                                 int count, int *eof, void *data)
1100 {
1101         return vicam_read_helper(page,start,off,count,eof,
1102                                 ((struct vicam_camera *)data)->shutter_speed);
1103 }
1104
1105 static int vicam_read_proc_gain(char *page, char **start, off_t off,
1106                                 int count, int *eof, void *data)
1107 {
1108         return vicam_read_helper(page,start,off,count,eof,
1109                                 ((struct vicam_camera *)data)->gain);
1110 }
1111
1112 static int
1113 vicam_write_proc_shutter(struct file *file, const char *buffer,
1114                          unsigned long count, void *data)
1115 {
1116         u16 stmp;
1117         char kbuf[8];
1118         struct vicam_camera *cam = (struct vicam_camera *) data;
1119
1120         if (count > 6)
1121                 return -EINVAL;
1122
1123         if (copy_from_user(kbuf, buffer, count))
1124                 return -EFAULT;
1125
1126         stmp = (u16) simple_strtoul(kbuf, NULL, 10);
1127         if (stmp < 4 || stmp > 32000)
1128                 return -EINVAL;
1129
1130         cam->shutter_speed = stmp;
1131
1132         return count;
1133 }
1134
1135 static int
1136 vicam_write_proc_gain(struct file *file, const char *buffer,
1137                       unsigned long count, void *data)
1138 {
1139         u16 gtmp;
1140         char kbuf[8];
1141
1142         struct vicam_camera *cam = (struct vicam_camera *) data;
1143
1144         if (count > 4)
1145                 return -EINVAL;
1146
1147         if (copy_from_user(kbuf, buffer, count))
1148                 return -EFAULT;
1149
1150         gtmp = (u16) simple_strtoul(kbuf, NULL, 10);
1151         if (gtmp > 255)
1152                 return -EINVAL;
1153         cam->gain = gtmp;
1154
1155         return count;
1156 }
1157
1158 static void
1159 vicam_create_proc_root(void)
1160 {
1161         vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
1162
1163         if (vicam_proc_root)
1164                 vicam_proc_root->owner = THIS_MODULE;
1165         else
1166                 printk(KERN_ERR
1167                        "could not create /proc entry for vicam!");
1168 }
1169
1170 static void
1171 vicam_destroy_proc_root(void)
1172 {
1173         if (vicam_proc_root)
1174                 remove_proc_entry("video/vicam", 0);
1175 }
1176
1177 static void
1178 vicam_create_proc_entry(struct vicam_camera *cam)
1179 {
1180         char name[64];
1181         struct proc_dir_entry *ent;
1182
1183         DBG(KERN_INFO "vicam: creating proc entry\n");
1184
1185         if (!vicam_proc_root || !cam) {
1186                 printk(KERN_INFO
1187                        "vicam: could not create proc entry, %s pointer is null.\n",
1188                        (!cam ? "camera" : "root"));
1189                 return;
1190         }
1191
1192         sprintf(name, "video%d", cam->vdev.minor);
1193
1194         cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root);
1195
1196         if ( !cam->proc_dir )
1197                 return; // FIXME: We should probably return an error here
1198         
1199         ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
1200                                 cam->proc_dir);
1201         if (ent) {
1202                 ent->data = cam;
1203                 ent->read_proc = vicam_read_proc_shutter;
1204                 ent->write_proc = vicam_write_proc_shutter;
1205                 ent->size = 64;
1206         }
1207
1208         ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
1209                                 cam->proc_dir);
1210         if (ent) {
1211                 ent->data = cam;
1212                 ent->read_proc = vicam_read_proc_gain;
1213                 ent->write_proc = vicam_write_proc_gain;
1214                 ent->size = 64;
1215         }
1216 }
1217
1218 static void
1219 vicam_destroy_proc_entry(void *ptr)
1220 {
1221         struct vicam_camera *cam = (struct vicam_camera *) ptr;
1222         char name[16];
1223
1224         if ( !cam->proc_dir )
1225                 return;
1226
1227         sprintf(name, "video%d", cam->vdev.minor);
1228         remove_proc_entry("shutter", cam->proc_dir);
1229         remove_proc_entry("gain", cam->proc_dir);
1230         remove_proc_entry(name,vicam_proc_root);
1231         cam->proc_dir = NULL;
1232
1233 }
1234
1235 #else
1236 static inline void vicam_create_proc_root(void) { }
1237 static inline void vicam_destroy_proc_root(void) { }
1238 static inline void vicam_create_proc_entry(struct vicam_camera *cam) { }
1239 static inline void vicam_destroy_proc_entry(void *ptr) { }
1240 #endif
1241
1242 static struct file_operations vicam_fops = {
1243         .owner          = THIS_MODULE,
1244         .open           = vicam_open,
1245         .release        = vicam_close,
1246         .read           = vicam_read,
1247         .mmap           = vicam_mmap,
1248         .ioctl          = vicam_ioctl,
1249         .llseek         = no_llseek,
1250 };
1251
1252 static struct video_device vicam_template = {
1253         .owner          = THIS_MODULE,
1254         .name           = "ViCam-based USB Camera",
1255         .type           = VID_TYPE_CAPTURE,
1256         .hardware       = VID_HARDWARE_VICAM,
1257         .fops           = &vicam_fops,
1258         .minor          = -1,
1259 };
1260
1261 /* table of devices that work with this driver */
1262 static struct usb_device_id vicam_table[] = {
1263         {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1264         {}                      /* Terminating entry */
1265 };
1266
1267 MODULE_DEVICE_TABLE(usb, vicam_table);
1268
1269 static struct usb_driver vicam_driver = {
1270         .owner          = THIS_MODULE,
1271         .name           = "vicam",
1272         .probe          = vicam_probe,
1273         .disconnect     = vicam_disconnect,
1274         .id_table       = vicam_table
1275 };
1276
1277 /**
1278  *      vicam_probe
1279  *      @intf: the interface
1280  *      @id: the device id
1281  *
1282  *      Called by the usb core when a new device is connected that it thinks
1283  *      this driver might be interested in.
1284  */
1285 static int
1286 vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
1287 {
1288         struct usb_device *dev = interface_to_usbdev(intf);
1289         int bulkEndpoint = 0;
1290         const struct usb_host_interface *interface;
1291         const struct usb_endpoint_descriptor *endpoint;
1292         struct vicam_camera *cam;
1293         
1294         /* See if the device offered us matches what we can accept */
1295         if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
1296             (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
1297                 return -ENODEV;
1298         }
1299
1300         printk(KERN_INFO "ViCam based webcam connected\n");
1301
1302         interface = intf->cur_altsetting;
1303
1304         DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1305                interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
1306         endpoint = &interface->endpoint[0].desc;
1307
1308         if ((endpoint->bEndpointAddress & 0x80) &&
1309             ((endpoint->bmAttributes & 3) == 0x02)) {
1310                 /* we found a bulk in endpoint */
1311                 bulkEndpoint = endpoint->bEndpointAddress;
1312         } else {
1313                 printk(KERN_ERR
1314                        "No bulk in endpoint was found ?! (this is bad)\n");
1315         }
1316
1317         if ((cam =
1318              kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1319                 printk(KERN_WARNING
1320                        "could not allocate kernel memory for vicam_camera struct\n");
1321                 return -ENOMEM;
1322         }
1323
1324         memset(cam, 0, sizeof (struct vicam_camera));
1325
1326         cam->shutter_speed = 15;
1327
1328         init_MUTEX(&cam->cam_lock);
1329
1330         memcpy(&cam->vdev, &vicam_template,
1331                sizeof (vicam_template));
1332         cam->vdev.priv = cam;   // sort of a reverse mapping for those functions that get vdev only
1333
1334         cam->udev = dev;
1335         cam->bulkEndpoint = bulkEndpoint;
1336
1337         if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1338                 kfree(cam);
1339                 printk(KERN_WARNING "video_register_device failed\n");
1340                 return -EIO;
1341         }
1342
1343         vicam_create_proc_entry(cam);
1344
1345         printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1346
1347         usb_set_intfdata (intf, cam);
1348         
1349         return 0;
1350 }
1351
1352 static void
1353 vicam_disconnect(struct usb_interface *intf)
1354 {
1355         int open_count;
1356         struct vicam_camera *cam = usb_get_intfdata (intf);
1357         usb_set_intfdata (intf, NULL);
1358
1359         /* we must unregister the device before taking its
1360          * cam_lock. This is because the video open call
1361          * holds the same lock as video unregister. if we
1362          * unregister inside of the cam_lock and open also
1363          * uses the cam_lock, we get deadlock.
1364          */
1365
1366         video_unregister_device(&cam->vdev);
1367
1368         /* stop the camera from being used */
1369
1370         down(&cam->cam_lock);
1371
1372         /* mark the camera as gone */
1373
1374         cam->udev = NULL;
1375
1376         vicam_destroy_proc_entry(cam);
1377
1378         /* the only thing left to do is synchronize with
1379          * our close/release function on who should release
1380          * the camera memory. if there are any users using the
1381          * camera, it's their job. if there are no users,
1382          * it's ours.
1383          */
1384
1385         open_count = cam->open_count;
1386
1387         up(&cam->cam_lock);
1388
1389         if (!open_count) {
1390                 kfree(cam);
1391         }
1392
1393         printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1394 }
1395
1396 /*
1397  */
1398 static int __init
1399 usb_vicam_init(void)
1400 {
1401         int retval;
1402         DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1403         vicam_create_proc_root();
1404         retval = usb_register(&vicam_driver);
1405         if (retval)
1406                 printk(KERN_WARNING "usb_register failed!\n");
1407         return retval;
1408 }
1409
1410 static void __exit
1411 usb_vicam_exit(void)
1412 {
1413         DBG(KERN_INFO
1414                "ViCam-based WebCam driver shutdown\n");
1415
1416         usb_deregister(&vicam_driver);
1417         vicam_destroy_proc_root();
1418 }
1419
1420 module_init(usb_vicam_init);
1421 module_exit(usb_vicam_exit);
1422
1423 MODULE_AUTHOR(DRIVER_AUTHOR);
1424 MODULE_DESCRIPTION(DRIVER_DESC);
1425 MODULE_LICENSE("GPL");