OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [usb/] [vicam.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
                        strcpy(b.name, "ViCam-based Camera");
485
                        b.type = VID_TYPE_CAPTURE;
486
                        b.channels = 1;
487
                        b.audios = 0;
488
                        b.maxwidth = 320;       /* VIDEOSIZE_CIF */
489
                        b.maxheight = 240;
490
                        b.minwidth = 320;       /* VIDEOSIZE_48_48 */
491
                        b.minheight = 240;
492
 
493
                        if (copy_to_user(arg, &b, sizeof (b)))
494
                                retval = -EFAULT;
495
 
496
                        break;
497
                }
498
                /* get/set video source - we are a camera and nothing else */
499
        case VIDIOCGCHAN:
500
                {
501
                        struct video_channel v;
502
 
503
                        DBG("VIDIOCGCHAN\n");
504
                        if (copy_from_user(&v, arg, sizeof (v))) {
505
                                retval = -EFAULT;
506
                                break;
507
                        }
508
                        if (v.channel != 0) {
509
                                retval = -EINVAL;
510
                                break;
511
                        }
512
 
513
                        v.channel = 0;
514
                        strcpy(v.name, "Camera");
515
                        v.tuners = 0;
516
                        v.flags = 0;
517
                        v.type = VIDEO_TYPE_CAMERA;
518
                        v.norm = 0;
519
 
520
                        if (copy_to_user(arg, &v, sizeof (v)))
521
                                retval = -EFAULT;
522
                        break;
523
                }
524
 
525
        case VIDIOCSCHAN:
526
                {
527
                        int v;
528
 
529
                        if (copy_from_user(&v, arg, sizeof (v)))
530
                                retval = -EFAULT;
531
                        DBG("VIDIOCSCHAN %d\n", v);
532
 
533
                        if (retval == 0 && v != 0)
534
                                retval = -EINVAL;
535
 
536
                        break;
537
                }
538
 
539
                /* image properties */
540
        case VIDIOCGPICT:
541
                {
542
                        struct video_picture vp;
543
                        DBG("VIDIOCGPICT\n");
544
                        memset(&vp, 0, sizeof (struct video_picture));
545
                        vp.brightness = cam->gain << 8;
546
                        vp.depth = 24;
547
                        vp.palette = VIDEO_PALETTE_RGB24;
548
                        if (copy_to_user
549
                            (arg, &vp, sizeof (struct video_picture)))
550
                                retval = -EFAULT;
551
                        break;
552
                }
553
 
554
        case VIDIOCSPICT:
555
                {
556
                        struct video_picture vp;
557
 
558
                        if(copy_from_user(&vp, (struct video_picture *) arg,
559
                                sizeof(struct video_picture)))
560
                                retval = -EFAULT;
561
 
562
                        else
563
                        {
564
                                DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
565
                                    vp.palette);
566
 
567
                                cam->gain = vp.brightness >> 8;
568
 
569
                                if (vp.depth != 24
570
                                    || vp.palette != VIDEO_PALETTE_RGB24)
571
                                        retval = -EINVAL;
572
                        }
573
 
574
                        break;
575
                }
576
 
577
                /* get/set capture window */
578
        case VIDIOCGWIN:
579
                {
580
                        struct video_window vw;
581
                        vw.x = 0;
582
                        vw.y = 0;
583
                        vw.width = 320;
584
                        vw.height = 240;
585
                        vw.chromakey = 0;
586
                        vw.flags = 0;
587
                        vw.clips = NULL;
588
                        vw.clipcount = 0;
589
 
590
                        DBG("VIDIOCGWIN\n");
591
 
592
                        if (copy_to_user
593
                            ((void *) arg, (void *) &vw, sizeof (vw)))
594
                                retval = -EFAULT;
595
 
596
                        // I'm not sure what the deal with a capture window is, it is very poorly described
597
                        // in the doc.  So I won't support it now.
598
                        break;
599
                }
600
 
601
        case VIDIOCSWIN:
602
                {
603
 
604
                        struct video_window vw;
605
 
606
                        if (copy_from_user(&vw, arg, sizeof(vw)))
607
                        {
608
                                retval = -EFAULT;
609
                                break;
610
                        }
611
 
612
                        DBG("VIDIOCSWIN %d x %d\n", vw->width, vw->height);
613
 
614
                        if ( vw.width != 320 || vw.height != 240 )
615
                                retval = -EFAULT;
616
 
617
                        break;
618
                }
