1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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>
46#include "usbvideo.h"
47
48
49
50#ifndef MODULE_LICENSE
51#define MODULE_LICENSE(a)
52#endif
53
54#ifndef bool
55#define bool int
56#endif
57
58#ifdef VICAM_DEBUG
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)
61#else
62#define DBG(fmn,args...) do {} while(0)
63#endif
64
65
66#define DRIVER_VERSION "v1.0"
67#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
68#define DRIVER_DESC "ViCam WebCam Driver"
69
70
71#define USB_VICAM_VENDOR_ID 0x04c1
72#define USB_VICAM_PRODUCT_ID 0x009d
73
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
78
79
80
81
82
83
84static 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
90};
91
92static unsigned char setup2[] = {
93 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00,
94 0x00, 0x00
95};
96
97static unsigned char setup3[] = {
98 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00
99};
100
101static 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,
313};
314
315static 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
355};
356
357struct vicam_camera {
358 u16 shutter_speed;
359 u16 gain;
360
361 u8 *raw_image;
362 u8 *framebuf;
363
364 struct video_device vdev;
365 struct usb_device *udev;
366
367 struct semaphore busy_lock;
368
369 bool is_initialized;
370 bool is_removed;
371 bool is_opened;
372 u8 bulkEndpoint;
373 bool needsDummyRead;
374
375 u32 framebuf_size;
376 u32 framebuf_read_start;
377
378#ifdef CONFIG_PROC_FS
379 struct proc_dir_entry *proc_entry;
380#endif
381
382};
383
384static void *vicam_probe(struct usb_device *dev, unsigned int ifnum,
385 const struct usb_device_id *id);
386static void vicam_disconnect(struct usb_device *dev, void *ptr);
387static void read_frame(struct vicam_camera *cam, int framenum);
388static void vicam_purge(struct vicam_camera *cam);
389
390static int
391send_control_msg(struct usb_device *udev, u8 request, u16 value, u16 index,
392 unsigned char *cp, u16 size)
393{
394 int status;
395
396
397
398
399
400
401 unsigned char *transfer_buffer = kmalloc(size, GFP_KERNEL);
402 memcpy(transfer_buffer, cp, size);
403
404 status = usb_control_msg(udev,
405 usb_sndctrlpipe(udev, 0),
406 request,
407 USB_DIR_OUT | USB_TYPE_VENDOR |
408 USB_RECIP_DEVICE, value, index,
409 transfer_buffer, size, HZ);
410
411 kfree(transfer_buffer);
412
413 if (status < 0) {
414 printk(KERN_INFO "Failed sending control message, error %d.\n",
415 status);
416 }
417
418 return status;
419}
420
421static int
422initialize_camera(struct vicam_camera *cam)
423{
424 struct usb_device *udev = cam->udev;
425 int status;
426
427 if ((status =
428 send_control_msg(udev, 0xff, 0, 0, setup1, sizeof (setup1))) < 0)
429 return status;
430 if ((status =
431 send_control_msg(udev, 0xff, 0, 0, setup2, sizeof (setup2))) < 0)
432 return status;
433 if ((status =
434 send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
435 return status;
436 if ((status =
437 send_control_msg(udev, 0xff, 0, 0, setup4, sizeof (setup4))) < 0)
438 return status;
439 if ((status =
440 send_control_msg(udev, 0xff, 0, 0, setup5, sizeof (setup5))) < 0)
441 return status;
442 if ((status =
443 send_control_msg(udev, 0xff, 0, 0, setup3, sizeof (setup3))) < 0)
444 return status;
445
446 return 0;
447}
448
449static int
450set_camera_power(struct vicam_camera *cam, int state)
451{
452 int status;
453
454 if ((status = send_control_msg(cam->udev, 0x50, state, 0, NULL, 0)) < 0)
455 return status;
456
457 if (state) {
458 send_control_msg(cam->udev, 0x55, 1, 0, NULL, 0);
459 }
460
461 return 0;
462}
463
464static int
465vicam_ioctl(struct video_device *dev, unsigned int ioctlnr, void *arg)
466{
467 struct vicam_camera *cam = dev->priv;
468 int retval = 0;
469
470 if (!cam)
471 return -ENODEV;
472
473
474 if (down_interruptible(&cam->busy_lock))
475 return -EINTR;
476
477 switch (ioctlnr) {
478
479 case VIDIOCGCAP:
480 {
481 struct video_capability b;
482
483 DBG("VIDIOCGCAP\n");
484 strcpy(b.name, "ViCam-based Camera");
485 b.type = VID_TYPE_CAPTURE;
486 b.channels = 1;
487 b.audios = 0;
488 b.maxwidth = 320;
489 b.maxheight = 240;
490 b.minwidth = 320;
491 b.minheight = 240;
492
493 if (copy_to_user(arg, &b, sizeof (b)))
494 retval = -EFAULT;
495
496 break;
497 }
498
499 case VIDIOCGCHAN:
500 {
501 struct video_channel v;
502
503 DBG("VIDIOCGCHAN\n");
504 if (copy_from_user(&v, arg, sizeof (v))) {
505 retval = -EFAULT;
506 break;
507 }
508 if (v.channel != 0) {
509 retval = -EINVAL;
510 break;
511 }
512
513 v.channel = 0;
514 strcpy(v.name, "Camera");
515 v.tuners = 0;
516 v.flags = 0;
517 v.type = VIDEO_TYPE_CAMERA;
518 v.norm = 0;
519
520 if (copy_to_user(arg, &v, sizeof (v)))
521 retval = -EFAULT;
522 break;
523 }
524
525 case VIDIOCSCHAN:
526 {
527 int v;
528
529 if (copy_from_user(&v, arg, sizeof (v)))
530 retval = -EFAULT;
531 DBG("VIDIOCSCHAN %d\n", v);
532
533 if (retval == 0 && v != 0)
534 retval = -EINVAL;
535
536 break;
537 }
538
539
540 case VIDIOCGPICT:
541 {
542 struct video_picture vp;
543 DBG("VIDIOCGPICT\n");
544 memset(&vp, 0, sizeof (struct video_picture));
545 vp.brightness = cam->gain << 8;
546 vp.depth = 24;
547 vp.palette = VIDEO_PALETTE_RGB24;
548 if (copy_to_user
549 (arg, &vp, sizeof (struct video_picture)))
550 retval = -EFAULT;
551 break;
552 }
553
554 case VIDIOCSPICT:
555 {
556 struct video_picture vp;
557
558 if(copy_from_user(&vp, (struct video_picture *) arg,
559 sizeof(struct video_picture)))
560 retval = -EFAULT;
561
562 else
563 {
564 DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
565 vp.palette);
566
567 cam->gain = vp.brightness >> 8;
568
569 if (vp.depth != 24
570 || vp.palette != VIDEO_PALETTE_RGB24)
571 retval = -EINVAL;
572 }
573
574 break;
575 }
576
577
578 case VIDIOCGWIN:
579 {
580 struct video_window vw;
581 vw.x = 0;
582 vw.y = 0;
583 vw.width = 320;
584 vw.height = 240;
585 vw.chromakey = 0;
586 vw.flags = 0;
587 vw.clips = NULL;
588 vw.clipcount = 0;
589
590 DBG("VIDIOCGWIN\n");
591
592 if (copy_to_user
593 ((void *) arg, (void *) &vw, sizeof (vw)))
594 retval = -EFAULT;
595
596
597
598 break;
599 }
600
601 case VIDIOCSWIN:
602 {
603
604 struct video_window vw;
605
606 if (copy_from_user(&vw, arg, sizeof(vw)))
607 {
608 retval = -EFAULT;
609 break;
610 }
611
612 DBG("VIDIOCSWIN %d x %d\n", vw->width, vw->height);
613
614 if ( vw.width != 320 || vw.height != 240 )
615 retval = -EFAULT;
616
617 break;
618 }
619
620
621 case VIDIOCGMBUF:
622 {
623 struct video_mbuf vm;
624 int i;
625
626 DBG("VIDIOCGMBUF\n");
627 memset(&vm, 0, sizeof (vm));
628 vm.size =
629 VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
630 vm.frames = VICAM_FRAMES;
631 for (i = 0; i < VICAM_FRAMES; i++)
632 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
633
634 if (copy_to_user
635 ((void *) arg, (void *) &vm, sizeof (vm)))
636 retval = -EFAULT;
637
638 break;
639 }
640
641 case VIDIOCMCAPTURE:
642 {
643 struct video_mmap vm;
644
645
646 if (copy_from_user
647 ((void *) &vm, (void *) arg, sizeof (vm))) {
648 retval = -EFAULT;
649 break;
650 }
651
652 DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
653
654 if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
655 retval = -EINVAL;
656
657
658
659
660
661
662
663 break;
664 }
665
666 case VIDIOCSYNC:
667 {
668 int frame;
669
670 if (copy_from_user((void *) &frame, arg, sizeof (int))) {
671 retval = -EFAULT;
672 break;
673 }
674 DBG("VIDIOCSYNC: %d\n", frame);
675
676 read_frame(cam, frame);
677
678 break;
679 }
680
681
682 case VIDIOCCAPTURE:
683 case VIDIOCGFBUF:
684 case VIDIOCSFBUF:
685 case VIDIOCKEY:
686 retval = -EINVAL;
687 break;
688
689
690 case VIDIOCGTUNER:
691 case VIDIOCSTUNER:
692 case VIDIOCGFREQ:
693 case VIDIOCSFREQ:
694 retval = -EINVAL;
695 break;
696
697
698 case VIDIOCGAUDIO:
699 case VIDIOCSAUDIO:
700 retval = -EINVAL;
701 break;
702 default:
703 retval = -ENOIOCTLCMD;
704 break;
705 }
706
707 up(&cam->busy_lock);
708 return retval;
709}
710
711static int
712vicam_open(struct video_device *dev, int flags)
713{
714 struct vicam_camera *cam =
715 (struct vicam_camera *) dev->priv;
716 int intr;
717 DBG("open\n");
718
719 if (!cam) {
720 printk(KERN_ERR
721 "vicam video_device improperly initialized");
722 }
723
724 intr = down_interruptible(&cam->busy_lock);
725 if (intr)
726 return -EINTR;
727
728 if (cam->is_opened) {
729 printk(KERN_INFO
730 "vicam_open called on already opened camera");
731 up(&cam->busy_lock);
732 return -EBUSY;
733 }
734
735 if (!cam->raw_image) {
736 cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
737 if (!cam->raw_image) {
738 up(&cam->busy_lock);
739 return -ENOMEM;
740 }
741 }
742
743 if (!cam->framebuf) {
744 cam->framebuf =
745 usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
746 if (!cam->framebuf) {
747 kfree(cam->raw_image);
748 up(&cam->busy_lock);
749 return -ENOMEM;
750 }
751 }
752
753
754 if (!cam->is_initialized) {
755 initialize_camera(cam);
756
757 cam->is_initialized = 1;
758 }
759
760 set_camera_power(cam, 1);
761
762 cam->needsDummyRead = 1;
763 cam->is_opened = 1;
764
765 up(&cam->busy_lock);
766
767 return 0;
768}
769
770static void
771vicam_close(struct video_device *dev)
772{
773 struct vicam_camera *cam = (struct vicam_camera *) dev->priv;
774 DBG("close\n");
775
776
777 if (cam->is_removed) {
778 vicam_purge(cam);
779 } else {
780 set_camera_power(cam, 0);
781 cam->is_opened = 0;
782 }
783}
784
785inline int pin(int x)
786{
787 return((x > 255) ? 255 : ((x < 0) ? 0 : x));
788}
789
790inline void writepixel(char *rgb, int Y, int Cr, int Cb)
791{
792 Y = 1160 * (Y - 16);
793
794 rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 );
795 rgb[1] = pin( ( ( Y - ( 392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 );
796 rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );
797}
798
799#define DATA_HEADER_SIZE 64
800
801
802
803
804
805
806
807void vicam_decode_color( char *data, char *rgb)
808{
809 int x,y;
810 int Cr, Cb;
811 int sign;
812 int prevX, nextX, prevY, nextY;
813 int skip;
814 unsigned char *src;
815 unsigned char *dst;
816
817 prevY = 512;
818 nextY = 512;
819
820 src = data + DATA_HEADER_SIZE;
821 dst = rgb;
822
823 for(y = 1; y < 241; y += 2)
824 {
825
826 sign = 1;
827 prevX = 1;
828 nextX = 1;
829
830 skip = 0;
831
832 dst = rgb + (y-1)*320*3;
833
834 for(x = 0; x < 512; x++)
835 {
836 if(x == 512-1)
837 nextX = -1;
838
839 Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1;
840 Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2;
841
842 writepixel(
843 dst + ((x*5)>>3)*3,
844 src[0] + (sign * (Cr >> 1)),
845 Cr,
846 Cb);
847
848 src++;
849 sign *= -1;
850 prevX = -1;
851 }
852
853 prevY = -512;
854
855 if(y == (242 - 2))
856 nextY = -512;
857
858
859 sign = 1;
860 prevX = 1;
861 nextX = 1;
862
863 skip = 0;
864
865 dst = rgb + (y)*320*3;
866
867 for(x = 0; x < 512; x++)
868 {
869 if(x == 512-1)
870 nextX = -1;
871
872 Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2;
873 Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1;
874
875 writepixel(
876 dst + ((x * 5)>>3)*3,
877 src[0] - (sign * (Cb >> 1)),
878 Cr,
879 Cb);
880
881 src++;
882 sign *= -1;
883 prevX = -1;
884 }
885 }
886}
887
888static void
889read_frame(struct vicam_camera *cam, int framenum)
890{
891 unsigned char request[16];
892 int realShutter;
893 int n;
894 int actual_length;
895
896 memset(request, 0, 16);
897 request[0] = cam->gain;
898
899 request[1] = 0;
900
901 request[2] = 0x90;
902 request[3] = 0x07;
903
904 if (cam->shutter_speed > 60) {
905
906 realShutter =
907 ((-15631900 / cam->shutter_speed) + 260533) / 1000;
908 request[4] = realShutter & 0xFF;
909 request[5] = (realShutter >> 8) & 0xFF;
910 request[6] = 0x03;
911 request[7] = 0x01;
912 } else {
913
914 realShutter = 15600 / cam->shutter_speed - 1;
915 request[4] = 0;
916 request[5] = 0;
917 request[6] = realShutter & 0xFF;
918 request[7] = realShutter >> 8;
919 }
920
921
922 request[8] = 0;
923
924
925 n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16);
926
927 if (n < 0) {
928 printk(KERN_ERR
929 " Problem sending frame capture control message");
930 return;
931 }
932
933 n = usb_bulk_msg(cam->udev,
934 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
935 cam->raw_image,
936 512 * 242 + 128, &actual_length, 500);
937
938 if (n < 0) {
939 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
940 n);
941 }
942
943 vicam_decode_color(cam->raw_image,
944 cam->framebuf +
945 framenum * VICAM_MAX_FRAME_SIZE );
946
947 cam->framebuf_size =
948 320 * 240 * VICAM_BYTES_PER_PIXEL;
949 cam->framebuf_read_start = 0;
950
951 return;
952
953}
954
955static long
956vicam_read(struct video_device *dev, char *buf,
957 unsigned long count, int noblock)
958{
959 struct vicam_camera *cam = dev->priv;
960 int intr;
961 DBG("read %d bytes.\n", (int) count);
962
963 if (!buf)
964 return -EINVAL;
965
966 if (!count)
967 return -EINVAL;
968
969
970
971 if (cam->framebuf_size != 0) {
972 if (cam->framebuf_read_start == cam->framebuf_size) {
973 cam->framebuf_size = cam->framebuf_read_start = 0;
974 return 0;
975 } else {
976 if (cam->framebuf_read_start + count <=
977 cam->framebuf_size) {
978
979 if (copy_to_user(buf,
980 (cam->framebuf) +
981 cam->framebuf_read_start, count))
982 return -EFAULT;
983 cam->framebuf_read_start += count;
984 return count;
985 } else {
986 count =
987 cam->framebuf_size -
988 cam->framebuf_read_start;
989 if (copy_to_user(buf,
990 (cam->framebuf) +
991 cam->framebuf_read_start, count))
992 return -EFAULT;
993 cam->framebuf_read_start = cam->framebuf_size;
994 return count;
995 }
996 }
997 }
998
999 intr = down_interruptible(&cam->busy_lock);
1000 if (intr)
1001 return -EINTR;
1002
1003 if (cam->needsDummyRead) {
1004 read_frame(cam, 0);
1005 cam->needsDummyRead = 0;
1006 }
1007
1008
1009 read_frame(cam, 0);
1010
1011 if (count > cam->framebuf_size)
1012 count = cam->framebuf_size;
1013
1014 if (copy_to_user(buf, cam->framebuf, count)) {
1015 up(&cam->busy_lock);
1016 return -EFAULT;
1017 }
1018
1019 if (count != cam->framebuf_size)
1020 cam->framebuf_read_start = count;
1021 else
1022 cam->framebuf_size = 0;
1023
1024 up(&cam->busy_lock);
1025
1026 return count;
1027}
1028
1029static int
1030vicam_mmap(struct video_device *dev, const char *adr, unsigned long size)
1031{
1032
1033 unsigned long start = (unsigned long) adr;
1034 unsigned long page, pos;
1035 struct vicam_camera *cam = dev->priv;
1036
1037 if (!cam)
1038 return -ENODEV;
1039
1040 DBG("vicam_mmap: %ld\n", size);
1041
1042
1043
1044
1045
1046
1047
1048
1049 if (down_interruptible(&cam->busy_lock))
1050 return -EINTR;
1051
1052 if (!cam->framebuf) {
1053 cam->framebuf =
1054 usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
1055 if (!cam->framebuf) {
1056 up(&cam->busy_lock);
1057 return -ENOMEM;
1058 }
1059 }
1060
1061 pos = (unsigned long) (cam->framebuf);
1062 while (size > 0) {
1063 page = usbvideo_kvirt_to_pa(pos);
1064 if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
1065 up(&cam->busy_lock);
1066 return -EAGAIN;
1067 }
1068 start += PAGE_SIZE;
1069 pos += PAGE_SIZE;
1070 if (size > PAGE_SIZE)
1071 size -= PAGE_SIZE;
1072 else
1073 size = 0;
1074 }
1075
1076 up(&cam->busy_lock);
1077
1078 return 0;
1079}
1080
1081#ifdef CONFIG_PROC_FS
1082
1083static struct proc_dir_entry *vicam_proc_root = NULL;
1084
1085static int
1086vicam_read_proc(char *page, char **start, off_t off,
1087 int count, int *eof, void *data)
1088{
1089 char *out = page;
1090 int len;
1091 struct vicam_camera *cam = (struct vicam_camera *) data;
1092
1093 out +=
1094 sprintf(out, "Vicam-based WebCam Linux Driver.\n");
1095 out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n");
1096 out += sprintf(out, "vicam stats:\n");
1097 out += sprintf(out, " Shutter Speed: 1/%d\n", cam->shutter_speed);
1098 out += sprintf(out, " Gain: %d\n", cam->gain);
1099
1100 len = out - page;
1101 len -= off;
1102 if (len < count) {
1103 *eof = 1;
1104 if (len <= 0)
1105 return 0;
1106 } else
1107 len = count;
1108
1109 *start = page + off;
1110 return len;
1111}
1112
1113static int
1114vicam_write_proc(struct file *file, const char *buffer,
1115 unsigned long count, void *data)
1116{
1117 char *in;
1118 char *start;
1119 struct vicam_camera *cam = (struct vicam_camera *) data;
1120
1121 in = kmalloc(count + 1, GFP_KERNEL);
1122 if (!in)
1123 return -ENOMEM;
1124
1125 in[count] = 0;
1126
1127
1128 strncpy(in, buffer, count);
1129
1130 start = strstr(in, "gain=");
1131 if (start
1132 && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
1133 cam->gain = simple_strtoul(start + 5, NULL, 10);
1134
1135 start = strstr(in, "shutter=");
1136 if (start
1137 && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
1138 cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
1139
1140 kfree(in);
1141 return count;
1142}
1143
1144void
1145vicam_create_proc_root(void)
1146{
1147 vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
1148
1149 if (vicam_proc_root)
1150 vicam_proc_root->owner = THIS_MODULE;
1151 else
1152 printk(KERN_ERR
1153 "could not create /proc entry for vicam!");
1154}
1155
1156void
1157vicam_destroy_proc_root(void)
1158{
1159 if (vicam_proc_root)
1160 remove_proc_entry("video/vicam", 0);
1161}
1162
1163void
1164vicam_create_proc_entry(void *ptr)
1165{
1166 struct vicam_camera *cam = (struct vicam_camera *) ptr;
1167
1168 char name[7];
1169 struct proc_dir_entry *ent;
1170
1171 DBG(KERN_INFO "vicam: creating proc entry\n");
1172
1173 if (!vicam_proc_root || !cam) {
1174 printk(KERN_INFO
1175 "vicam: could not create proc entry, %s pointer is null.\n",
1176 (!cam ? "camera" : "root"));
1177 return;
1178 }
1179
1180 sprintf(name, "video%d", cam->vdev.minor);
1181
1182 ent =
1183 create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
1184 vicam_proc_root);
1185 if (!ent)
1186 return;
1187
1188 ent->data = cam;
1189 ent->read_proc = vicam_read_proc;
1190 ent->write_proc = vicam_write_proc;
1191 ent->size = 512;
1192 cam->proc_entry = ent;
1193}
1194
1195void
1196vicam_destroy_proc_entry(void *ptr)
1197{
1198 struct vicam_camera *cam = (struct vicam_camera *) ptr;
1199 char name[7];
1200
1201 if (!cam || !cam->proc_entry)
1202 return;
1203
1204 sprintf(name, "video%d", cam->vdev.minor);
1205 remove_proc_entry(name, vicam_proc_root);
1206 cam->proc_entry = NULL;
1207
1208}
1209
1210#endif
1211
1212int
1213vicam_video_init(struct video_device *vdev)
1214{
1215
1216#ifdef CONFIG_PROC_FS
1217 vicam_create_proc_entry(vdev->priv);
1218#endif
1219 return 0;
1220}
1221
1222static long
1223vicam_write(struct video_device *v, const char *buf, unsigned long count,
1224 int nonblock)
1225{
1226
1227 return -EINVAL;
1228}
1229
1230static struct video_device vicam_template = {
1231 owner:THIS_MODULE,
1232 name:"ViCam-based USB Camera",
1233 type:VID_TYPE_CAPTURE,
1234 hardware:VID_HARDWARE_VICAM,
1235 open:vicam_open,
1236 close:vicam_close,
1237 read:vicam_read,
1238 write:vicam_write,
1239 ioctl:vicam_ioctl,
1240 mmap:vicam_mmap,
1241 initialize:vicam_video_init,
1242 minor:-1,
1243};
1244
1245
1246static struct usb_device_id vicam_table[] = {
1247 {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1248 {}
1249};
1250
1251MODULE_DEVICE_TABLE(usb, vicam_table);
1252
1253static struct usb_driver vicam_driver = {
1254 name:"vicam",
1255 probe:vicam_probe,
1256 disconnect:vicam_disconnect,
1257 id_table:vicam_table
1258};
1259
1260
1261
1262
1263
1264
1265
1266static void *
1267vicam_probe(struct usb_device *dev, unsigned int ifnum,
1268 const struct usb_device_id *id)
1269{
1270 int nas, bulkEndpoint = 0;
1271 const struct usb_interface_descriptor *interface;
1272 const struct usb_endpoint_descriptor *endpoint;
1273 struct vicam_camera *cam;
1274
1275
1276 if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
1277 (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
1278 return NULL;
1279 }
1280
1281 printk(KERN_INFO "ViCam based webcam connected\n");
1282
1283 nas = dev->actconfig->interface[ifnum].num_altsetting;
1284 if (nas != 1) {
1285 printk(KERN_WARNING
1286 "Expected only one alternate setting for this camera!\n");
1287 return NULL;
1288 }
1289
1290 interface = &dev->actconfig->interface[ifnum].altsetting[0];
1291 DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1292 ifnum, (unsigned) (interface->bNumEndpoints));
1293 endpoint = &interface->endpoint[0];
1294
1295 if ((endpoint->bEndpointAddress & 0x80) &&
1296 ((endpoint->bmAttributes & 3) == 0x02)) {
1297
1298 bulkEndpoint = endpoint->bEndpointAddress;
1299 } else {
1300 printk(KERN_ERR
1301 "No bulk in endpoint was found ?! (this is bad)\n");
1302 }
1303
1304 if ((cam =
1305 kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1306 printk(KERN_WARNING
1307 "could not allocate kernel memory for vicam_camera struct\n");
1308 return NULL;
1309 }
1310
1311 memset(cam, 0, sizeof (struct vicam_camera));
1312
1313 cam->shutter_speed = 15;
1314
1315 init_MUTEX(&cam->busy_lock);
1316
1317 memcpy(&cam->vdev, &vicam_template,
1318 sizeof (vicam_template));
1319 cam->vdev.priv = cam;
1320
1321 cam->udev = dev;
1322 cam->bulkEndpoint = bulkEndpoint;
1323
1324 if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1325 kfree(cam);
1326 printk(KERN_WARNING "video_register_device failed\n");
1327 return NULL;
1328 }
1329
1330 printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1331
1332 return cam;
1333}
1334
1335
1336static void
1337vicam_purge(struct vicam_camera *cam)
1338{
1339 video_unregister_device(&cam->vdev);
1340
1341#ifdef CONFIG_PROC_FS
1342 vicam_destroy_proc_entry(cam);
1343#endif
1344
1345 if (cam->raw_image)
1346 kfree(cam->raw_image);
1347 if (cam->framebuf)
1348 usbvideo_rvfree(cam->framebuf,
1349 VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
1350
1351 kfree(cam);
1352
1353 printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1354}
1355
1356static void
1357vicam_disconnect(struct usb_device *dev, void *ptr)
1358{
1359 struct vicam_camera *cam = ptr;
1360
1361 if (cam->is_opened) {
1362 cam->is_removed = 1;
1363 } else {
1364 vicam_purge(cam);
1365 }
1366}
1367
1368
1369
1370static int __init
1371usb_vicam_init(void)
1372{
1373 DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1374#ifdef CONFIG_PROC_FS
1375 vicam_create_proc_root();
1376#endif
1377 if (usb_register(&vicam_driver) != 0)
1378 printk(KERN_WARNING "usb_register failed!\n");
1379 return 0;
1380}
1381
1382static void __exit
1383usb_vicam_exit(void)
1384{
1385 DBG(KERN_INFO
1386 "ViCam-based WebCam driver shutdown\n");
1387
1388 usb_deregister(&vicam_driver);
1389#ifdef CONFIG_PROC_FS
1390 vicam_destroy_proc_root();
1391#endif
1392}
1393
1394module_init(usb_vicam_init);
1395module_exit(usb_vicam_exit);
1396
1397MODULE_AUTHOR(DRIVER_AUTHOR);
1398MODULE_DESCRIPTION(DRIVER_DESC);
1399MODULE_LICENSE("GPL");
1400