[PATCH] USB: ZC0301 driver bugfix
[deliverable/linux.git] / drivers / usb / media / vicam.c
CommitLineData
1da177e4
LT
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>
4186ecf8 45#include <linux/mutex.h>
1da177e4
LT
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
82static 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
90static unsigned char setup2[] = {
91 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00,
92 0x00, 0x00
93};
94
95static unsigned char setup3[] = {
96 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00
97};
98
99static 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
313static 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*/
362static 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
383static 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
399struct 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 */
4186ecf8 411 struct mutex cam_lock;
1da177e4
LT
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
424static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
425static void vicam_disconnect(struct usb_interface *intf);
426static void read_frame(struct vicam_camera *cam, int framenum);
427static void vicam_decode_color(const u8 *, u8 *);
428
429static 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
457static 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;
4186ecf8 465 mutex_lock(&cam->cam_lock);
1da177e4
LT
466 if (cam->udev) {
467 status = __send_control_msg(cam, request, value,
468 index, cp, size);
469 }
4186ecf8 470 mutex_unlock(&cam->cam_lock);
1da177e4
LT
471 return status;
472}
473static int
474initialize_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
501static int
502set_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
516static int
517vicam_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
756static int
757vicam_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
816static int
817vicam_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
4186ecf8 835 mutex_lock(&cam->cam_lock);
1da177e4
LT
836
837 cam->open_count--;
838 open_count = cam->open_count;
839 udev = cam->udev;
840
4186ecf8 841 mutex_unlock(&cam->cam_lock);
1da177e4
LT
842
843 if (!open_count && !udev) {
844 kfree(cam);
845 }
846
847 return 0;
848}
849
850static 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
922static void
923read_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