619
 
620
                /* mmap interface */
621
        case VIDIOCGMBUF:
622
                {
623
                        struct video_mbuf vm;
624
                        int i;
625
 
626
                        DBG("VIDIOCGMBUF\n");
627
                        memset(&vm, 0, sizeof (vm));
628
                        vm.size =
629
                            VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
630
                        vm.frames = VICAM_FRAMES;
631
                        for (i = 0; i < VICAM_FRAMES; i++)
632
                                vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
633
 
634
                        if (copy_to_user
635
                            ((void *) arg, (void *) &vm, sizeof (vm)))
636
                                retval = -EFAULT;
637
 
638
                        break;
639
                }
640
 
641
        case VIDIOCMCAPTURE:
642
                {
643
                        struct video_mmap vm;
644
                        // int video_size;
645
 
646
                        if (copy_from_user
647
                            ((void *) &vm, (void *) arg, sizeof (vm))) {
648
                                retval = -EFAULT;
649
                                break;
650
                        }
651
 
652
                        DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
653
 
654
                        if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
655
                                retval = -EINVAL;
656
 
657
                        // in theory right here we'd start the image capturing
658
                        // (fill in a bulk urb and submit it asynchronously)
659
                        //
660
                        // Instead we're going to do a total hack job for now and
661
                        // retrieve the frame in VIDIOCSYNC
662
 
663
                        break;
664
                }
665
 
666
        case VIDIOCSYNC:
667
                {
668
                        int frame;
669
 
670
                        if (copy_from_user((void *) &frame, arg, sizeof (int))) {
671
                                retval = -EFAULT;
672
                                break;
673
                        }
674
                        DBG("VIDIOCSYNC: %d\n", frame);
675
 
676
                        read_frame(cam, frame);
677
 
678
                        break;
679
                }
680
 
681
                /* pointless to implement overlay with this camera */
682
        case VIDIOCCAPTURE:
683
        case VIDIOCGFBUF:
684
        case VIDIOCSFBUF:
685
        case VIDIOCKEY:
686
                retval = -EINVAL;
687
                break;
688
 
689
                /* tuner interface - we have none */
690
        case VIDIOCGTUNER:
691
        case VIDIOCSTUNER:
692
        case VIDIOCGFREQ:
693
        case VIDIOCSFREQ:
694
                retval = -EINVAL;
695
                break;
696
 
697
                /* audio interface - we have none */
698
        case VIDIOCGAUDIO:
699
        case VIDIOCSAUDIO:
700
                retval = -EINVAL;
701
                break;
702
        default:
703
                retval = -ENOIOCTLCMD;
704
                break;
705
        }
706
 
707
        up(&cam->busy_lock);
708
        return retval;
709
}
710
 
711
static int
712
vicam_open(struct video_device *dev, int flags)
713
{
714
        struct vicam_camera *cam =
715
            (struct vicam_camera *) dev->priv;
716
        int intr;
717
        DBG("open\n");
718
 
719
        if (!cam) {
720
                printk(KERN_ERR
721
                       "vicam video_device improperly initialized");
722
        }
723
 
724
        intr = down_interruptible(&cam->busy_lock);
725
        if (intr)
726
                return -EINTR;
727
 
728
        if (cam->is_opened) {
729
                printk(KERN_INFO
730
                       "vicam_open called on already opened camera");
731
                up(&cam->busy_lock);
732
                return -EBUSY;
733
        }
734
 
735
        if (!cam->raw_image) {
736
                cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
737
                if (!cam->raw_image) {
738
                        up(&cam->busy_lock);
739
                        return -ENOMEM;
740
                }
741
        }
742
 
743
        if (!cam->framebuf) {
744
                cam->framebuf =
745
                    usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
746
                if (!cam->framebuf) {
747
                        kfree(cam->raw_image);
748
                        up(&cam->busy_lock);
749
                        return -ENOMEM;
750
                }
751
        }
752
        // First upload firmware, then turn the camera on
753
 
754
        if (!cam->is_initialized) {
755
                initialize_camera(cam);
756
 
757
                cam->is_initialized = 1;
758
        }
759
 
760
        set_camera_power(cam, 1);
761
 
762
        cam->needsDummyRead = 1;
763
        cam->is_opened = 1;
764
 
765
        up(&cam->busy_lock);
766
 
767
        return 0;
768
}
769
 
