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