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