770
static void
771
vicam_close(struct video_device *dev)
772
{
773
        struct vicam_camera *cam = (struct vicam_camera *) dev->priv;
774
        DBG("close\n");
775
 
776
 
777
        if (cam->is_removed) {
778
                vicam_purge(cam);
779
        } else {
780
                set_camera_power(cam, 0);
781
                cam->is_opened = 0;
782
        }
783
}
784
 
785
inline int pin(int x)
786
{
787
        return((x > 255) ? 255 : ((x < 0) ? 0 : x));
788
}
789
 
790
inline void writepixel(char *rgb, int Y, int Cr, int Cb)
791
{
792
        Y = 1160 * (Y - 16);
793
 
794
        rgb[2] = pin( ( ( Y + ( 1594 * Cr ) ) + 500 ) / 1300 );
795
        rgb[1] = pin( ( ( Y - (  392 * Cb ) - ( 813 * Cr ) ) + 500 ) / 1000 );
796
        rgb[0] = pin( ( ( Y + ( 2017 * Cb ) ) + 500 ) / 900 );
797
}
798
 
799
#define DATA_HEADER_SIZE 64
800
 
801
// --------------------------------------------------------------------------------
802
//      vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
803
//
804
//   Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
805
// --------------------------------------------------------------------------------
806
 
807
void vicam_decode_color( char *data, char *rgb)
808
{
809
        int x,y;
810
        int Cr, Cb;
811
        int sign;
812
        int prevX, nextX, prevY, nextY;
813
        int skip;
814
        unsigned char *src;
815
        unsigned char *dst;
816
 
817
        prevY = 512;
818
        nextY = 512;
819
 
820
        src = data + DATA_HEADER_SIZE;
821
        dst = rgb;
822
 
823
        for(y = 1; y < 241; y += 2)
824
        {
825
                // even line
826
                sign = 1;
827
                prevX = 1;
828
                nextX = 1;
829
 
830
                skip = 0;
831
 
832
                dst = rgb + (y-1)*320*3;
833
 
834
                for(x = 0; x < 512; x++)
835
                {
836
                        if(x == 512-1)
837
                                nextX = -1;
838
 
839
                        Cr = sign * ((src[prevX] - src[0]) + (src[nextX] - src[0])) >> 1;
840
                        Cb = sign * ((src[prevY] - src[prevX + prevY]) + (src[prevY] - src[nextX + prevY]) + (src[nextY] - src[prevX + nextY]) + (src[nextY] - src[nextX + nextY])) >> 2;
841
 
842
                        writepixel(
843
                                        dst + ((x*5)>>3)*3,
844
                                        src[0] + (sign * (Cr >> 1)),
845
                                        Cr,
846
                                        Cb);
847
 
848
                        src++;
849
                        sign *= -1;
850
                        prevX = -1;
851
                }
852
 
853
                prevY = -512;
854
 
855
                if(y == (242 - 2))
856
                        nextY = -512;
857
 
858
                // odd line
859
                sign = 1;
860
                prevX = 1;
861
                nextX = 1;
862
 
863
                skip = 0;
864
 
865
                dst = rgb + (y)*320*3;
866
 
867
                for(x = 0; x < 512; x++)
868
                {
869
                        if(x == 512-1)
870
                                nextX = -1;
871
 
872
                        Cr = sign * ((src[prevX + prevY] - src[prevY]) + (src[nextX + prevY] - src[prevY]) + (src[prevX + nextY] - src[nextY]) + (src[nextX + nextY] - src[nextY])) >> 2;
873
                        Cb = sign * ((src[0] - src[prevX]) + (src[0] - src[nextX])) >> 1;
874
 
875
                        writepixel(
876
                                        dst + ((x * 5)>>3)*3,
877
                                        src[0] - (sign * (Cb >> 1)),
878
                                        Cr,
879
                                        Cb);
880
 
881
                        src++;
882
                        sign *= -1;
883
                        prevX = -1;
884
                }
885
        }
886
}
887
 
