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)
9 * Supports 3COM HomeConnect PC Digital WebCam
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.
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.
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.
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
28 * Portions of this code were also copied from usbvideo.c
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.
37 #include <linux/kernel.h>
38 #include <linux/wrapper.h>
39 #include <linux/module.h>
40 #include <linux/init.h>
41 #include <linux/videodev.h>
42 #include <linux/usb.h>
43 #include <linux/vmalloc.h>
44 #include <linux/slab.h>
45 #include <linux/proc_fs.h>
48 // #define VICAM_DEBUG
50 #ifndef MODULE_LICENSE
51 #define MODULE_LICENSE(a)
59 #define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
60 #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
62 #define DBG(fmn,args...) do {} while(0)
65 /* Version Information */
66 #define DRIVER_VERSION "v1.0"
67 #define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
68 #define DRIVER_DESC "ViCam WebCam Driver"
70 /* Define these values to match your device */
71 #define USB_VICAM_VENDOR_ID 0x04c1
72 #define USB_VICAM_PRODUCT_ID 0x009d
74 #define VICAM_BYTES_PER_PIXEL 3
75 #define VICAM_MAX_READ_SIZE (512*242+128)
76 #define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
77 #define VICAM_FRAMES 2
79 /* Not sure what all the bytes in these char
80 * arrays do, but they're necessary to make
84 static unsigned char setup1[] = {
85 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67,
86 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00,
87 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17,
88 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00,
89 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
92 static unsigned char setup2[] = {
93 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00,
97 static unsigned char setup3[] = {
98 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00
101 static unsigned char setup4[] = {
102 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07,
103 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00,
104 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00,
105 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07,
106 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00,
107 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00,
108 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07,
109 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF,
110 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0,
111 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07,
112 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00,
113 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0,
114 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1,
115 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09,
116 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00,
117 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF,
118 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02,
119 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00,
120 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF,
121 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00,
122 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00,
123 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05,
124 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA,
125 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06,
126 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF,
127 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05,
128 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01,
129 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09,
130 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06,
131 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05,
132 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA,
133 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05,
134 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
135 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00,
136 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF,
137 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00,
138 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0,
139 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06,
140 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00,
141 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07,
142 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF,
143 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00,
144 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
145 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57,
146 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57,
147 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00,
148 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0,
149 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B,
150 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06,
151 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06,
152 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E,
153 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00,
154 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05,
155 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00,
156 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
157 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF,
158 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0,
159 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
160 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05,
161 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF,
162 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0,
163 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07,
164 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07,
165 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF,
166 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF,
167 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
168 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
169 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1,
170 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
171 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00,
172 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07,
173 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07,
174 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07,
175 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00,
176 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06,
177 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67,
178 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8,
179 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0,
180 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF,
181 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02,
182 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
183 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06,
184 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05,
185 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
186 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00,
187 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06,
188 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
189 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05,
190 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05,
191 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
192 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04,
193 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF,
194 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06,
195 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
196 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00,
197 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05,
198 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07,
199 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07,
200 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07,
201 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF,
202 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07,
203 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06,
204 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05,
205 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07,
206 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00,
207 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00,
208 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77,
209 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04,
210 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0,
211 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1,
212 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07,
213 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF,
214 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
215 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
216 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
217 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77,
218 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1,
219 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07,
220 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF,
221 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06,
222 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
223 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07,
224 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07,
225 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00,
226 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00,
227 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
228 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
229 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F,
230 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00,
231 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00,
232 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA,
233 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
234 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06,
235 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF,
236 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B,
237 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
238 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09,
239 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05,
240 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07,
241 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00,
242 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF,
243 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05,
244 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00,
245 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00,
246 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05,
247 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05,
248 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00,
249 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF,
250 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09,
251 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
252 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1,
253 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00,
254 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05,
255 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00,
256 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00,
257 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05,
258 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0,
259 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67,
260 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87,
261 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9,
262 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1,
263 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF,
264 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00,
265 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0,
266 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87,
267 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
268 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67,
269 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
270 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
271 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67,
272 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
273 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
274 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
275 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00,
276 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF,
277 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
278 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
279 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09,
280 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
281 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA,
282 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87,
283 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
284 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
285 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
286 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
287 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02,
288 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09,
289 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
290 0x07, 0x05, 0x81, 0x02, 0x40, 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, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 static unsigned char setup5[] = {
316 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00,
317 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00,
318 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00,
319 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00,
320 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00,
321 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00,
322 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00,
323 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01,
324 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01,
325 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01,
326 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01,
327 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01,
328 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01,
329 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01,
330 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01,
331 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02,
332 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02,
333 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02,
334 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02,
335 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02,
336 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02,
337 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02,
338 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02,
339 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03,
340 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03,
341 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03,
342 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03,
343 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03,
344 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03,
345 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03,
346 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04,
347 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04,
348 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04,
349 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04,
350 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04,
351 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04,
352 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04,
353 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05,
354 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
357 struct vicam_camera {
358 u16 shutter_speed; // capture shutter speed
359 u16 gain; // capture gain
361 u8 *raw_image; // raw data captured from the camera
362 u8 *framebuf; // processed data in RGB24 format
364 struct video_device vdev; // v4l video device
365 struct usb_device *udev; // usb device
367 struct semaphore busy_lock; // guard against SMP multithreading
375 u32 framebuf_size; // # of valid bytes in framebuf
376 u32 framebuf_read_start; // position in frame buf that a read is happening at.
378 #ifdef CONFIG_PROC_FS
379 struct proc_dir_entry *proc_entry;
384 static void *vicam_probe(struct usb_device *dev, unsigned int ifnum,
385 const struct usb_device_id *id);
386 static void vicam_disconnect(struct usb_device *dev, void *ptr);
387 static void read_frame(struct vicam_camera *cam, int framenum);
388 static void vicam_purge(struct vicam_camera *cam);
391 send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index,
392 unsigned char *cp, u16 size)
396 // for reasons not yet known to me, you can't send USB control messages
397 // with data in the module (if you are compiled as a module). Whatever
398 // the reason, copying it to memory allocated as kernel memory then
399 // doing the usb control message fixes the problem.
401 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
402 memcpy(transfer_buffer, cp, size);
404 status = usb_control_msg(udev,
405 usb_sndctrlpipe(udev, 0),
407 USB_DIR_OUT | USB_TYPE_VENDOR |
408 USB_RECIP_DEVICE, value, index,
409 transfer_buffer, size, HZ);
411 kfree(transfer_buffer);
414 printk(KERN_INFO "Failed sending control message, error %d.\n",
422 initialize_camera(struct vicam_camera *cam)
424 struct usb_device *udev = cam->udev;
428 send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0)
431 send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0)
434 send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
437 send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0)
440 send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0)
443 send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
450 set_camera_power(struct vicam_camera *cam, int state)
454 if ((status = send_control_msg(cam->udev, 0x50, state, 0, NULL, 0)) < 0)
458 send_control_msg(cam->udev, 0x55, 1, 0, NULL, 0);
465 vicam_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg)
467 struct vicam_camera *cam = dev->priv;
473 /* make this _really_ smp-safe */
474 if (down_interruptible(&cam->busy_lock))
478 /* query capabilites */
481 struct video_capability b;
484 memset(&b, 0, sizeof(b));
485 strcpy(b.name, "ViCam-based Camera");
486 b.type = VID_TYPE_CAPTURE;
489 b.maxwidth = 320; /* VIDEOSIZE_CIF */
491 b.minwidth = 320; /* VIDEOSIZE_48_48 */
494 if (copy_to_user(arg, &b, sizeof (b)))
499 /* get/set video source - we are a camera and nothing else */
502 struct video_channel v;
504 DBG("VIDIOCGCHAN\n");
505 if (copy_from_user(&v, arg, sizeof (v))) {
509 if (v.channel != 0) {
515 strcpy(v.name, "Camera");
518 v.type = VIDEO_TYPE_CAMERA;
521 if (copy_to_user(arg, &v, sizeof (v)))
530 if (copy_from_user(&v, arg, sizeof (v)))
532 DBG("VIDIOCSCHAN %d\n", v);
534 if (retval == 0 && v != 0)
540 /* image properties */
543 struct video_picture vp;
544 DBG("VIDIOCGPICT\n");
545 memset(&vp, 0, sizeof (struct video_picture));
546 vp.brightness = cam->gain << 8;
548 vp.palette = VIDEO_PALETTE_RGB24;
550 (arg, &vp, sizeof (struct video_picture)))
557 struct video_picture vp;
559 if(copy_from_user(&vp, (struct video_picture *) arg,
560 sizeof(struct video_picture)))
565 DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
568 cam->gain = vp.brightness >> 8;
571 || vp.palette != VIDEO_PALETTE_RGB24)
578 /* get/set capture window */
581 struct video_window vw;
594 ((void *) arg, (void *) &vw, sizeof (vw)))
597 // I'm not sure what the deal with a capture window is, it is very poorly described
598 // in the doc. So I won't support it now.
605 struct video_window vw;
607 if (copy_from_user(&vw, arg, sizeof(vw)))
613 DBG("VIDIOCSWIN %d x %d\n", vw->width, vw->height);
615 if ( vw.width != 320 || vw.height != 240 )
624 struct video_mbuf vm;
627 DBG("VIDIOCGMBUF\n");
628 memset(&vm, 0, sizeof (vm));
630 VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
631 vm.frames = VICAM_FRAMES;
632 for (i = 0; i < VICAM_FRAMES; i++)
633 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
636 ((void *) arg, (void *) &vm, sizeof (vm)))
644 struct video_mmap vm;
648 ((void *) &vm, (void *) arg, sizeof (vm))) {
653 DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
655 if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
658 // in theory right here we'd start the image capturing
659 // (fill in a bulk urb and submit it asynchronously)
661 // Instead we're going to do a total hack job for now and
662 // retrieve the frame in VIDIOCSYNC
671 if (copy_from_user((void *) &frame, arg, sizeof (int))) {
675 DBG("VIDIOCSYNC: %d\n", frame);
677 read_frame(cam, frame);
682 /* pointless to implement overlay with this camera */
690 /* tuner interface - we have none */
698 /* audio interface - we have none */
704 retval = -ENOIOCTLCMD;
713 vicam_open(struct video_device *dev, int flags)
715 struct vicam_camera *cam =
716 (struct vicam_camera *) dev->priv;
722 "vicam video_device improperly initialized");
725 intr = down_interruptible(&cam->busy_lock);
729 if (cam->is_opened) {
731 "vicam_open called on already opened camera");
736 if (!cam->raw_image) {
737 cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
738 if (!cam->raw_image) {
744 if (!cam->framebuf) {
746 usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
747 if (!cam->framebuf) {
748 kfree(cam->raw_image);
753 // First upload firmware, then turn the camera on
755 if (!cam->is_initialized) {
756 initialize_camera(cam);
758 cam->is_initialized = 1;
761 set_camera_power(cam, 1);
763 cam->needsDummyRead = 1;
772 vicam_close(struct video_device *dev)
774 struct vicam_camera *cam = (struct vicam_camera *) dev->priv;
778 if (cam->is_removed) {
781 set_camera_power(cam, 0);
786 inline int pin(int x)
788 return((x > 255) ? 255 : ((x < 0) ? 0 : x));
791 inline void writepixel(char *rgb, int Y, int Cr, int Cb)
795 rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 );
796 rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 );
797 rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );
800 #define DATA_HEADER_SIZE 64
802 // --------------------------------------------------------------------------------
803 // vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
805 // Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
806 // --------------------------------------------------------------------------------
808 void vicam_decode_color( char *data, char *rgb)
813 int prevX, nextX, prevY, nextY;
821 src = data + DATA_HEADER_SIZE;
824 for(y = 1; y < 241; y += 2)
833 dst = rgb + (y-1)*320*3;
835 for(x = 0; x < 512; x++)
840 Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1;
841 Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2;
845 src[0] + (sign * (Cr >> 1)),
866 dst = rgb + (y)*320*3;
868 for(x = 0; x < 512; x++)
873 Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2;
874 Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1;
877 dst + ((x * 5)>>3)*3,
878 src[0] - (sign * (Cb >> 1)),
890 read_frame(struct vicam_camera *cam, int framenum)
892 unsigned char request[16];
897 memset(request, 0, 16);
898 request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
900 request[1] = 0; // 512x242 capture
902 request[2] = 0x90; // the function of these two bytes
903 request[3] = 0x07; // is not yet understood
905 if (cam->shutter_speed > 60) {
908 ((-15631900 / cam->shutter_speed) + 260533) / 1000;
909 request[4] = realShutter & 0xFF;
910 request[5] = (realShutter >> 8) & 0xFF;
915 realShutter = 15600 / cam->shutter_speed - 1;
918 request[6] = realShutter & 0xFF;
919 request[7] = realShutter >> 8;
922 // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
924 // bytes 9-15 do not seem to affect exposure or image quality
926 n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16);
930 " Problem sending frame capture control message");
934 n = usb_bulk_msg(cam->udev,
935 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
937 512 * 242 + 128, &actual_length, 500);
940 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
944 vicam_decode_color(cam->raw_image,
946 framenum * VICAM_MAX_FRAME_SIZE );
949 320 * 240 * VICAM_BYTES_PER_PIXEL;
950 cam->framebuf_read_start = 0;
957 vicam_read(struct video_device *dev, char *buf,
958 unsigned long count, int noblock)
960 struct vicam_camera *cam = dev->priv;
962 DBG("read %d bytes.\n", (int) count);
970 // This is some code that will hopefully allow us to do shell copies from
971 // the /dev/videoX to a file and have it actually work.
972 if (cam->framebuf_size != 0) {
973 if (cam->framebuf_read_start == cam->framebuf_size) {
974 cam->framebuf_size = cam->framebuf_read_start = 0;
977 if (cam->framebuf_read_start + count <=
978 cam->framebuf_size) {
979 // count does not exceed available bytes
980 if (copy_to_user(buf,
982 cam->framebuf_read_start, count))
984 cam->framebuf_read_start += count;
989 cam->framebuf_read_start;
990 if (copy_to_user(buf,
992 cam->framebuf_read_start, count))
994 cam->framebuf_read_start = cam->framebuf_size;
1000 intr = down_interruptible(&cam->busy_lock);
1004 if (cam->needsDummyRead) {
1006 cam->needsDummyRead = 0;
1008 // read_frame twice because the camera doesn't seem to take the shutter speed for the first one.
1012 if (count > cam->framebuf_size)
1013 count = cam->framebuf_size;
1015 if (copy_to_user(buf, cam->framebuf, count)) {
1016 up(&cam->busy_lock);
1020 if (count != cam->framebuf_size)
1021 cam->framebuf_read_start = count;
1023 cam->framebuf_size = 0;
1025 up(&cam->busy_lock);
1031 vicam_mmap(struct video_device *dev, const char *adr, unsigned long size)
1033 // TODO: allocate the raw frame buffer if necessary
1034 unsigned long start = (unsigned long) adr;
1035 unsigned long page, pos;
1036 struct vicam_camera *cam = dev->priv;
1041 DBG("vicam_mmap: %ld\n", size);
1043 /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1044 * to the size the application requested for mmap and it was screwing apps up.
1045 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1049 /* make this _really_ smp-safe */
1050 if (down_interruptible(&cam->busy_lock))
1053 if (!cam->framebuf) { /* we do lazy allocation */
1055 usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
1056 if (!cam->framebuf) {
1057 up(&cam->busy_lock);
1062 pos = (unsigned long) (cam->framebuf);
1064 page = usbvideo_kvirt_to_pa(pos);
1065 if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
1066 up(&cam->busy_lock);
1071 if (size > PAGE_SIZE)
1077 up(&cam->busy_lock);
1082 #ifdef CONFIG_PROC_FS
1084 static struct proc_dir_entry *vicam_proc_root = NULL;
1087 vicam_read_proc(char *page, char **start, off_t off,
1088 int count, int *eof, void *data)
1092 struct vicam_camera *cam = (struct vicam_camera *) data;
1095 sprintf(out, "Vicam-based WebCam Linux Driver.\n");
1096 out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n");
1097 out += sprintf(out, "vicam stats:\n");
1098 out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed);
1099 out += sprintf(out, " Gain: %d\n", cam->gain);
1110 *start = page + off;
1115 vicam_write_proc(struct file *file, const char *buffer,
1116 unsigned long count, void *data)
1120 struct vicam_camera *cam = (struct vicam_camera *) data;
1122 in = kmalloc(count + 1, GFP_KERNEL);
1126 in[count] = 0; // I'm not sure buffer is gauranteed to be null terminated
1127 // so I do this to make sure I have a null in there.
1129 strncpy(in, buffer, count);
1131 start = strstr(in, "gain=");
1133 && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
1134 cam->gain = simple_strtoul(start + 5, NULL, 10);
1136 start = strstr(in, "shutter=");
1138 && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
1139 cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
1146 vicam_create_proc_root(void)
1148 vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
1150 if (vicam_proc_root)
1151 vicam_proc_root->owner = THIS_MODULE;
1154 "could not create /proc entry for vicam!");
1158 vicam_destroy_proc_root(void)
1160 if (vicam_proc_root)
1161 remove_proc_entry("video/vicam", 0);
1165 vicam_create_proc_entry(void *ptr)
1167 struct vicam_camera *cam = (struct vicam_camera *) ptr;
1170 struct proc_dir_entry *ent;
1172 DBG(KERN_INFO "vicam: creating proc entry\n");
1174 if (!vicam_proc_root || !cam) {
1176 "vicam: could not create proc entry, %s pointer is null.\n",
1177 (!cam ? "camera" : "root"));
1181 sprintf(name, "video%d", cam->vdev.minor);
1184 create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
1190 ent->read_proc = vicam_read_proc;
1191 ent->write_proc = vicam_write_proc;
1193 cam->proc_entry = ent;
1197 vicam_destroy_proc_entry(void *ptr)
1199 struct vicam_camera *cam = (struct vicam_camera *) ptr;
1202 if (!cam || !cam->proc_entry)
1205 sprintf(name, "video%d", cam->vdev.minor);
1206 remove_proc_entry(name, vicam_proc_root);
1207 cam->proc_entry = NULL;
1214 vicam_video_init(struct video_device *vdev)
1216 // This would normally create the proc entry for this camera
1217 #ifdef CONFIG_PROC_FS
1218 vicam_create_proc_entry(vdev->priv);
1224 vicam_write(struct video_device *v, const char *buf, unsigned long count,
1231 static struct video_device vicam_template = {
1233 name:"ViCam-based USB Camera",
1234 type:VID_TYPE_CAPTURE,
1235 hardware:VID_HARDWARE_VICAM,
1242 initialize:vicam_video_init,
1246 /* table of devices that work with this driver */
1247 static struct usb_device_id vicam_table[] = {
1248 {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1249 {} /* Terminating entry */
1252 MODULE_DEVICE_TABLE(usb, vicam_table);
1254 static struct usb_driver vicam_driver = {
1257 disconnect:vicam_disconnect,
1258 id_table:vicam_table
1264 * Called by the usb core when a new device is connected that it thinks
1265 * this driver might be interested in.
1268 vicam_probe(struct usb_device *dev, unsigned int ifnum,
1269 const struct usb_device_id *id)
1271 int nas, bulkEndpoint = 0;
1272 const struct usb_interface_descriptor *interface;
1273 const struct usb_endpoint_descriptor *endpoint;
1274 struct vicam_camera *cam;
1276 /* See if the device offered us matches what we can accept */
1277 if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
1278 (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
1282 printk(KERN_INFO "ViCam based webcam connected\n");
1284 nas = dev->actconfig->interface[ifnum].num_altsetting;
1287 "Expected only one alternate setting for this camera!\n");
1291 interface = &dev->actconfig->interface[ifnum].altsetting[0];
1292 DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1293 ifnum, (unsigned) (interface->bNumEndpoints));
1294 endpoint = &interface->endpoint[0];
1296 if ((endpoint->bEndpointAddress & 0x80) &&
1297 ((endpoint->bmAttributes & 3) == 0x02)) {
1298 /* we found a bulk in endpoint */
1299 bulkEndpoint = endpoint->bEndpointAddress;
1302 "No bulk in endpoint was found ?! (this is bad)\n");
1306 kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1308 "could not allocate kernel memory for vicam_camera struct\n");
1312 memset(cam, 0, sizeof (struct vicam_camera));
1314 cam->shutter_speed = 15;
1316 init_MUTEX(&cam->busy_lock);
1318 memcpy(&cam->vdev, &vicam_template,
1319 sizeof (vicam_template));
1320 cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only
1323 cam->bulkEndpoint = bulkEndpoint;
1325 if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1327 printk(KERN_WARNING "video_register_device failed\n");
1331 printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1338 vicam_purge(struct vicam_camera *cam)
1340 video_unregister_device(&cam->vdev);
1342 #ifdef CONFIG_PROC_FS
1343 vicam_destroy_proc_entry(cam);
1347 kfree(cam->raw_image);
1349 usbvideo_rvfree(cam->framebuf,
1350 VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
1354 printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1358 vicam_disconnect(struct usb_device *dev, void *ptr)
1360 struct vicam_camera *cam = ptr;
1362 if (cam->is_opened) {
1363 cam->is_removed = 1;
1372 usb_vicam_init(void)
1374 DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1375 #ifdef CONFIG_PROC_FS
1376 vicam_create_proc_root();
1378 if (usb_register(&vicam_driver) != 0)
1379 printk(KERN_WARNING "usb_register failed!\n");
1384 usb_vicam_exit(void)
1387 "ViCam-based WebCam driver shutdown\n");
1389 usb_deregister(&vicam_driver);
1390 #ifdef CONFIG_PROC_FS
1391 vicam_destroy_proc_root();
1395 module_init(usb_vicam_init);
1396 module_exit(usb_vicam_exit);
1398 MODULE_AUTHOR(DRIVER_AUTHOR);
1399 MODULE_DESCRIPTION(DRIVER_DESC);
1400 MODULE_LICENSE("GPL");