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