888
static void
889
read_frame(struct vicam_camera *cam, int framenum)
890
{
891
        unsigned char request[16];
892
        int realShutter;
893
        int n;
894
        int actual_length;
895
 
896
        memset(request, 0, 16);
897
        request[0] = cam->gain;  // 0 = 0% gain, FF = 100% gain
898
 
899
        request[1] = 0;  // 512x242 capture
900
 
901
        request[2] = 0x90;      // the function of these two bytes
902
        request[3] = 0x07;      // is not yet understood
903
 
904
        if (cam->shutter_speed > 60) {
905
                // Short exposure
906
                realShutter =
907
                    ((-15631900 / cam->shutter_speed) + 260533) / 1000;
908
                request[4] = realShutter & 0xFF;
909
                request[5] = (realShutter >> 8) & 0xFF;
910
                request[6] = 0x03;
911
                request[7] = 0x01;
912
        } else {
913
                // Long exposure
914
                realShutter = 15600 / cam->shutter_speed - 1;
915
                request[4] = 0;
916
                request[5] = 0;
917
                request[6] = realShutter & 0xFF;
918
                request[7] = realShutter >> 8;
919
        }
920
 
921
        // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
922
        request[8] = 0;
923
        // bytes 9-15 do not seem to affect exposure or image quality
924
 
925
        n = send_control_msg(cam->udev, 0x51, 0x80, 0, request, 16);
926
 
927
        if (n < 0) {
928
                printk(KERN_ERR
929
                       " Problem sending frame capture control message");
930
                return;
931
        }
932
 
933
        n = usb_bulk_msg(cam->udev,
934
                         usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
935
                         cam->raw_image,
936
                         512 * 242 + 128, &actual_length, 500);
937
 
938
        if (n < 0) {
939
                printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
940
                       n);
941
        }
942
 
943
        vicam_decode_color(cam->raw_image,
944
                         cam->framebuf +
945
                         framenum * VICAM_MAX_FRAME_SIZE );
946
 
947
        cam->framebuf_size =
948
            320 * 240 * VICAM_BYTES_PER_PIXEL;
949
        cam->framebuf_read_start = 0;
950
 
951
        return;
952
 
953
}
954
 
955
static long
956
vicam_read(struct video_device *dev, char *buf,
957
                 unsigned long count, int noblock)
958
{
959
        struct vicam_camera *cam = dev->priv;
960
        int intr;
961
        DBG("read %d bytes.\n", (int) count);
962
 
963
        if (!buf)
964
                return -EINVAL;
965
 
966
        if (!count)
967
                return -EINVAL;
968
 
969
        // This is some code that will hopefully allow us to do shell copies from
970
        // the /dev/videoX to a file and have it actually work.
971
        if (cam->framebuf_size != 0) {
972
                if (cam->framebuf_read_start == cam->framebuf_size) {
973
                        cam->framebuf_size = cam->framebuf_read_start = 0;
974
                        return 0;
975
                } else {
976
                        if (cam->framebuf_read_start + count <=
977
                            cam->framebuf_size) {
978
                                // count does not exceed available bytes
979
                                if (copy_to_user(buf,
980
                                                 (cam->framebuf) +
981
                                                 cam->framebuf_read_start, count))
982
                                        return -EFAULT;
983
                                cam->framebuf_read_start += count;
984
                                return count;
985
                        } else {
986
                                count =
987
                                    cam->framebuf_size -
988
                                    cam->framebuf_read_start;
989
                                if (copy_to_user(buf,
990
                                                 (cam->framebuf) +
991
                                                 cam->framebuf_read_start, count))
992
                                        return -EFAULT;
993
                                cam->framebuf_read_start = cam->framebuf_size;
994
                                return count;
995
                        }
996
                }
997
        }
998
 
999
        intr = down_interruptible(&cam->busy_lock);
1000
        if (intr)
1001
                return -EINTR;
1002
 
1003
        if (cam->needsDummyRead) {
1004
                read_frame(cam, 0);
1005
                cam->needsDummyRead = 0;
1006
        }
1007
        // read_frame twice because the camera doesn't seem to take the shutter speed for the first one.
1008
 
1009
        read_frame(cam, 0);
1010
 
1011
        if (count > cam->framebuf_size)
1012
                count = cam->framebuf_size;
1013
 
1014
        if (copy_to_user(buf, cam->framebuf, count)) {
1015
                up(&cam->busy_lock);
1016
                return -EFAULT;
1017
        }
1018
 
1019
        if (count != cam->framebuf_size)
1020
                cam->framebuf_read_start = count;
1021
        else
1022
                cam->framebuf_size = 0;
1023
 
1024
        up(&cam->busy_lock);
1025
 
1026
        return count;
1027
}
1028
 
