Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * USB ViCam WebCam driver
  3  * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
  4  *                    Christopher L Cheney (ccheney@cheney.cx),
  5  *                    Pavel Machek (pavel@suse.cz),
  6  *                    John Tyner (jtyner@cs.ucr.edu),
  7  *                    Monroe Williams (monroe@pobox.com)
  8  *
  9  * Supports 3COM HomeConnect PC Digital WebCam
 10  * Supports Compro PS39U WebCam
 11  *
 12  * This program is free software; you can redistribute it and/or modify
 13  * it under the terms of the GNU General Public License as published by
 14  * the Free Software Foundation; either version 2 of the License, or
 15  * (at your option) any later version.
 16  *
 17  * This program is distributed in the hope that it will be useful,
 18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20  * GNU General Public License for more details.
 21  *
 22  * You should have received a copy of the GNU General Public License
 23  * along with this program; if not, write to the Free Software
 24  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 25  *
 26  * This source code is based heavily on the CPiA webcam driver which was
 27  * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
 28  *
 29  * Portions of this code were also copied from usbvideo.c
 30  *
 31  * Special thanks to the whole team at Sourceforge for help making
 32  * this driver become a reality.  Notably:
 33  * Andy Armstrong who reverse engineered the color encoding and
 34  * Pavel Machek and Chris Cheney who worked on reverse engineering the
 35  *    camera controls and wrote the first generation driver.
 36  */
 37 
 38 #include <linux/kernel.h>
 39 #include <linux/module.h>
 40 #include <linux/init.h>
 41 #include <linux/videodev.h>
 42 #include <linux/usb.h>
 43 #include <linux/vmalloc.h>
 44 #include <linux/slab.h>
 45 #include <linux/mutex.h>
 46 #include "usbvideo.h"
 47 
 48 // #define VICAM_DEBUG
 49 
 50 #ifdef VICAM_DEBUG
 51 #define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __FUNCTION__, lineno, ##args)
 52 #define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
 53 #else
 54 #define DBG(fmn,args...) do {} while(0)
 55 #endif
 56 
 57 #define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
 58 #define DRIVER_DESC             "ViCam WebCam Driver"
 59 
 60 /* Define these values to match your device */
 61 #define USB_VICAM_VENDOR_ID     0x04c1
 62 #define USB_VICAM_PRODUCT_ID    0x009d
 63 #define USB_COMPRO_VENDOR_ID    0x0602
 64 #define USB_COMPRO_PRODUCT_ID   0x1001
 65 
 66 #define VICAM_BYTES_PER_PIXEL   3
 67 #define VICAM_MAX_READ_SIZE     (512*242+128)
 68 #define VICAM_MAX_FRAME_SIZE    (VICAM_BYTES_PER_PIXEL*320*240)
 69 #define VICAM_FRAMES            2
 70 
 71 #define VICAM_HEADER_SIZE       64
 72 
 73 #define clamp( x, l, h )        max_t( __typeof__( x ),         \
 74                                        ( l ),                   \
 75                                        min_t( __typeof__( x ),  \
 76                                               ( h ),            \
 77                                               ( x ) ) )
 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 /* rvmalloc / rvfree copied from usbvideo.c
358  *
359  * Not sure why these are not yet non-statics which I can reference through
360  * usbvideo.h the same as it is in 2.4.20.  I bet this will get fixed sometime
361  * in the future.
362  *
363 */
364 static void *rvmalloc(unsigned long size)
365 {
366         void *mem;
367         unsigned long adr;
368 
369         size = PAGE_ALIGN(size);
370         mem = vmalloc_32(size);
371         if (!mem)
372                 return NULL;
373 
374         memset(mem, 0, size); /* Clear the ram out, no junk to the user */
375         adr = (unsigned long) mem;
376         while (size > 0) {
377                 SetPageReserved(vmalloc_to_page((void *)adr));
378                 adr += PAGE_SIZE;
379                 size -= PAGE_SIZE;
380         }
381 
382         return mem;
383 }
384 
385 static void rvfree(void *mem, unsigned long size)
386 {
387         unsigned long adr;
388 
389         if (!mem)
390                 return;
391 
392         adr = (unsigned long) mem;
393         while ((long) size > 0) {
394                 ClearPageReserved(vmalloc_to_page((void *)adr));
395                 adr += PAGE_SIZE;
396                 size -= PAGE_SIZE;
397         }
398         vfree(mem);
399 }
400 
401 struct vicam_camera {
402         u16 shutter_speed;      // capture shutter speed
403         u16 gain;               // capture gain
404 
405         u8 *raw_image;          // raw data captured from the camera
406         u8 *framebuf;           // processed data in RGB24 format
407         u8 *cntrlbuf;           // area used to send control msgs
408 
409         struct video_device vdev;       // v4l video device
410         struct usb_device *udev;        // usb device
411 
412         /* guard against simultaneous accesses to the camera */
413         struct mutex cam_lock;
414 
415         int is_initialized;
416         u8 open_count;
417         u8 bulkEndpoint;
418         int needsDummyRead;
419 };
420 
421 static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
422 static void vicam_disconnect(struct usb_interface *intf);
423 static void read_frame(struct vicam_camera *cam, int framenum);
424 static void vicam_decode_color(const u8 *, u8 *);
425 
426 static int __send_control_msg(struct vicam_camera *cam,
427                               u8 request,
428                               u16 value,
429                               u16 index,
430                               unsigned char *cp,
431                               u16 size)
432 {
433         int status;
434 
435         /* cp must be memory that has been allocated by kmalloc */
436 
437         status = usb_control_msg(cam->udev,
438                                  usb_sndctrlpipe(cam->udev, 0),
439                                  request,
440                                  USB_DIR_OUT | USB_TYPE_VENDOR |
441                                  USB_RECIP_DEVICE, value, index,
442                                  cp, size, 1000);
443 
444         status = min(status, 0);
445 
446         if (status < 0) {
447                 printk(KERN_INFO "Failed sending control message, error %d.\n",
448                        status);
449         }
450 
451         return status;
452 }
453 
454 static int send_control_msg(struct vicam_camera *cam,
455                             u8 request,
456                             u16 value,
457                             u16 index,
458                             unsigned char *cp,
459                             u16 size)
460 {
461         int status = -ENODEV;
462         mutex_lock(&cam->cam_lock);
463         if (cam->udev) {
464                 status = __send_control_msg(cam, request, value,
465                                             index, cp, size);
466         }
467         mutex_unlock(&cam->cam_lock);
468         return status;
469 }
470 static int
471 initialize_camera(struct vicam_camera *cam)
472 {
473         const struct {
474                 u8 *data;
475                 u32 size;
476         } firmware[] = {
477                 { .data = setup1, .size = sizeof(setup1) },
478                 { .data = setup2, .size = sizeof(setup2) },
479                 { .data = setup3, .size = sizeof(setup3) },
480                 { .data = setup4, .size = sizeof(setup4) },
481                 { .data = setup5, .size = sizeof(setup5) },
482                 { .data = setup3, .size = sizeof(setup3) },
483                 { .data = NULL, .size = 0 }
484         };
485 
486         int err, i;
487 
488         for (i = 0, err = 0; firmware[i].data && !err; i++) {
489                 memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
490 
491                 err = send_control_msg(cam, 0xff, 0, 0,
492                                        cam->cntrlbuf, firmware[i].size);
493         }
494 
495         return err;
496 }
497 
498 static int
499 set_camera_power(struct vicam_camera *cam, int state)
500 {
501         int status;
502 
503         if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
504                 return status;
505 
506         if (state) {
507                 send_control_msg(cam, 0x55, 1, 0, NULL, 0);
508         }
509 
510         return 0;
511 }
512 
513 static int
514 vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
515 {
516         void __user *user_arg = (void __user *)arg;
517         struct vicam_camera *cam = file->private_data;
518         int retval = 0;
519 
520         if (!cam)
521                 return -ENODEV;
522 
523         switch (ioctlnr) {
524                 /* query capabilities */
525         case VIDIOCGCAP:
526                 {
527                         struct video_capability b;
528 
529                         DBG("VIDIOCGCAP\n");
530                         memset(&b, 0, sizeof(b));
531                         strcpy(b.name, "ViCam-based Camera");
532                         b.type = VID_TYPE_CAPTURE;
533                         b.channels = 1;
534                         b.audios = 0;
535                         b.maxwidth = 320;       /* VIDEOSIZE_CIF */
536                         b.maxheight = 240;
537                         b.minwidth = 320;       /* VIDEOSIZE_48_48 */
538                         b.minheight = 240;
539 
540                         if (copy_to_user(user_arg, &b, sizeof(b)))
541                                 retval = -EFAULT;
542 
543                         break;
544                 }
545                 /* get/set video source - we are a camera and nothing else */
546         case VIDIOCGCHAN:
547                 {
548                         struct video_channel v;
549 
550                         DBG("VIDIOCGCHAN\n");
551                         if (copy_from_user(&v, user_arg, sizeof(v))) {
552                                 retval = -EFAULT;
553                                 break;
554                         }
555                         if (v.channel != 0) {
556                                 retval = -EINVAL;
557                                 break;
558                         }
559 
560                         v.channel = 0;
561                         strcpy(v.name, "Camera");
562                         v.tuners = 0;
563                         v.flags = 0;
564                         v.type = VIDEO_TYPE_CAMERA;
565                         v.norm = 0;
566 
567                         if (copy_to_user(user_arg, &v, sizeof(v)))
568                                 retval = -EFAULT;
569                         break;
570                 }
571 
572         case VIDIOCSCHAN:
573                 {
574                         int v;
575 
576                         if (copy_from_user(&v, user_arg, sizeof(v)))
577                                 retval = -EFAULT;
578                         DBG("VIDIOCSCHAN %d\n", v);
579 
580                         if (retval == 0 && v != 0)
581                                 retval = -EINVAL;
582 
583                         break;
584                 }
585 
586                 /* image properties */
587         case VIDIOCGPICT:
588                 {
589                         struct video_picture vp;
590                         DBG("VIDIOCGPICT\n");
591                         memset(&vp, 0, sizeof (struct video_picture));
592                         vp.brightness = cam->gain << 8;
593                         vp.depth = 24;
594                         vp.palette = VIDEO_PALETTE_RGB24;
595                         if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
596                                 retval = -EFAULT;
597                         break;
598                 }
599 
600         case VIDIOCSPICT:
601                 {
602                         struct video_picture vp;
603 
604                         if (copy_from_user(&vp, user_arg, sizeof(vp))) {
605                                 retval = -EFAULT;
606                                 break;
607                         }
608 
609                         DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
610                             vp.palette);
611 
612                         cam->gain = vp.brightness >> 8;
613 
614                         if (vp.depth != 24
615                             || vp.palette != VIDEO_PALETTE_RGB24)
616                                 retval = -EINVAL;
617 
618                         break;
619                 }
620 
621                 /* get/set capture window */
622         case VIDIOCGWIN:
623                 {
624                         struct video_window vw;
625                         vw.x = 0;
626                         vw.y = 0;
627                         vw.width = 320;
628                         vw.height = 240;
629                         vw.chromakey = 0;
630                         vw.flags = 0;
631                         vw.clips = NULL;
632                         vw.clipcount = 0;
633 
634                         DBG("VIDIOCGWIN\n");
635 
636                         if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
637                                 retval = -EFAULT;
638 
639                         // I'm not sure what the deal with a capture window is, it is very poorly described
640                         // in the doc.  So I won't support it now.
641                         break;
642                 }
643 
644         case VIDIOCSWIN:
645                 {
646 
647                         struct video_window vw;
648 
649                         if (copy_from_user(&vw, user_arg, sizeof(vw))) {
650                                 retval = -EFAULT;
651                                 break;
652                         }
653 
654                         DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
655 
656                         if ( vw.width != 320 || vw.height != 240 )
657                                 retval = -EFAULT;
658 
659                         break;
660                 }
661 
662                 /* mmap interface */
663         case VIDIOCGMBUF:
664                 {
665                         struct video_mbuf vm;
666                         int i;
667 
668                         DBG("VIDIOCGMBUF\n");
669                         memset(&vm, 0, sizeof (vm));
670                         vm.size =
671                             VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
672                         vm.frames = VICAM_FRAMES;
673                         for (i = 0; i < VICAM_FRAMES; i++)
674                                 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
675 
676                         if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
677                                 retval = -EFAULT;
678 
679                         break;
680                 }
681 
682         case VIDIOCMCAPTURE:
683                 {
684                         struct video_mmap vm;
685                         // int video_size;
686 
687                         if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
688                                 retval = -EFAULT;
689                                 break;
690                         }
691 
692                         DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
693 
694                         if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
695                                 retval = -EINVAL;
696 
697                         // in theory right here we'd start the image capturing
698                         // (fill in a bulk urb and submit it asynchronously)
699                         //
700                         // Instead we're going to do a total hack job for now and
701                         // retrieve the frame in VIDIOCSYNC
702 
703                         break;
704                 }
705 
706         case VIDIOCSYNC:
707                 {
708                         int frame;
709 
710                         if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
711                                 retval = -EFAULT;
712                                 break;
713                         }
714                         DBG("VIDIOCSYNC: %d\n", frame);
715 
716                         read_frame(cam, frame);
717                         vicam_decode_color(cam->raw_image,
718                                            cam->framebuf +
719                                            frame * VICAM_MAX_FRAME_SIZE );
720 
721                         break;
722                 }
723 
724                 /* pointless to implement overlay with this camera */
725         case VIDIOCCAPTURE:
726         case VIDIOCGFBUF:
727         case VIDIOCSFBUF:
728         case VIDIOCKEY:
729                 retval = -EINVAL;
730                 break;
731 
732                 /* tuner interface - we have none */
733         case VIDIOCGTUNER:
734         case VIDIOCSTUNER:
735         case VIDIOCGFREQ:
736         case VIDIOCSFREQ:
737                 retval = -EINVAL;
738                 break;
739 
740                 /* audio interface - we have none */
741         case VIDIOCGAUDIO:
742         case VIDIOCSAUDIO:
743                 retval = -EINVAL;
744                 break;
745         default:
746                 retval = -ENOIOCTLCMD;
747                 break;
748         }
749 
750         return retval;
751 }
752 
753 static int
754 vicam_open(struct inode *inode, struct file *file)
755 {
756         struct video_device *dev = video_devdata(file);
757         struct vicam_camera *cam =
758             (struct vicam_camera *) dev->priv;
759         DBG("open\n");
760 
761         if (!cam) {
762                 printk(KERN_ERR
763                        "vicam video_device improperly initialized");
764                 return -EINVAL;
765         }
766 
767         /* the videodev_lock held above us protects us from
768          * simultaneous opens...for now. we probably shouldn't
769          * rely on this fact forever.
770          */
771 
772         if (cam->open_count > 0) {
773                 printk(KERN_INFO
774                        "vicam_open called on already opened camera");
775                 return -EBUSY;
776         }
777 
778         cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
779         if (!cam->raw_image) {
780                 return -ENOMEM;
781         }
782 
783         cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
784         if (!cam->framebuf) {
785                 kfree(cam->raw_image);
786                 return -ENOMEM;
787         }
788 
789         cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
790         if (!cam->cntrlbuf) {
791                 kfree(cam->raw_image);
792                 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
793                 return -ENOMEM;
794         }
795 
796         // First upload firmware, then turn the camera on
797 
798         if (!cam->is_initialized) {
799                 initialize_camera(cam);
800 
801                 cam->is_initialized = 1;
802         }
803 
804         set_camera_power(cam, 1);
805 
806         cam->needsDummyRead = 1;
807         cam->open_count++;
808 
809         file->private_data = cam;
810 
811         return 0;
812 }
813 
814 static int
815 vicam_close(struct inode *inode, struct file *file)
816 {
817         struct vicam_camera *cam = file->private_data;
818         int open_count;
819         struct usb_device *udev;
820 
821         DBG("close\n");
822 
823         /* it's not the end of the world if
824          * we fail to turn the camera off.
825          */
826 
827         set_camera_power(cam, 0);
828 
829         kfree(cam->raw_image);
830         rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
831         kfree(cam->cntrlbuf);
832 
833         mutex_lock(&cam->cam_lock);
834 
835         cam->open_count--;
836         open_count = cam->open_count;
837         udev = cam->udev;
838 
839         mutex_unlock(&cam->cam_lock);
840 
841         if (!open_count && !udev) {
842                 kfree(cam);
843         }
844 
845         return 0;
846 }
847 
848 static void vicam_decode_color(const u8 *data, u8 *rgb)
849 {
850         /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
851          * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
852          */
853 
854         int i, prevY, nextY;
855 
856         prevY = 512;
857         nextY = 512;
858 
859         data += VICAM_HEADER_SIZE;
860 
861         for( i = 0; i < 240; i++, data += 512 ) {
862                 const int y = ( i * 242 ) / 240;
863 
864                 int j, prevX, nextX;
865                 int Y, Cr, Cb;
866 
867                 if ( y == 242 - 1 ) {
868                         nextY = -512;
869                 }
870 
871                 prevX = 1;
872                 nextX = 1;
873 
874                 for ( j = 0; j < 320; j++, rgb += 3 ) {
875                         const int x = ( j * 512 ) / 320;
876                         const u8 * const src = &data[x];
877 
878                         if ( x == 512 - 1 ) {
879                                 nextX = -1;
880                         }
881 
882                         Cr = ( src[prevX] - src[0] ) +
883                                 ( src[nextX] - src[0] );
884                         Cr /= 2;
885 
886                         Cb = ( src[prevY] - src[prevX + prevY] ) +
887                                 ( src[prevY] - src[nextX + prevY] ) +
888                                 ( src[nextY] - src[prevX + nextY] ) +
889                                 ( src[nextY] - src[nextX + nextY] );
890                         Cb /= 4;
891 
892                         Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
893 
894                         if ( i & 1 ) {
895                                 int Ct = Cr;
896                                 Cr = Cb;
897                                 Cb = Ct;
898                         }
899 
900                         if ( ( x ^ i ) & 1 ) {
901                                 Cr = -Cr;
902                                 Cb = -Cb;
903                         }
904 
905                         rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
906                                         500 ) / 900, 0, 255 );
907                         rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
908                                           ( 813 * Cr ) ) +
909                                           500 ) / 1000, 0, 255 );
910                         rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
911                                         500 ) / 1300, 0, 255 );
912 
913                         prevX = -1;
914                 }
915 
916                 prevY = -512;
917         }
918 }
919 
920 static void
921 read_frame(struct vicam_camera *cam, int framenum)
922 {
923         unsigned char *request = cam->cntrlbuf;
924         int realShutter;
925         int n;
926         int actual_length;
927 
928         if (cam->needsDummyRead) {
929                 cam->needsDummyRead = 0;
930                 read_frame(cam, framenum);
931         }
932 
933         memset(request, 0, 16);
934         request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
935 
936         request[1] = 0; // 512x242 capture
937 
938         request[2] = 0x90;      // the function of these two bytes
939         request[3] = 0x07;      // is not yet understood
940 
941         if (cam->shutter_speed > 60) {
942                 // Short exposure
943                 realShutter =
944                     ((-15631900 / cam->shutter_speed) + 260533) / 1000;
945                 request[4] = realShutter & 0xFF;
946                 request[5] = (realShutter >> 8) & 0xFF;
947                 request[6] = 0x03;
948                 request[7] = 0x01;
949         } else {
950                 // Long exposure
951                 realShutter = 15600 / cam->shutter_speed - 1;
952                 request[4] = 0;
953                 request[5] = 0;
954                 request[6] = realShutter & 0xFF;
955                 request[7] = realShutter >> 8;
956         }
957 
958         // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
959         request[8] = 0;
960         // bytes 9-15 do not seem to affect exposure or image quality
961 
962         mutex_lock(&cam->cam_lock);
963 
964         if (!cam->udev) {
965                 goto done;
966         }
967 
968         n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
969 
970         if (n < 0) {
971                 printk(KERN_ERR
972                        " Problem sending frame capture control message");
973                 goto done;
974         }
975 
976         n = usb_bulk_msg(cam->udev,
977                          usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
978                          cam->raw_image,
979                          512 * 242 + 128, &actual_length, 10000);
980 
981         if (n < 0) {
982                 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
983                        n);
984         }
985 
986  done:
987         mutex_unlock(&cam->cam_lock);
988 }
989 
990 static ssize_t
991 vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
992 {
993         struct vicam_camera *cam = file->private_data;
994 
995         DBG("read %d bytes.\n", (int) count);
996 
997         if (*ppos >= VICAM_MAX_FRAME_SIZE) {
998                 *ppos = 0;
999                 return 0;
1000         }
1001 
1002         if (*ppos == 0) {
1003                 read_frame(cam, 0);
1004                 vicam_decode_color(cam->raw_image,
1005                                    cam->framebuf +
1006                                    0 * VICAM_MAX_FRAME_SIZE);
1007         }
1008 
1009         count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
1010 
1011         if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
1012                 count = -EFAULT;
1013         } else {
1014                 *ppos += count;
1015         }
1016 
1017         if (count == VICAM_MAX_FRAME_SIZE) {
1018                 *ppos = 0;
1019         }
1020 
1021         return count;
1022 }
1023 
1024 
1025 static int
1026 vicam_mmap(struct file *file, struct vm_area_struct *vma)
1027 {
1028         // TODO: allocate the raw frame buffer if necessary
1029         unsigned long page, pos;
1030         unsigned long start = vma->vm_start;
1031         unsigned long size  = vma->vm_end-vma->vm_start;
1032         struct vicam_camera *cam = file->private_data;
1033 
1034         if (!cam)
1035                 return -ENODEV;
1036 
1037         DBG("vicam_mmap: %ld\n", size);
1038 
1039         /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1040          * to the size the application requested for mmap and it was screwing apps up.
1041          if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1042          return -EINVAL;
1043          */
1044 
1045         pos = (unsigned long)cam->framebuf;
1046         while (size > 0) {
1047                 page = vmalloc_to_pfn((void *)pos);
1048                 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1049                         return -EAGAIN;
1050 
1051                 start += PAGE_SIZE;
1052                 pos += PAGE_SIZE;
1053                 if (size > PAGE_SIZE)
1054                         size -= PAGE_SIZE;
1055                 else
1056                         size = 0;
1057         }
1058 
1059         return 0;
1060 }
1061 
1062 static const struct file_operations vicam_fops = {
1063         .owner          = THIS_MODULE,
1064         .open           = vicam_open,
1065         .release        = vicam_close,
1066         .read           = vicam_read,
1067         .mmap           = vicam_mmap,
1068         .ioctl          = vicam_ioctl,
1069         .compat_ioctl   = v4l_compat_ioctl32,
1070         .llseek         = no_llseek,
1071 };
1072 
1073 static struct video_device vicam_template = {
1074         .owner          = THIS_MODULE,
1075         .name           = "ViCam-based USB Camera",
1076         .type           = VID_TYPE_CAPTURE,
1077         .fops           = &vicam_fops,
1078         .minor          = -1,
1079 };
1080 
1081 /* table of devices that work with this driver */
1082 static struct usb_device_id vicam_table[] = {
1083         {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1084         {USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)},
1085         {}                      /* Terminating entry */
1086 };
1087 
1088 MODULE_DEVICE_TABLE(usb, vicam_table);
1089 
1090 static struct usb_driver vicam_driver = {
1091         .name           = "vicam",
1092         .probe          = vicam_probe,
1093         .disconnect     = vicam_disconnect,
1094         .id_table       = vicam_table
1095 };
1096 
1097 /**
1098  *      vicam_probe
1099  *      @intf: the interface
1100  *      @id: the device id
1101  *
1102  *      Called by the usb core when a new device is connected that it thinks
1103  *      this driver might be interested in.
1104  */
1105 static int
1106 vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
1107 {
1108         struct usb_device *dev = interface_to_usbdev(intf);
1109         int bulkEndpoint = 0;
1110         const struct usb_host_interface *interface;
1111         const struct usb_endpoint_descriptor *endpoint;
1112         struct vicam_camera *cam;
1113 
1114         printk(KERN_INFO "ViCam based webcam connected\n");
1115 
1116         interface = intf->cur_altsetting;
1117 
1118         DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1119                interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
1120         endpoint = &interface->endpoint[0].desc;
1121 
1122         if ((endpoint->bEndpointAddress & 0x80) &&
1123             ((endpoint->bmAttributes & 3) == 0x02)) {
1124                 /* we found a bulk in endpoint */
1125                 bulkEndpoint = endpoint->bEndpointAddress;
1126         } else {
1127                 printk(KERN_ERR
1128                        "No bulk in endpoint was found ?! (this is bad)\n");
1129         }
1130 
1131         if ((cam =
1132              kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1133                 printk(KERN_WARNING
1134                        "could not allocate kernel memory for vicam_camera struct\n");
1135                 return -ENOMEM;
1136         }
1137 
1138 
1139         cam->shutter_speed = 15;
1140 
1141         mutex_init(&cam->cam_lock);
1142 
1143         memcpy(&cam->vdev, &vicam_template,
1144                sizeof (vicam_template));
1145         cam->vdev.priv = cam;   // sort of a reverse mapping for those functions that get vdev only
1146 
1147         cam->udev = dev;
1148         cam->bulkEndpoint = bulkEndpoint;
1149 
1150         if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1151                 kfree(cam);
1152                 printk(KERN_WARNING "video_register_device failed\n");
1153                 return -EIO;
1154         }
1155 
1156         printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1157 
1158         usb_set_intfdata (intf, cam);
1159 
1160         return 0;
1161 }
1162 
1163 static void
1164 vicam_disconnect(struct usb_interface *intf)
1165 {
1166         int open_count;
1167         struct vicam_camera *cam = usb_get_intfdata (intf);
1168         usb_set_intfdata (intf, NULL);
1169 
1170         /* we must unregister the device before taking its
1171          * cam_lock. This is because the video open call
1172          * holds the same lock as video unregister. if we
1173          * unregister inside of the cam_lock and open also
1174          * uses the cam_lock, we get deadlock.
1175          */
1176 
1177         video_unregister_device(&cam->vdev);
1178 
1179         /* stop the camera from being used */
1180 
1181         mutex_lock(&cam->cam_lock);
1182 
1183         /* mark the camera as gone */
1184 
1185         cam->udev = NULL;
1186 
1187         /* the only thing left to do is synchronize with
1188          * our close/release function on who should release
1189          * the camera memory. if there are any users using the
1190          * camera, it's their job. if there are no users,
1191          * it's ours.
1192          */
1193 
1194         open_count = cam->open_count;
1195 
1196         mutex_unlock(&cam->cam_lock);
1197 
1198         if (!open_count) {
1199                 kfree(cam);
1200         }
1201 
1202         printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1203 }
1204 
1205 /*
1206  */
1207 static int __init
1208 usb_vicam_init(void)
1209 {
1210         int retval;
1211         DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1212         retval = usb_register(&vicam_driver);
1213         if (retval)
1214                 printk(KERN_WARNING "usb_register failed!\n");
1215         return retval;
1216 }
1217 
1218 static void __exit
1219 usb_vicam_exit(void)
1220 {
1221         DBG(KERN_INFO
1222                "ViCam-based WebCam driver shutdown\n");
1223 
1224         usb_deregister(&vicam_driver);
1225 }
1226 
1227 module_init(usb_vicam_init);
1228 module_exit(usb_vicam_exit);
1229 
1230 MODULE_AUTHOR(DRIVER_AUTHOR);
1231 MODULE_DESCRIPTION(DRIVER_DESC);
1232 MODULE_LICENSE("GPL");
1233 
  This page was automatically generated by the LXR engine.