patch-2_6_7-vs1_9_1_12
[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 ul_arg)
527 {
528         void *arg = (void *)ul_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(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, 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(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, 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
608                             (arg, &vp, sizeof (struct video_picture)))
609                                 retval = -EFAULT;
610                         break;
611                 }
612
613         case VIDIOCSPICT:
614                 {
615                         struct video_picture vp;
616                         
617                         if (copy_from_user(&vp, arg, sizeof(vp))) {
618                                 retval = -EFAULT;
619                                 break;
620                         }
621                         
622                         DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
623                             vp.palette);
624
625                         cam->gain = vp.brightness >> 8;
626
627                         if (vp.depth != 24
628                             || vp.palette != VIDEO_PALETTE_RGB24)
629                                 retval = -EINVAL;
630
631                         break;
632                 }
633
634                 /* get/set capture window */
635         case VIDIOCGWIN:
636                 {
637                         struct video_window vw;
638                         vw.x = 0;
639                         vw.y = 0;
640                         vw.width = 320;
641                         vw.height = 240;
642                         vw.chromakey = 0;
643                         vw.flags = 0;
644                         vw.clips = NULL;
645                         vw.clipcount = 0;
646
647                         DBG("VIDIOCGWIN\n");
648
649                         if (copy_to_user
650                             ((void *) arg, (void *) &vw, sizeof (vw)))
651                                 retval = -EFAULT;
652
653                         // I'm not sure what the deal with a capture window is, it is very poorly described
654                         // in the doc.  So I won't support it now.
655                         break;
656                 }
657
658         case VIDIOCSWIN:
659                 {
660
661                         struct video_window vw;
662
663                         if (copy_from_user(&vw, arg, sizeof(vw))) {
664                                 retval = -EFAULT;
665                                 break;
666                         }
667
668                         DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
669                         
670                         if ( vw.width != 320 || vw.height != 240 )
671                                 retval = -EFAULT;
672
673                         break;
674                 }
675
676                 /* mmap interface */
677         case VIDIOCGMBUF:
678                 {
679                         struct video_mbuf vm;
680                         int i;
681
682                         DBG("VIDIOCGMBUF\n");
683                         memset(&vm, 0, sizeof (vm));
684                         vm.size =
685                             VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
686                         vm.frames = VICAM_FRAMES;
687                         for (i = 0; i < VICAM_FRAMES; i++)
688                                 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
689
690                         if (copy_to_user
691                             ((void *) arg, (void *) &vm, sizeof (vm)))
692                                 retval = -EFAULT;
693
694                         break;
695                 }
696
697         case VIDIOCMCAPTURE:
698                 {
699                         struct video_mmap vm;
700                         // int video_size;
701
702                         if (copy_from_user
703                             ((void *) &vm, (void *) arg, sizeof (vm))) {
704                                 retval = -EFAULT;
705                                 break;
706                         }
707
708                         DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
709
710                         if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
711                                 retval = -EINVAL;
712
713                         // in theory right here we'd start the image capturing
714                         // (fill in a bulk urb and submit it asynchronously)
715                         //
716                         // Instead we're going to do a total hack job for now and
717                         // retrieve the frame in VIDIOCSYNC
718
719                         break;
720                 }
721
722         case VIDIOCSYNC:
723                 {
724                         int frame;
725
726                         if (copy_from_user((void *) &frame, arg, sizeof (int))) {
727                                 retval = -EFAULT;
728                                 break;
729                         }
730                         DBG("VIDIOCSYNC: %d\n", frame);
731
732                         read_frame(cam, frame);
733                         vicam_decode_color(cam->raw_image,
734                                            cam->framebuf +
735                                            frame * VICAM_MAX_FRAME_SIZE );
736
737                         break;
738                 }
739
740                 /* pointless to implement overlay with this camera */
741         case VIDIOCCAPTURE:
742         case VIDIOCGFBUF:
743         case VIDIOCSFBUF:
744         case VIDIOCKEY:
745                 retval = -EINVAL;
746                 break;
747
748                 /* tuner interface - we have none */
749         case VIDIOCGTUNER:
750         case VIDIOCSTUNER:
751         case VIDIOCGFREQ:
752         case VIDIOCSFREQ:
753                 retval = -EINVAL;
754                 break;
755
756                 /* audio interface - we have none */
757         case VIDIOCGAUDIO:
758         case VIDIOCSAUDIO:
759                 retval = -EINVAL;
760                 break;
761         default:
762                 retval = -ENOIOCTLCMD;
763                 break;
764         }
765
766         return retval;
767 }
768
769 static int
770 vicam_open(struct inode *inode, struct file *file)
771 {
772         struct video_device *dev = video_devdata(file);
773         struct vicam_camera *cam =
774             (struct vicam_camera *) dev->priv;
775         DBG("open\n");
776
777         if (!cam) {
778                 printk(KERN_ERR
779                        "vicam video_device improperly initialized");
780         }
781
782         /* the videodev_lock held above us protects us from
783          * simultaneous opens...for now. we probably shouldn't
784          * rely on this fact forever.
785          */
786
787         if (cam->open_count > 0) {
788                 printk(KERN_INFO
789                        "vicam_open called on already opened camera");
790                 return -EBUSY;
791         }
792
793         cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
794         if (!cam->raw_image) {
795                 return -ENOMEM;
796         }
797
798         cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
799         if (!cam->framebuf) {
800                 kfree(cam->raw_image);
801                 return -ENOMEM;
802         }
803
804         cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
805         if (!cam->cntrlbuf) {
806                 kfree(cam->raw_image);
807                 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
808                 return -ENOMEM;
809         }
810
811         // First upload firmware, then turn the camera on
812
813         if (!cam->is_initialized) {
814                 initialize_camera(cam);
815
816                 cam->is_initialized = 1;
817         }
818
819         set_camera_power(cam, 1);
820
821         cam->needsDummyRead = 1;
822         cam->open_count++;
823
824         file->private_data = cam;       
825         
826         return 0;
827 }
828
829 static int 
830 vicam_close(struct inode *inode, struct file *file)
831 {
832         struct vicam_camera *cam = file->private_data;
833         int open_count;
834         struct usb_device *udev;
835
836         DBG("close\n");
837
838         /* it's not the end of the world if
839          * we fail to turn the camera off.
840          */
841
842         set_camera_power(cam, 0);
843
844         kfree(cam->raw_image);
845         rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
846         kfree(cam->cntrlbuf);
847
848         down(&cam->cam_lock);
849
850         cam->open_count--;
851         open_count = cam->open_count;
852         udev = cam->udev;
853
854         up(&cam->cam_lock);
855
856         if (!open_count && !udev) {
857                 kfree(cam);
858         }
859
860         return 0;
861 }
862
863 static void vicam_decode_color(const u8 *data, u8 *rgb)
864 {
865         /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
866          * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
867          */
868
869         int i, prevY, nextY;
870
871         prevY = 512;
872         nextY = 512;
873
874         data += VICAM_HEADER_SIZE;
875
876         for( i = 0; i < 240; i++, data += 512 ) {
877                 const int y = ( i * 242 ) / 240;
878
879                 int j, prevX, nextX;
880                 int Y, Cr, Cb;
881
882                 if ( y == 242 - 1 ) {
883                         nextY = -512;
884                 }
885
886                 prevX = 1;
887                 nextX = 1;
888
889                 for ( j = 0; j < 320; j++, rgb += 3 ) {
890                         const int x = ( j * 512 ) / 320;
891                         const u8 * const src = &data[x];
892
893                         if ( x == 512 - 1 ) {
894                                 nextX = -1;
895                         }
896
897                         Cr = ( src[prevX] - src[0] ) +
898                                 ( src[nextX] - src[0] );
899                         Cr /= 2;
900
901                         Cb = ( src[prevY] - src[prevX + prevY] ) +
902                                 ( src[prevY] - src[nextX + prevY] ) +
903                                 ( src[nextY] - src[prevX + nextY] ) +
904                                 ( src[nextY] - src[nextX + nextY] );
905                         Cb /= 4;
906
907                         Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
908
909                         if ( i & 1 ) {
910                                 int Ct = Cr;
911                                 Cr = Cb;
912                                 Cb = Ct;
913                         }
914
915                         if ( ( x ^ i ) & 1 ) {
916                                 Cr = -Cr;
917                                 Cb = -Cb;
918                         }
919
920                         rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
921                                         500 ) / 900, 0, 255 );
922                         rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
923                                           ( 813 * Cr ) ) +
924                                           500 ) / 1000, 0, 255 );
925                         rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
926                                         500 ) / 1300, 0, 255 );
927
928                         prevX = -1;
929                 }
930
931                 prevY = -512;
932         }
933 }
934
935 static void
936 read_frame(struct vicam_camera *cam, int framenum)
937 {
938         unsigned char *request = cam->cntrlbuf;
939         int realShutter;
940         int n;
941         int actual_length;
942
943         if (cam->needsDummyRead) {
944                 cam->needsDummyRead = 0;
945                 read_frame(cam, framenum);
946         }
947
948         memset(request, 0, 16);
949         request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
950
951         request[1] = 0; // 512x242 capture
952
953         request[2] = 0x90;      // the function of these two bytes
954         request[3] = 0x07;      // is not yet understood
955
956         if (cam->shutter_speed > 60) {
957                 // Short exposure
958                 realShutter =
959                     ((-15631900 / cam->shutter_speed) + 260533) / 1000;
960                 request[4] = realShutter & 0xFF;
961                 request[5] = (realShutter >> 8) & 0xFF;
962                 request[6] = 0x03;
963                 request[7] = 0x01;
964         } else {
965                 // Long exposure
966                 realShutter = 15600 / cam->shutter_speed - 1;
967                 request[4] = 0;
968                 request[5] = 0;
969                 request[6] = realShutter & 0xFF;
970                 request[7] = realShutter >> 8;
971         }
972
973         // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
974         request[8] = 0;
975         // bytes 9-15 do not seem to affect exposure or image quality
976
977         down(&cam->cam_lock);
978
979         if (!cam->udev) {
980                 goto done;
981         }
982
983         n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
984
985         if (n < 0) {
986                 printk(KERN_ERR
987                        " Problem sending frame capture control message");
988                 goto done;
989         }
990
991         n = usb_bulk_msg(cam->udev,
992                          usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
993                          cam->raw_image,
994                          512 * 242 + 128, &actual_length, HZ*10);
995
996         if (n < 0) {
997                 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
998                        n);
999         }
1000
1001  done:
1002         up(&cam->cam_lock);
1003 }
1004
1005 static ssize_t
1006 vicam_read( struct file *file, char *buf, size_t count, loff_t *ppos )
1007 {
1008         struct vicam_camera *cam = file->private_data;
1009
1010         DBG("read %d bytes.\n", (int) count);
1011
1012         if (*ppos >= VICAM_MAX_FRAME_SIZE) {
1013                 *ppos = 0;
1014                 return 0;
1015         }
1016
1017         if (*ppos == 0) {
1018                 read_frame(cam, 0);
1019                 vicam_decode_color(cam->raw_image,
1020                                    cam->framebuf +
1021                                    0 * VICAM_MAX_FRAME_SIZE);
1022         }
1023
1024         count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
1025
1026         if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
1027                 count = -EFAULT;
1028         } else {
1029                 *ppos += count;
1030         }
1031
1032         if (count == VICAM_MAX_FRAME_SIZE) {
1033                 *ppos = 0;
1034         }
1035
1036         return count;
1037 }
1038
1039
1040 static int
1041 vicam_mmap(struct file *file, struct vm_area_struct *vma)
1042 {
1043         // TODO: allocate the raw frame buffer if necessary
1044         unsigned long page, pos;
1045         unsigned long start = vma->vm_start;
1046         unsigned long size  = vma->vm_end-vma->vm_start;
1047         struct vicam_camera *cam = file->private_data;
1048
1049         if (!cam)
1050                 return -ENODEV;
1051
1052         DBG("vicam_mmap: %ld\n", size);
1053
1054         /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1055          * to the size the application requested for mmap and it was screwing apps up.
1056          if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1057          return -EINVAL;
1058          */
1059
1060         pos = (unsigned long)cam->framebuf;
1061         while (size > 0) {
1062                 page = kvirt_to_pa(pos);
1063                 if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1064                         return -EAGAIN;
1065
1066                 start += PAGE_SIZE;
1067                 pos += PAGE_SIZE;
1068                 if (size > PAGE_SIZE)
1069                         size -= PAGE_SIZE;
1070                 else
1071                         size = 0;
1072         }
1073
1074         return 0;
1075 }
1076
1077 #if defined(CONFIG_VIDEO_PROC_FS)
1078
1079 static struct proc_dir_entry *vicam_proc_root = NULL;
1080
1081 static int vicam_read_helper(char *page, char **start, off_t off,
1082                                 int count, int *eof, int value)
1083 {
1084         char *out = page;
1085         int len;
1086
1087         out += sprintf(out, "%d",value);
1088
1089         len = out - page;
1090         len -= off;
1091         if (len < count) {
1092                 *eof = 1;
1093                 if (len <= 0)
1094                         return 0;
1095         } else
1096                 len = count;
1097
1098         *start = page + off;
1099         return len;
1100 }
1101
1102 static int vicam_read_proc_shutter(char *page, char **start, off_t off,
1103                                 int count, int *eof, void *data)
1104 {
1105         return vicam_read_helper(page,start,off,count,eof,
1106                                 ((struct vicam_camera *)data)->shutter_speed);
1107 }
1108
1109 static int vicam_read_proc_gain(char *page, char **start, off_t off,
1110                                 int count, int *eof, void *data)
1111 {
1112         return vicam_read_helper(page,start,off,count,eof,
1113                                 ((struct vicam_camera *)data)->gain);
1114 }
1115
1116 static int
1117 vicam_write_proc_shutter(struct file *file, const char *buffer,
1118                          unsigned long count, void *data)
1119 {
1120         u16 stmp;
1121         char kbuf[8];
1122         struct vicam_camera *cam = (struct vicam_camera *) data;
1123
1124         if (count > 6)
1125                 return -EINVAL;
1126
1127         if (copy_from_user(kbuf, buffer, count))
1128                 return -EFAULT;
1129
1130         stmp = (u16) simple_strtoul(kbuf, NULL, 10);
1131         if (stmp < 4 || stmp > 32000)
1132                 return -EINVAL;
1133
1134         cam->shutter_speed = stmp;
1135
1136         return count;
1137 }
1138
1139 static int
1140 vicam_write_proc_gain(struct file *file, const char *buffer,
1141                       unsigned long count, void *data)
1142 {
1143         u16 gtmp;
1144         char kbuf[8];
1145
1146         struct vicam_camera *cam = (struct vicam_camera *) data;
1147
1148         if (count > 4)
1149                 return -EINVAL;
1150
1151         if (copy_from_user(kbuf, buffer, count))
1152                 return -EFAULT;
1153
1154         gtmp = (u16) simple_strtoul(kbuf, NULL, 10);
1155         if (gtmp > 255)
1156                 return -EINVAL;
1157         cam->gain = gtmp;
1158
1159         return count;
1160 }
1161
1162 static void
1163 vicam_create_proc_root(void)
1164 {
1165         vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
1166
1167         if (vicam_proc_root)
1168                 vicam_proc_root->owner = THIS_MODULE;
1169         else
1170                 printk(KERN_ERR
1171                        "could not create /proc entry for vicam!");
1172 }
1173
1174 static void
1175 vicam_destroy_proc_root(void)
1176 {
1177         if (vicam_proc_root)
1178                 remove_proc_entry("video/vicam", 0);
1179 }
1180
1181 static void
1182 vicam_create_proc_entry(struct vicam_camera *cam)
1183 {
1184         char name[64];
1185         struct proc_dir_entry *ent;
1186
1187         DBG(KERN_INFO "vicam: creating proc entry\n");
1188
1189         if (!vicam_proc_root || !cam) {
1190                 printk(KERN_INFO
1191                        "vicam: could not create proc entry, %s pointer is null.\n",
1192                        (!cam ? "camera" : "root"));
1193                 return;
1194         }
1195
1196         sprintf(name, "video%d", cam->vdev.minor);
1197
1198         cam->proc_dir = create_proc_entry(name, S_IFDIR, vicam_proc_root);
1199
1200         if ( !cam->proc_dir )
1201                 return; // FIXME: We should probably return an error here
1202         
1203         ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
1204                                 cam->proc_dir);
1205         if (ent) {
1206                 ent->data = cam;
1207                 ent->read_proc = vicam_read_proc_shutter;
1208                 ent->write_proc = vicam_write_proc_shutter;
1209                 ent->size = 64;
1210         }
1211
1212         ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
1213                                 cam->proc_dir);
1214         if (ent) {
1215                 ent->data = cam;
1216                 ent->read_proc = vicam_read_proc_gain;
1217                 ent->write_proc = vicam_write_proc_gain;
1218                 ent->size = 64;
1219         }
1220 }
1221
1222 static void
1223 vicam_destroy_proc_entry(void *ptr)
1224 {
1225         struct vicam_camera *cam = (struct vicam_camera *) ptr;
1226         char name[16];
1227
1228         if ( !cam->proc_dir )
1229                 return;
1230
1231         sprintf(name, "video%d", cam->vdev.minor);
1232         remove_proc_entry("shutter", cam->proc_dir);
1233         remove_proc_entry("gain", cam->proc_dir);
1234         remove_proc_entry(name,vicam_proc_root);
1235         cam->proc_dir = NULL;
1236
1237 }
1238
1239 #else
1240 static inline void vicam_create_proc_root(void) { }
1241 static inline void vicam_destroy_proc_root(void) { }
1242 static inline void vicam_create_proc_entry(struct vicam_camera *cam) { }
1243 static inline void vicam_destroy_proc_entry(void *ptr) { }
1244 #endif
1245
1246 static struct file_operations vicam_fops = {
1247         .owner          = THIS_MODULE,
1248         .open           = vicam_open,
1249         .release        = vicam_close,
1250         .read           = vicam_read,
1251         .mmap           = vicam_mmap,
1252         .ioctl          = vicam_ioctl,
1253         .llseek         = no_llseek,
1254 };
1255
1256 static struct video_device vicam_template = {
1257         .owner          = THIS_MODULE,
1258         .name           = "ViCam-based USB Camera",
1259         .type           = VID_TYPE_CAPTURE,
1260         .hardware       = VID_HARDWARE_VICAM,
1261         .fops           = &vicam_fops,
1262         .minor          = -1,
1263 };
1264
1265 /* table of devices that work with this driver */
1266 static struct usb_device_id vicam_table[] = {
1267         {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1268         {}                      /* Terminating entry */
1269 };
1270
1271 MODULE_DEVICE_TABLE(usb, vicam_table);
1272
1273 static struct usb_driver vicam_driver = {
1274         .owner          = THIS_MODULE,
1275         .name           = "vicam",
1276         .probe          = vicam_probe,
1277         .disconnect     = vicam_disconnect,
1278         .id_table       = vicam_table
1279 };
1280
1281 /**
1282  *      vicam_probe
1283  *      @intf: the interface
1284  *      @id: the device id
1285  *
1286  *      Called by the usb core when a new device is connected that it thinks
1287  *      this driver might be interested in.
1288  */
1289 static int
1290 vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
1291 {
1292         struct usb_device *dev = interface_to_usbdev(intf);
1293         int bulkEndpoint = 0;
1294         const struct usb_host_interface *interface;
1295         const struct usb_endpoint_descriptor *endpoint;
1296         struct vicam_camera *cam;
1297         
1298         /* See if the device offered us matches what we can accept */
1299         if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
1300             (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
1301                 return -ENODEV;
1302         }
1303
1304         printk(KERN_INFO "ViCam based webcam connected\n");
1305
1306         interface = intf->cur_altsetting;
1307
1308         DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1309                interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
1310         endpoint = &interface->endpoint[0].desc;
1311
1312         if ((endpoint->bEndpointAddress & 0x80) &&
1313             ((endpoint->bmAttributes & 3) == 0x02)) {
1314                 /* we found a bulk in endpoint */
1315                 bulkEndpoint = endpoint->bEndpointAddress;
1316         } else {
1317                 printk(KERN_ERR
1318                        "No bulk in endpoint was found ?! (this is bad)\n");
1319         }
1320
1321         if ((cam =
1322              kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1323                 printk(KERN_WARNING
1324                        "could not allocate kernel memory for vicam_camera struct\n");
1325                 return -ENOMEM;
1326         }
1327
1328         memset(cam, 0, sizeof (struct vicam_camera));
1329
1330         cam->shutter_speed = 15;
1331
1332         init_MUTEX(&cam->cam_lock);
1333
1334         memcpy(&cam->vdev, &vicam_template,
1335                sizeof (vicam_template));
1336         cam->vdev.priv = cam;   // sort of a reverse mapping for those functions that get vdev only
1337
1338         cam->udev = dev;
1339         cam->bulkEndpoint = bulkEndpoint;
1340
1341         if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1342                 kfree(cam);
1343                 printk(KERN_WARNING "video_register_device failed\n");
1344                 return -EIO;
1345         }
1346
1347         vicam_create_proc_entry(cam);
1348
1349         printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1350
1351         usb_set_intfdata (intf, cam);
1352         
1353         return 0;
1354 }
1355
1356 static void
1357 vicam_disconnect(struct usb_interface *intf)
1358 {
1359         int open_count;
1360         struct vicam_camera *cam = usb_get_intfdata (intf);
1361         usb_set_intfdata (intf, NULL);
1362
1363         /* we must unregister the device before taking its
1364          * cam_lock. This is because the video open call
1365          * holds the same lock as video unregister. if we
1366          * unregister inside of the cam_lock and open also
1367          * uses the cam_lock, we get deadlock.
1368          */
1369
1370         video_unregister_device(&cam->vdev);
1371
1372         /* stop the camera from being used */
1373
1374         down(&cam->cam_lock);
1375
1376         /* mark the camera as gone */
1377
1378         cam->udev = NULL;
1379
1380         vicam_destroy_proc_entry(cam);
1381
1382         /* the only thing left to do is synchronize with
1383          * our close/release function on who should release
1384          * the camera memory. if there are any users using the
1385          * camera, it's their job. if there are no users,
1386          * it's ours.
1387          */
1388
1389         open_count = cam->open_count;
1390
1391         up(&cam->cam_lock);
1392
1393         if (!open_count) {
1394                 kfree(cam);
1395         }
1396
1397         printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1398 }
1399
1400 /*
1401  */
1402 static int __init
1403 usb_vicam_init(void)
1404 {
1405         int retval;
1406         DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1407         vicam_create_proc_root();
1408         retval = usb_register(&vicam_driver);
1409         if (retval)
1410                 printk(KERN_WARNING "usb_register failed!\n");
1411         return retval;
1412 }
1413
1414 static void __exit
1415 usb_vicam_exit(void)
1416 {
1417         DBG(KERN_INFO
1418                "ViCam-based WebCam driver shutdown\n");
1419
1420         usb_deregister(&vicam_driver);
1421         vicam_destroy_proc_root();
1422 }
1423
1424 module_init(usb_vicam_init);
1425 module_exit(usb_vicam_exit);
1426
1427 MODULE_AUTHOR(DRIVER_AUTHOR);
1428 MODULE_DESCRIPTION(DRIVER_DESC);
1429 MODULE_LICENSE("GPL");