1029
static int
1030
vicam_mmap(struct video_device *dev, const char *adr, unsigned long size)
1031
{
1032
        // TODO: allocate the raw frame buffer if necessary
1033
        unsigned long start = (unsigned long) adr;
1034
        unsigned long page, pos;
1035
        struct vicam_camera *cam = dev->priv;
1036
 
1037
        if (!cam)
1038
                return -ENODEV;
1039
 
1040
        DBG("vicam_mmap: %ld\n", size);
1041
 
1042
        /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1043
         * to the size the application requested for mmap and it was screwing apps up.
1044
         if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1045
         return -EINVAL;
1046
         */
1047
 
1048
        /* make this _really_ smp-safe */
1049
        if (down_interruptible(&cam->busy_lock))
1050
                return -EINTR;
1051
 
1052
        if (!cam->framebuf) {   /* we do lazy allocation */
1053
                cam->framebuf =
1054
                    usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
1055
                if (!cam->framebuf) {
1056
                        up(&cam->busy_lock);
1057
                        return -ENOMEM;
1058
                }
1059
        }
1060
 
1061
        pos = (unsigned long) (cam->framebuf);
1062
        while (size > 0) {
1063
                page = usbvideo_kvirt_to_pa(pos);
1064
                if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {
1065
                        up(&cam->busy_lock);
1066
                        return -EAGAIN;
1067
                }
1068
                start += PAGE_SIZE;
1069
                pos += PAGE_SIZE;
1070
                if (size > PAGE_SIZE)
1071
                        size -= PAGE_SIZE;
1072
                else
1073
                        size = 0;
1074
        }
1075
 
1076
        up(&cam->busy_lock);
1077
 
1078
        return 0;
1079
}
1080
 
1081
#ifdef CONFIG_PROC_FS
1082
 
1083
static struct proc_dir_entry *vicam_proc_root = NULL;
1084
 
1085
static int
1086
vicam_read_proc(char *page, char **start, off_t off,
1087
                      int count, int *eof, void *data)
1088
{
1089
        char *out = page;
1090
        int len;
1091
        struct vicam_camera *cam = (struct vicam_camera *) data;
1092
 
1093
        out +=
1094
            sprintf(out, "Vicam-based WebCam Linux Driver.\n");
1095
        out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n");
1096
        out += sprintf(out, "vicam stats:\n");
1097
        out += sprintf(out, "    Shutter Speed: 1/%d\n", cam->shutter_speed);
1098
        out += sprintf(out, "             Gain: %d\n", cam->gain);
1099
 
1100
        len = out - page;
1101
        len -= off;
1102
        if (len < count) {
1103
                *eof = 1;
1104
                if (len <= 0)
1105
                        return 0;
1106
        } else
1107
                len = count;
1108
 
1109
        *start = page + off;
1110
        return len;
1111
}
1112
 
1113
static int
1114
vicam_write_proc(struct file *file, const char *buffer,
1115
                       unsigned long count, void *data)
1116
{
1117
        char *in;
1118
        char *start;
1119
        struct vicam_camera *cam = (struct vicam_camera *) data;
1120
 
1121
        in = kmalloc(count + 1, GFP_KERNEL);
1122
        if (!in)
1123
                return -ENOMEM;
1124
 
1125
        in[count] = 0;           // I'm not sure buffer is gauranteed to be null terminated
1126
        // so I do this to make sure I have a null in there.
1127
 
1128
        strncpy(in, buffer, count);
1129
 
1130
        start = strstr(in, "gain=");
1131
        if (start
1132
            && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
1133
                cam->gain = simple_strtoul(start + 5, NULL, 10);
1134
 
1135
        start = strstr(in, "shutter=");
1136
        if (start
1137
            && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))
1138
                cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);
