Initial commit
[wrt350n-kernel.git] / drivers / media / video / usbvideo / vicam.c
blobda1ba0211108939810983cb3753588d713c257ef
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)
9 * Supports 3COM HomeConnect PC Digital WebCam
10 * Supports Compro PS39U WebCam
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * This source code is based heavily on the CPiA webcam driver which was
27 * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
29 * Portions of this code were also copied from usbvideo.c
31 * Special thanks to the whole team at Sourceforge for help making
32 * this driver become a reality. Notably:
33 * Andy Armstrong who reverse engineered the color encoding and
34 * Pavel Machek and Chris Cheney who worked on reverse engineering the
35 * camera controls and wrote the first generation driver.
38 #include <linux/kernel.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/mutex.h>
46 #include "usbvideo.h"
48 // #define VICAM_DEBUG
50 #ifdef VICAM_DEBUG
51 #define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
52 #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
53 #else
54 #define DBG(fmn,args...) do {} while(0)
55 #endif
57 #define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
58 #define DRIVER_DESC "ViCam WebCam Driver"
60 /* Define these values to match your device */
61 #define USB_VICAM_VENDOR_ID 0x04c1
62 #define USB_VICAM_PRODUCT_ID 0x009d
63 #define USB_COMPRO_VENDOR_ID 0x0602
64 #define USB_COMPRO_PRODUCT_ID 0x1001
66 #define VICAM_BYTES_PER_PIXEL 3
67 #define VICAM_MAX_READ_SIZE (512*242+128)
68 #define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
69 #define VICAM_FRAMES 2
71 #define VICAM_HEADER_SIZE 64
73 #define clamp( x, l, h ) max_t( __typeof__( x ), \
74 ( l ), \
75 min_t( __typeof__( x ), \
76 ( h ), \
77 ( x ) ) )
79 /* Not sure what all the bytes in these char
80 * arrays do, but they're necessary to make
81 * the camera work.
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,
94 0x00, 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 /* rvmalloc / rvfree copied from usbvideo.c
359 * Not sure why these are not yet non-statics which I can reference through
360 * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime
361 * in the future.
364 static void *rvmalloc(unsigned long size)
366 void *mem;
367 unsigned long adr;
369 size = PAGE_ALIGN(size);
370 mem = vmalloc_32(size);
371 if (!mem)
372 return NULL;
374 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
375 adr = (unsigned long) mem;
376 while (size > 0) {
377 SetPageReserved(vmalloc_to_page((void *)adr));
378 adr += PAGE_SIZE;
379 size -= PAGE_SIZE;
382 return mem;
385 static void rvfree(void *mem, unsigned long size)
387 unsigned long adr;
389 if (!mem)
390 return;
392 adr = (unsigned long) mem;
393 while ((long) size > 0) {
394 ClearPageReserved(vmalloc_to_page((void *)adr));
395 adr += PAGE_SIZE;
396 size -= PAGE_SIZE;
398 vfree(mem);
401 struct vicam_camera {
402 u16 shutter_speed; // capture shutter speed
403 u16 gain; // capture gain
405 u8 *raw_image; // raw data captured from the camera
406 u8 *framebuf; // processed data in RGB24 format
407 u8 *cntrlbuf; // area used to send control msgs
409 struct video_device vdev; // v4l video device
410 struct usb_device *udev; // usb device
412 /* guard against simultaneous accesses to the camera */
413 struct mutex cam_lock;
415 int is_initialized;
416 u8 open_count;
417 u8 bulkEndpoint;
418 int needsDummyRead;
421 static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
422 static void vicam_disconnect(struct usb_interface *intf);
423 static void read_frame(struct vicam_camera *cam, int framenum);
424 static void vicam_decode_color(const u8 *, u8 *);
426 static int __send_control_msg(struct vicam_camera *cam,
427 u8 request,
428 u16 value,
429 u16 index,
430 unsigned char *cp,
431 u16 size)
433 int status;
435 /* cp must be memory that has been allocated by kmalloc */
437 status = usb_control_msg(cam->udev,
438 usb_sndctrlpipe(cam->udev, 0),
439 request,
440 USB_DIR_OUT | USB_TYPE_VENDOR |
441 USB_RECIP_DEVICE, value, index,
442 cp, size, 1000);
444 status = min(status, 0);
446 if (status < 0) {
447 printk(KERN_INFO "Failed sending control message, error %d.\n",
448 status);
451 return status;
454 static int send_control_msg(struct vicam_camera *cam,
455 u8 request,
456 u16 value,
457 u16 index,
458 unsigned char *cp,
459 u16 size)
461 int status = -ENODEV;
462 mutex_lock(&cam->cam_lock);
463 if (cam->udev) {
464 status = __send_control_msg(cam, request, value,
465 index, cp, size);
467 mutex_unlock(&cam->cam_lock);
468 return status;
470 static int
471 initialize_camera(struct vicam_camera *cam)
473 const struct {
474 u8 *data;
475 u32 size;
476 } firmware[] = {
477 { .data = setup1, .size = sizeof(setup1) },
478 { .data = setup2, .size = sizeof(setup2) },
479 { .data = setup3, .size = sizeof(setup3) },
480 { .data = setup4, .size = sizeof(setup4) },
481 { .data = setup5, .size = sizeof(setup5) },
482 { .data = setup3, .size = sizeof(setup3) },
483 { .data = NULL, .size = 0 }
486 int err, i;
488 for (i = 0, err = 0; firmware[i].data && !err; i++) {
489 memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
491 err = send_control_msg(cam, 0xff, 0, 0,
492 cam->cntrlbuf, firmware[i].size);
495 return err;
498 static int
499 set_camera_power(struct vicam_camera *cam, int state)
501 int status;
503 if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
504 return status;
506 if (state) {
507 send_control_msg(cam, 0x55, 1, 0, NULL, 0);
510 return 0;
513 static int
514 vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
516 void __user *user_arg = (void __user *)arg;
517 struct vicam_camera *cam = file->private_data;
518 int retval = 0;
520 if (!cam)
521 return -ENODEV;
523 switch (ioctlnr) {
524 /* query capabilities */
525 case VIDIOCGCAP:
527 struct video_capability b;
529 DBG("VIDIOCGCAP\n");
530 memset(&b, 0, sizeof(b));
531 strcpy(b.name, "ViCam-based Camera");
532 b.type = VID_TYPE_CAPTURE;
533 b.channels = 1;
534 b.audios = 0;
535 b.maxwidth = 320; /* VIDEOSIZE_CIF */
536 b.maxheight = 240;
537 b.minwidth = 320; /* VIDEOSIZE_48_48 */
538 b.minheight = 240;
540 if (copy_to_user(user_arg, &b, sizeof(b)))
541 retval = -EFAULT;
543 break;
545 /* get/set video source - we are a camera and nothing else */
546 case VIDIOCGCHAN:
548 struct video_channel v;
550 DBG("VIDIOCGCHAN\n");
551 if (copy_from_user(&v, user_arg, sizeof(v))) {
552 retval = -EFAULT;
553 break;
555 if (v.channel != 0) {
556 retval = -EINVAL;
557 break;
560 v.channel = 0;
561 strcpy(v.name, "Camera");
562 v.tuners = 0;
563 v.flags = 0;
564 v.type = VIDEO_TYPE_CAMERA;
565 v.norm = 0;
567 if (copy_to_user(user_arg, &v, sizeof(v)))
568 retval = -EFAULT;
569 break;
572 case VIDIOCSCHAN:
574 int v;
576 if (copy_from_user(&v, user_arg, sizeof(v)))
577 retval = -EFAULT;
578 DBG("VIDIOCSCHAN %d\n", v);
580 if (retval == 0 && v != 0)
581 retval = -EINVAL;
583 break;
586 /* image properties */
587 case VIDIOCGPICT:
589 struct video_picture vp;
590 DBG("VIDIOCGPICT\n");
591 memset(&vp, 0, sizeof (struct video_picture));
592 vp.brightness = cam->gain << 8;
593 vp.depth = 24;
594 vp.palette = VIDEO_PALETTE_RGB24;
595 if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
596 retval = -EFAULT;
597 break;
600 case VIDIOCSPICT:
602 struct video_picture vp;
604 if (copy_from_user(&vp, user_arg, sizeof(vp))) {
605 retval = -EFAULT;
606 break;
609 DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
610 vp.palette);
612 cam->gain = vp.brightness >> 8;
614 if (vp.depth != 24
615 || vp.palette != VIDEO_PALETTE_RGB24)
616 retval = -EINVAL;
618 break;
621 /* get/set capture window */
622 case VIDIOCGWIN:
624 struct video_window vw;
625 vw.x = 0;
626 vw.y = 0;
627 vw.width = 320;
628 vw.height = 240;
629 vw.chromakey = 0;
630 vw.flags = 0;
631 vw.clips = NULL;
632 vw.clipcount = 0;
634 DBG("VIDIOCGWIN\n");
636 if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
637 retval = -EFAULT;
639 // I'm not sure what the deal with a capture window is, it is very poorly described
640 // in the doc. So I won't support it now.
641 break;
644 case VIDIOCSWIN:
647 struct video_window vw;
649 if (copy_from_user(&vw, user_arg, sizeof(vw))) {
650 retval = -EFAULT;
651 break;
654 DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
656 if ( vw.width != 320 || vw.height != 240 )
657 retval = -EFAULT;
659 break;
662 /* mmap interface */
663 case VIDIOCGMBUF:
665 struct video_mbuf vm;
666 int i;
668 DBG("VIDIOCGMBUF\n");
669 memset(&vm, 0, sizeof (vm));
670 vm.size =
671 VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
672 vm.frames = VICAM_FRAMES;
673 for (i = 0; i < VICAM_FRAMES; i++)
674 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
676 if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
677 retval = -EFAULT;
679 break;
682 case VIDIOCMCAPTURE:
684 struct video_mmap vm;
685 // int video_size;
687 if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
688 retval = -EFAULT;
689 break;
692 DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
694 if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
695 retval = -EINVAL;
697 // in theory right here we'd start the image capturing
698 // (fill in a bulk urb and submit it asynchronously)
700 // Instead we're going to do a total hack job for now and
701 // retrieve the frame in VIDIOCSYNC
703 break;
706 case VIDIOCSYNC:
708 int frame;
710 if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
711 retval = -EFAULT;
712 break;
714 DBG("VIDIOCSYNC: %d\n", frame);
716 read_frame(cam, frame);
717 vicam_decode_color(cam->raw_image,
718 cam->framebuf +
719 frame * VICAM_MAX_FRAME_SIZE );
721 break;
724 /* pointless to implement overlay with this camera */
725 case VIDIOCCAPTURE:
726 case VIDIOCGFBUF:
727 case VIDIOCSFBUF:
728 case VIDIOCKEY:
729 retval = -EINVAL;
730 break;
732 /* tuner interface - we have none */
733 case VIDIOCGTUNER:
734 case VIDIOCSTUNER:
735 case VIDIOCGFREQ:
736 case VIDIOCSFREQ:
737 retval = -EINVAL;
738 break;
740 /* audio interface - we have none */
741 case VIDIOCGAUDIO:
742 case VIDIOCSAUDIO:
743 retval = -EINVAL;
744 break;
745 default:
746 retval = -ENOIOCTLCMD;
747 break;
750 return retval;
753 static int
754 vicam_open(struct inode *inode, struct file *file)
756 struct video_device *dev = video_devdata(file);
757 struct vicam_camera *cam =
758 (struct vicam_camera *) dev->priv;
759 DBG("open\n");
761 if (!cam) {
762 printk(KERN_ERR
763 "vicam video_device improperly initialized");
764 return -EINVAL;
767 /* the videodev_lock held above us protects us from
768 * simultaneous opens...for now. we probably shouldn't
769 * rely on this fact forever.
772 if (cam->open_count > 0) {
773 printk(KERN_INFO
774 "vicam_open called on already opened camera");
775 return -EBUSY;
778 cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
779 if (!cam->raw_image) {
780 return -ENOMEM;
783 cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
784 if (!cam->framebuf) {
785 kfree(cam->raw_image);
786 return -ENOMEM;
789 cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
790 if (!cam->cntrlbuf) {
791 kfree(cam->raw_image);
792 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
793 return -ENOMEM;
796 // First upload firmware, then turn the camera on
798 if (!cam->is_initialized) {
799 initialize_camera(cam);
801 cam->is_initialized = 1;
804 set_camera_power(cam, 1);
806 cam->needsDummyRead = 1;
807 cam->open_count++;
809 file->private_data = cam;
811 return 0;
814 static int
815 vicam_close(struct inode *inode, struct file *file)
817 struct vicam_camera *cam = file->private_data;
818 int open_count;
819 struct usb_device *udev;
821 DBG("close\n");
823 /* it's not the end of the world if
824 * we fail to turn the camera off.
827 set_camera_power(cam, 0);
829 kfree(cam->raw_image);
830 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
831 kfree(cam->cntrlbuf);
833 mutex_lock(&cam->cam_lock);
835 cam->open_count--;
836 open_count = cam->open_count;
837 udev = cam->udev;
839 mutex_unlock(&cam->cam_lock);
841 if (!open_count && !udev) {
842 kfree(cam);
845 return 0;
848 static void vicam_decode_color(const u8 *data, u8 *rgb)
850 /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
851 * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
854 int i, prevY, nextY;
856 prevY = 512;
857 nextY = 512;
859 data += VICAM_HEADER_SIZE;
861 for( i = 0; i < 240; i++, data += 512 ) {
862 const int y = ( i * 242 ) / 240;
864 int j, prevX, nextX;
865 int Y, Cr, Cb;
867 if ( y == 242 - 1 ) {
868 nextY = -512;
871 prevX = 1;
872 nextX = 1;
874 for ( j = 0; j < 320; j++, rgb += 3 ) {
875 const int x = ( j * 512 ) / 320;
876 const u8 * const src = &data[x];
878 if ( x == 512 - 1 ) {
879 nextX = -1;
882 Cr = ( src[prevX] - src[0] ) +
883 ( src[nextX] - src[0] );
884 Cr /= 2;
886 Cb = ( src[prevY] - src[prevX + prevY] ) +
887 ( src[prevY] - src[nextX + prevY] ) +
888 ( src[nextY] - src[prevX + nextY] ) +
889 ( src[nextY] - src[nextX + nextY] );
890 Cb /= 4;
892 Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
894 if ( i & 1 ) {
895 int Ct = Cr;
896 Cr = Cb;
897 Cb = Ct;
900 if ( ( x ^ i ) & 1 ) {
901 Cr = -Cr;
902 Cb = -Cb;
905 rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
906 500 ) / 900, 0, 255 );
907 rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
908 ( 813 * Cr ) ) +
909 500 ) / 1000, 0, 255 );
910 rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
911 500 ) / 1300, 0, 255 );
913 prevX = -1;
916 prevY = -512;
920 static void
921 read_frame(struct vicam_camera *cam, int framenum)
923 unsigned char *request = cam->cntrlbuf;
924 int realShutter;
925 int n;
926 int actual_length;
928 if (cam->needsDummyRead) {
929 cam->needsDummyRead = 0;
930 read_frame(cam, framenum);
933 memset(request, 0, 16);
934 request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
936 request[1] = 0; // 512x242 capture
938 request[2] = 0x90; // the function of these two bytes
939 request[3] = 0x07; // is not yet understood
941 if (cam->shutter_speed > 60) {
942 // Short exposure
943 realShutter =
944 ((-15631900 / cam->shutter_speed) + 260533) / 1000;
945 request[4] = realShutter & 0xFF;
946 request[5] = (realShutter >> 8) & 0xFF;
947 request[6] = 0x03;
948 request[7] = 0x01;
949 } else {
950 // Long exposure
951 realShutter = 15600 / cam->shutter_speed - 1;
952 request[4] = 0;
953 request[5] = 0;
954 request[6] = realShutter & 0xFF;
955 request[7] = realShutter >> 8;
958 // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
959 request[8] = 0;
960 // bytes 9-15 do not seem to affect exposure or image quality
962 mutex_lock(&cam->cam_lock);
964 if (!cam->udev) {
965 goto done;
968 n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
970 if (n < 0) {
971 printk(KERN_ERR
972 " Problem sending frame capture control message");
973 goto done;
976 n = usb_bulk_msg(cam->udev,
977 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
978 cam->raw_image,
979 512 * 242 + 128, &actual_length, 10000);
981 if (n < 0) {
982 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
986 done:
987 mutex_unlock(&cam->cam_lock);
990 static ssize_t
991 vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
993 struct vicam_camera *cam = file->private_data;
995 DBG("read %d bytes.\n", (int) count);
997 if (*ppos >= VICAM_MAX_FRAME_SIZE) {
998 *ppos = 0;
999 return 0;
1002 if (*ppos == 0) {
1003 read_frame(cam, 0);
1004 vicam_decode_color(cam->raw_image,
1005 cam->framebuf +
1006 0 * VICAM_MAX_FRAME_SIZE);
1009 count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
1011 if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
1012 count = -EFAULT;
1013 } else {
1014 *ppos += count;
1017 if (count == VICAM_MAX_FRAME_SIZE) {
1018 *ppos = 0;
1021 return count;
1025 static int
1026 vicam_mmap(struct file *file, struct vm_area_struct *vma)
1028 // TODO: allocate the raw frame buffer if necessary
1029 unsigned long page, pos;
1030 unsigned long start = vma->vm_start;
1031 unsigned long size = vma->vm_end-vma->vm_start;
1032 struct vicam_camera *cam = file->private_data;
1034 if (!cam)
1035 return -ENODEV;
1037 DBG("vicam_mmap: %ld\n", size);
1039 /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1040 * to the size the application requested for mmap and it was screwing apps up.
1041 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1042 return -EINVAL;
1045 pos = (unsigned long)cam->framebuf;
1046 while (size > 0) {
1047 page = vmalloc_to_pfn((void *)pos);
1048 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1049 return -EAGAIN;
1051 start += PAGE_SIZE;
1052 pos += PAGE_SIZE;
1053 if (size > PAGE_SIZE)
1054 size -= PAGE_SIZE;
1055 else
1056 size = 0;
1059 return 0;
1062 static const struct file_operations vicam_fops = {
1063 .owner = THIS_MODULE,
1064 .open = vicam_open,
1065 .release = vicam_close,
1066 .read = vicam_read,
1067 .mmap = vicam_mmap,
1068 .ioctl = vicam_ioctl,
1069 .compat_ioctl = v4l_compat_ioctl32,
1070 .llseek = no_llseek,
1073 static struct video_device vicam_template = {
1074 .owner = THIS_MODULE,
1075 .name = "ViCam-based USB Camera",
1076 .type = VID_TYPE_CAPTURE,
1077 .fops = &vicam_fops,
1078 .minor = -1,
1081 /* table of devices that work with this driver */
1082 static struct usb_device_id vicam_table[] = {
1083 {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1084 {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)},
1085 {} /* Terminating entry */
1088 MODULE_DEVICE_TABLE(usb, vicam_table);
1090 static struct usb_driver vicam_driver = {
1091 .name = "vicam",
1092 .probe = vicam_probe,
1093 .disconnect = vicam_disconnect,
1094 .id_table = vicam_table
1098 * vicam_probe
1099 * @intf: the interface
1100 * @id: the device id
1102 * Called by the usb core when a new device is connected that it thinks
1103 * this driver might be interested in.
1105 static int
1106 vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
1108 struct usb_device *dev = interface_to_usbdev(intf);
1109 int bulkEndpoint = 0;
1110 const struct usb_host_interface *interface;
1111 const struct usb_endpoint_descriptor *endpoint;
1112 struct vicam_camera *cam;
1114 printk(KERN_INFO "ViCam based webcam connected\n");
1116 interface = intf->cur_altsetting;
1118 DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1119 interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
1120 endpoint = &interface->endpoint[0].desc;
1122 if ((endpoint->bEndpointAddress & 0x80) &&
1123 ((endpoint->bmAttributes & 3) == 0x02)) {
1124 /* we found a bulk in endpoint */
1125 bulkEndpoint = endpoint->bEndpointAddress;
1126 } else {
1127 printk(KERN_ERR
1128 "No bulk in endpoint was found ?! (this is bad)\n");
1131 if ((cam =
1132 kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1133 printk(KERN_WARNING
1134 "could not allocate kernel memory for vicam_camera struct\n");
1135 return -ENOMEM;
1139 cam->shutter_speed = 15;
1141 mutex_init(&cam->cam_lock);
1143 memcpy(&cam->vdev, &vicam_template,
1144 sizeof (vicam_template));
1145 cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only
1147 cam->udev = dev;
1148 cam->bulkEndpoint = bulkEndpoint;
1150 if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1151 kfree(cam);
1152 printk(KERN_WARNING "video_register_device failed\n");
1153 return -EIO;
1156 printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1158 usb_set_intfdata (intf, cam);
1160 return 0;
1163 static void
1164 vicam_disconnect(struct usb_interface *intf)
1166 int open_count;
1167 struct vicam_camera *cam = usb_get_intfdata (intf);
1168 usb_set_intfdata (intf, NULL);
1170 /* we must unregister the device before taking its
1171 * cam_lock. This is because the video open call
1172 * holds the same lock as video unregister. if we
1173 * unregister inside of the cam_lock and open also
1174 * uses the cam_lock, we get deadlock.
1177 video_unregister_device(&cam->vdev);
1179 /* stop the camera from being used */
1181 mutex_lock(&cam->cam_lock);
1183 /* mark the camera as gone */
1185 cam->udev = NULL;
1187 /* the only thing left to do is synchronize with
1188 * our close/release function on who should release
1189 * the camera memory. if there are any users using the
1190 * camera, it's their job. if there are no users,
1191 * it's ours.
1194 open_count = cam->open_count;
1196 mutex_unlock(&cam->cam_lock);
1198 if (!open_count) {
1199 kfree(cam);
1202 printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1207 static int __init
1208 usb_vicam_init(void)
1210 int retval;
1211 DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1212 retval = usb_register(&vicam_driver);
1213 if (retval)
1214 printk(KERN_WARNING "usb_register failed!\n");
1215 return retval;
1218 static void __exit
1219 usb_vicam_exit(void)
1221 DBG(KERN_INFO
1222 "ViCam-based WebCam driver shutdown\n");
1224 usb_deregister(&vicam_driver);
1227 module_init(usb_vicam_init);
1228 module_exit(usb_vicam_exit);
1230 MODULE_AUTHOR(DRIVER_AUTHOR);
1231 MODULE_DESCRIPTION(DRIVER_DESC);
1232 MODULE_LICENSE("GPL");