1139
 
1140
        kfree(in);
1141
        return count;
1142
}
1143
 
1144
void
1145
vicam_create_proc_root(void)
1146
{
1147
        vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);
1148
 
1149
        if (vicam_proc_root)
1150
                vicam_proc_root->owner = THIS_MODULE;
1151
        else
1152
                printk(KERN_ERR
1153
                       "could not create /proc entry for vicam!");
1154
}
1155
 
1156
void
1157
vicam_destroy_proc_root(void)
1158
{
1159
        if (vicam_proc_root)
1160
                remove_proc_entry("video/vicam", 0);
1161
}
1162
 
1163
void
1164
vicam_create_proc_entry(void *ptr)
1165
{
1166
        struct vicam_camera *cam = (struct vicam_camera *) ptr;
1167
 
1168
        char name[7];
1169
        struct proc_dir_entry *ent;
1170
 
1171
        DBG(KERN_INFO "vicam: creating proc entry\n");
1172
 
1173
        if (!vicam_proc_root || !cam) {
1174
                printk(KERN_INFO
1175
                       "vicam: could not create proc entry, %s pointer is null.\n",
1176
                       (!cam ? "camera" : "root"));
1177
                return;
1178
        }
1179
 
1180
        sprintf(name, "video%d", cam->vdev.minor);
1181
 
1182
        ent =
1183
            create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,
1184
                              vicam_proc_root);
1185
        if (!ent)
1186
                return;
1187
 
1188
        ent->data = cam;
1189
        ent->read_proc = vicam_read_proc;
1190
        ent->write_proc = vicam_write_proc;
1191
        ent->size = 512;
1192
        cam->proc_entry = ent;
1193
}
1194
 
1195
void
1196
vicam_destroy_proc_entry(void *ptr)
1197
{
1198
        struct vicam_camera *cam = (struct vicam_camera *) ptr;
1199
        char name[7];
1200
 
1201
        if (!cam || !cam->proc_entry)
1202
                return;
1203
 
1204
        sprintf(name, "video%d", cam->vdev.minor);
1205
        remove_proc_entry(name, vicam_proc_root);
1206
        cam->proc_entry = NULL;
1207
 
1208
}
1209
 
1210
#endif
1211
 
1212
int
1213
vicam_video_init(struct video_device *vdev)
1214
{
1215
        // This would normally create the proc entry for this camera
1216
#ifdef CONFIG_PROC_FS
1217
        vicam_create_proc_entry(vdev->priv);
1218
#endif
1219
        return 0;
1220
}
1221
 
1222
static long
1223
vicam_write(struct video_device *v, const char *buf, unsigned long count,
1224
                  int nonblock)
1225
{
1226
 
1227
        return -EINVAL;
1228
}
1229
 
1230
static struct video_device vicam_template = {
1231
        owner:THIS_MODULE,
1232
        name:"ViCam-based USB Camera",
1233
        type:VID_TYPE_CAPTURE,
1234
        hardware:VID_HARDWARE_VICAM,
1235
        open:vicam_open,
1236
        close:vicam_close,
1237
        read:vicam_read,
1238
        write:vicam_write,
1239
        ioctl:vicam_ioctl,
1240
        mmap:vicam_mmap,
1241
        initialize:vicam_video_init,
1242
        minor:-1,
1243
};
1244
 
1245
/* table of devices that work with this driver */
1246
static struct usb_device_id vicam_table[] = {
1247
        {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1248
        {}                      /* Terminating entry */
1249
};
1250
 
1251
MODULE_DEVICE_TABLE(usb, vicam_table);
1252
 
1253
static struct usb_driver vicam_driver = {
1254
        name:"vicam",
1255
        probe:vicam_probe,
1256
        disconnect:vicam_disconnect,
1257
        id_table:vicam_table
1258
};
1259
 
1260
/**
1261
 *      vicam_probe
1262
 *
1263
 *      Called by the usb core when a new device is connected that it thinks
1264
 *      this driver might be interested in.
1265
 */
1266
static void *
1267
vicam_probe(struct usb_device *dev, unsigned int ifnum,
1268
                  const struct usb_device_id *id)
1269
{
1270
        int nas, bulkEndpoint = 0;
1271
        const struct usb_interface_descriptor *interface;
1272
        const struct usb_endpoint_descriptor *endpoint;
1273
        struct vicam_camera *cam;
1274
 
1275
        /* See if the device offered us matches what we can accept */
1276
        if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
1277
            (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
1278
                return NULL;
1279
        }
1280
 
1281
        printk(KERN_INFO "ViCam based webcam connected\n");
1282
 
1283
        nas = dev->actconfig->interface[ifnum].num_altsetting;
1284
        if (nas != 1) {
1285
                printk(KERN_WARNING
1286
                       "Expected only one alternate setting for this camera!\n");
1287
                return NULL;
1288
        }
1289
 
1290
        interface = &dev->actconfig->interface[ifnum].altsetting[0];
1291
        DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1292
               ifnum, (unsigned) (interface->bNumEndpoints));
1293
        endpoint = &interface->endpoint[0];
1294
 
1295
        if ((endpoint->bEndpointAddress & 0x80) &&
1296
            ((endpoint->bmAttributes & 3) == 0x02)) {
1297
                /* we found a bulk in endpoint */
1298
                bulkEndpoint = endpoint->bEndpointAddress;
1299
        } else {
1300
                printk(KERN_ERR
1301
                       "No bulk in endpoint was found ?! (this is bad)\n");
1302
        }
1303
 
1304
        if ((cam =
1305
             kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1306
                printk(KERN_WARNING
1307
                       "could not allocate kernel memory for vicam_camera struct\n");
1308
                return NULL;
1309
        }
1310
 
1311
        memset(cam, 0, sizeof (struct vicam_camera));
1312
 
1313
        cam->shutter_speed = 15;
1314
 
1315
        init_MUTEX(&cam->busy_lock);
1316
 
1317
        memcpy(&cam->vdev, &vicam_template,
1318
               sizeof (vicam_template));
1319
        cam->vdev.priv = cam;   // sort of a reverse mapping for those functions that get vdev only
1320
 
1321
        cam->udev = dev;
1322
        cam->bulkEndpoint = bulkEndpoint;
1323
 
1324
        if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1325
                kfree(cam);
1326
                printk(KERN_WARNING "video_register_device failed\n");
1327
                return NULL;
1328
        }
1329
 
1330
        printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1331
 
1332
        return cam;
1333
}
1334
 
1335
 
1336
static void
1337
vicam_purge(struct vicam_camera *cam)
1338
{
1339
        video_unregister_device(&cam->vdev);
1340
 
1341
#ifdef CONFIG_PROC_FS
1342
        vicam_destroy_proc_entry(cam);
1343
#endif
1344
 
1345
        if (cam->raw_image)
1346
                kfree(cam->raw_image);
1347
        if (cam->framebuf)
1348
                usbvideo_rvfree(cam->framebuf,
1349
                       VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
1350
 
1351
        kfree(cam);
1352
 
1353
        printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1354
}
1355
 
1356
static void
1357
vicam_disconnect(struct usb_device *dev, void *ptr)
1358
{
1359
        struct vicam_camera *cam = ptr;
1360
 
1361
        if (cam->is_opened) {
1362
                cam->is_removed = 1;
1363
        } else {
1364
                vicam_purge(cam);
1365
        }
1366
}
1367
 
1368
/*
1369
 */
1370
static int __init
1371
usb_vicam_init(void)
1372
{
1373
        DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1374
#ifdef CONFIG_PROC_FS
1375
        vicam_create_proc_root();
1376
#endif
1377
        if (usb_register(&vicam_driver) != 0)
1378
                printk(KERN_WARNING "usb_register failed!\n");
1379
        return 0;
1380
}
1381
 
1382
static void __exit
1383
usb_vicam_exit(void)
1384
{
1385
        DBG(KERN_INFO
1386
               "ViCam-based WebCam driver shutdown\n");
1387
 
1388
        usb_deregister(&vicam_driver);
1389
#ifdef CONFIG_PROC_FS
1390
        vicam_destroy_proc_root();
1391
#endif
1392
}
1393
 
1394
module_init(usb_vicam_init);
1395
module_exit(usb_vicam_exit);
1396
 
1397
MODULE_AUTHOR(DRIVER_AUTHOR);
1398
MODULE_DESCRIPTION(DRIVER_DESC);
1399
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.