]>
Commit | Line | Data |
---|---|---|
f512433a | 1 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/Documentation/Configure.help linux-2.4.19-pre8-konicawc/Documentation/Configure.help |
2 | --- linux-2.4.19-pre8/Documentation/Configure.help Sat May 11 01:02:03 2002 | |
3 | +++ linux-2.4.19-pre8-konicawc/Documentation/Configure.help Sat May 11 01:19:34 2002 | |
4 | @@ -13685,6 +13685,21 @@ | |
5 | The module will be called vicam.o. If you want to compile it as a | |
6 | module, say M here and read <file:Documentation/modules.txt>. | |
7 | ||
8 | +Konica based Webcam | |
9 | +CONFIG_USB_KONICAWC | |
10 | + Say Y here if you want support for webcams based on a Konica | |
11 | + chipset. This is known to work with the Intel YC76 webcam. | |
12 | + | |
13 | + This driver uses the Video For Linux API. You must enable | |
14 | + (Y or M in config) Video For Linux (under Character Devices) | |
15 | + to use this driver. Information on this API and pointers to | |
16 | + "v4l" programs may be found on the WWW at | |
17 | + <http://roadrunner.swansea.uk.linux.org/v4l.shtml>. | |
18 | + | |
19 | + This code is also available as a module ( = code which can be | |
20 | + inserted in and removed from the running kernel whenever you want). | |
21 | + The module will be called konicawc.o. If you want to compile it as | |
22 | + a module, say M here and read <file:Documentation/modules.txt>. | |
23 | ||
24 | Pegasus/Pegasus II based USB-Ethernet device support | |
25 | CONFIG_USB_PEGASUS | |
26 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/Config.in linux-2.4.19-pre8-konicawc/drivers/usb/Config.in | |
27 | --- linux-2.4.19-pre8/drivers/usb/Config.in Sat May 11 01:02:11 2002 | |
28 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/Config.in Sat May 11 01:18:02 2002 | |
29 | @@ -80,6 +80,7 @@ | |
30 | dep_tristate ' USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL | |
31 | dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL | |
32 | dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB | |
33 | + dep_tristate ' USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV | |
34 | fi | |
35 | ||
36 | comment 'USB Network adaptors' | |
37 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/Makefile linux-2.4.19-pre8-konicawc/drivers/usb/Makefile | |
38 | --- linux-2.4.19-pre8/drivers/usb/Makefile Sat May 11 01:02:11 2002 | |
39 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/Makefile Sat May 11 01:36:40 2002 | |
40 | @@ -10,7 +10,7 @@ | |
41 | ||
42 | # Objects that export symbols. | |
43 | ||
44 | -export-objs := hcd.o usb.o ov511.o pwc-uncompress.o | |
45 | +export-objs := hcd.o usb.o ov511.o pwc-uncompress.o usbvideo.o | |
46 | ||
47 | # Multipart objects. | |
48 | ||
49 | @@ -71,6 +71,7 @@ | |
50 | obj-$(CONFIG_USB_AUDIO) += audio.o | |
51 | obj-$(CONFIG_USB_EMI26) += emi26.o | |
52 | obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o | |
53 | +obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o | |
54 | obj-$(CONFIG_USB_PWC) += pwc.o | |
55 | obj-$(CONFIG_USB_DC2XX) += dc2xx.o | |
56 | obj-$(CONFIG_USB_MDC800) += mdc800.o | |
57 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/ibmcam.c linux-2.4.19-pre8-konicawc/drivers/usb/ibmcam.c | |
58 | --- linux-2.4.19-pre8/drivers/usb/ibmcam.c Sat May 11 01:02:11 2002 | |
59 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/ibmcam.c Sat May 11 01:34:30 2002 | |
60 | @@ -3899,6 +3899,17 @@ | |
61 | return uvd; | |
62 | } | |
63 | ||
64 | + | |
65 | +static struct usb_device_id id_table[] = { | |
66 | + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ | |
67 | + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ | |
68 | + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ | |
69 | + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ | |
70 | + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ | |
71 | + { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ | |
72 | + { } /* Terminating entry */ | |
73 | +}; | |
74 | + | |
75 | /* | |
76 | * ibmcam_init() | |
77 | * | |
78 | @@ -3926,7 +3937,8 @@ | |
79 | sizeof(ibmcam_t), | |
80 | "ibmcam", | |
81 | &cbTbl, | |
82 | - THIS_MODULE); | |
83 | + THIS_MODULE, | |
84 | + id_table); | |
85 | } | |
86 | ||
87 | static void __exit ibmcam_cleanup(void) | |
88 | @@ -3934,15 +3946,6 @@ | |
89 | usbvideo_Deregister(&cams); | |
90 | } | |
91 | ||
92 | -static __devinitdata struct usb_device_id id_table[] = { | |
93 | - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */ | |
94 | - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ | |
95 | - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */ | |
96 | - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ | |
97 | - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */ | |
98 | - { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */ | |
99 | - { } /* Terminating entry */ | |
100 | -}; | |
101 | MODULE_DEVICE_TABLE(usb, id_table); | |
102 | ||
103 | module_init(ibmcam_init); | |
104 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/konicawc.c linux-2.4.19-pre8-konicawc/drivers/usb/konicawc.c | |
105 | --- linux-2.4.19-pre8/drivers/usb/konicawc.c Thu Jan 1 01:00:00 1970 | |
106 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/konicawc.c Sat May 11 03:18:42 2002 | |
107 | @@ -0,0 +1,936 @@ | |
108 | +/* | |
109 | + * konicawc.c - konica webcam driver | |
110 | + * | |
111 | + * Author: Simon Evans <spse@secret.org.uk> | |
112 | + * | |
113 | + * Copyright (C) 2002 Simon Evans | |
114 | + * | |
115 | + * Licence: GPL | |
116 | + * | |
117 | + * Driver for USB webcams based on Konica chipset. This | |
118 | + * chipset is used in Intel YC76 camera. | |
119 | + * | |
120 | + */ | |
121 | + | |
122 | +#include <linux/kernel.h> | |
123 | +#include <linux/module.h> | |
124 | +#include <linux/init.h> | |
125 | + | |
126 | +//#define DEBUG | |
127 | + | |
128 | +#include "usbvideo.h" | |
129 | + | |
130 | +#define MAX_BRIGHTNESS 108 | |
131 | +#define MAX_CONTRAST 108 | |
132 | +#define MAX_SATURATION 108 | |
133 | +#define MAX_SHARPNESS 108 | |
134 | +#define MAX_WHITEBAL 372 | |
135 | +#define MAX_SPEED 6 | |
136 | + | |
137 | + | |
138 | +#define MAX_CAMERAS 1 | |
139 | + | |
140 | +#define DRIVER_VERSION "v1.3" | |
141 | +#define DRIVER_DESC "Konica Webcam driver" | |
142 | + | |
143 | +enum ctrl_req { | |
144 | + SetWhitebal = 0x01, | |
145 | + SetBrightness = 0x02, | |
146 | + SetSharpness = 0x03, | |
147 | + SetContrast = 0x04, | |
148 | + SetSaturation = 0x05, | |
149 | +}; | |
150 | + | |
151 | + | |
152 | +enum frame_sizes { | |
153 | + SIZE_160X120 = 0, | |
154 | + SIZE_160X136 = 1, | |
155 | + SIZE_176X144 = 2, | |
156 | + SIZE_320X240 = 3, | |
157 | + | |
158 | +}; | |
159 | + | |
160 | +#define MAX_FRAME_SIZE SIZE_320X240 | |
161 | + | |
162 | +static usbvideo_t *cams; | |
163 | + | |
164 | +/* Some default values for inital camera settings, | |
165 | + can be set by modprobe */ | |
166 | + | |
167 | +static int debug; | |
168 | +static enum frame_sizes size; | |
169 | +static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */ | |
170 | +static int brightness = MAX_BRIGHTNESS/2; | |
171 | +static int contrast = MAX_CONTRAST/2; | |
172 | +static int saturation = MAX_SATURATION/2; | |
173 | +static int sharpness = MAX_SHARPNESS/2; | |
174 | +static int whitebal = 3*(MAX_WHITEBAL/4); | |
175 | + | |
176 | +static int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 }; | |
177 | + | |
178 | +/* These FPS speeds are from the windows config box. They are | |
179 | + * indexed on size (0-2) and speed (0-6). Divide by 3 to get the | |
180 | + * real fps. | |
181 | + */ | |
182 | + | |
183 | +static int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 }, | |
184 | + { 24, 40, 48, 60, 72, 80, 100 }, | |
185 | + { 18, 30, 36, 45, 54, 60, 75 }, | |
186 | + { 6, 10, 12, 15, 18, 21, 25 } }; | |
187 | + | |
188 | +struct cam_size { | |
189 | + u16 width; | |
190 | + u16 height; | |
191 | + u8 cmd; | |
192 | +}; | |
193 | + | |
194 | +static struct cam_size camera_sizes[] = { { 160, 120, 0x7 }, | |
195 | + { 160, 136, 0xa }, | |
196 | + { 176, 144, 0x4 }, | |
197 | + { 320, 240, 0x5 } }; | |
198 | + | |
199 | +struct konicawc { | |
200 | + u8 brightness; /* camera uses 0 - 9, x11 for real value */ | |
201 | + u8 contrast; /* as above */ | |
202 | + u8 saturation; /* as above */ | |
203 | + u8 sharpness; /* as above */ | |
204 | + u8 white_bal; /* 0 - 33, x11 for real value */ | |
205 | + u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */ | |
206 | + u8 size; /* Frame Size */ | |
207 | + int height; | |
208 | + int width; | |
209 | + struct urb *sts_urb[USBVIDEO_NUMSBUF]; | |
210 | + u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC]; | |
211 | + struct urb *last_data_urb; | |
212 | + int lastframe; | |
213 | + int cur_frame_size; /* number of bytes in current frame size */ | |
214 | + int maxline; /* number of lines per frame */ | |
215 | + int yplanesz; /* Number of bytes in the Y plane */ | |
216 | + unsigned int skip_frame:2; | |
217 | + unsigned int buttonsts:1; | |
218 | +}; | |
219 | + | |
220 | + | |
221 | +#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0) | |
222 | +#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz) | |
223 | +#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0) | |
224 | + | |
225 | + | |
226 | +static int konicawc_ctrl_msg(uvd_t *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) | |
227 | +{ | |
228 | + int retval = usb_control_msg(uvd->dev, | |
229 | + dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0), | |
230 | + request, 0x40 | dir, value, index, buf, len, HZ); | |
231 | + return retval < 0 ? retval : 0; | |
232 | +} | |
233 | + | |
234 | + | |
235 | +static void konicawc_set_camera_size(uvd_t *uvd) | |
236 | +{ | |
237 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
238 | + | |
239 | + konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08); | |
240 | + cam->width = camera_sizes[cam->size].width; | |
241 | + cam->height = camera_sizes[cam->size].height; | |
242 | + cam->yplanesz = cam->height * cam->width; | |
243 | + cam->cur_frame_size = (cam->yplanesz * 3) / 2; | |
244 | + cam->maxline = cam->yplanesz / 256; | |
245 | + uvd->videosize = VIDEOSIZE(cam->width, cam->height); | |
246 | +} | |
247 | + | |
248 | + | |
249 | +static int konicawc_setup_on_open(uvd_t *uvd) | |
250 | +{ | |
251 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
252 | + | |
253 | + konicawc_set_misc(uvd, 0x2, 0, 0x0b); | |
254 | + dbg("setting brightness to %d (%d)", cam->brightness, | |
255 | + cam->brightness * 11); | |
256 | + konicawc_set_value(uvd, cam->brightness, SetBrightness); | |
257 | + dbg("setting white balance to %d (%d)", cam->white_bal, | |
258 | + cam->white_bal * 11); | |
259 | + konicawc_set_value(uvd, cam->white_bal, SetWhitebal); | |
260 | + dbg("setting contrast to %d (%d)", cam->contrast, | |
261 | + cam->contrast * 11); | |
262 | + konicawc_set_value(uvd, cam->contrast, SetContrast); | |
263 | + dbg("setting saturation to %d (%d)", cam->saturation, | |
264 | + cam->saturation * 11); | |
265 | + konicawc_set_value(uvd, cam->saturation, SetSaturation); | |
266 | + dbg("setting sharpness to %d (%d)", cam->sharpness, | |
267 | + cam->sharpness * 11); | |
268 | + konicawc_set_value(uvd, cam->sharpness, SetSharpness); | |
269 | + konicawc_set_camera_size(uvd); | |
270 | + konicawc_set_misc(uvd, 0x2, 1, 0x0b); | |
271 | + cam->lastframe = -1; | |
272 | + cam->skip_frame = 2; | |
273 | + cam->buttonsts = 0; | |
274 | + return 0; | |
275 | +} | |
276 | + | |
277 | + | |
278 | +static void konicawc_adjust_picture(uvd_t *uvd) | |
279 | +{ | |
280 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
281 | + | |
282 | + konicawc_set_misc(uvd, 0x2, 0, 0x0b); | |
283 | + dbg("new brightness: %d", uvd->vpic.brightness); | |
284 | + uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness; | |
285 | + if(cam->brightness != uvd->vpic.brightness / 11) { | |
286 | + cam->brightness = uvd->vpic.brightness / 11; | |
287 | + dbg("setting brightness to %d (%d)", cam->brightness, | |
288 | + cam->brightness * 11); | |
289 | + konicawc_set_value(uvd, cam->brightness, SetBrightness); | |
290 | + } | |
291 | + | |
292 | + dbg("new contrast: %d", uvd->vpic.contrast); | |
293 | + uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast; | |
294 | + if(cam->contrast != uvd->vpic.contrast / 11) { | |
295 | + cam->contrast = uvd->vpic.contrast / 11; | |
296 | + dbg("setting contrast to %d (%d)", cam->contrast, | |
297 | + cam->contrast * 11); | |
298 | + konicawc_set_value(uvd, cam->contrast, SetContrast); | |
299 | + } | |
300 | + konicawc_set_misc(uvd, 0x2, 1, 0x0b); | |
301 | +} | |
302 | + | |
303 | + | |
304 | +static int konicawc_compress_iso(uvd_t *uvd, struct urb *dataurb, struct urb *stsurb) | |
305 | +{ | |
306 | + char *cdata; | |
307 | + int i, totlen = 0; | |
308 | + unsigned char *status = stsurb->transfer_buffer; | |
309 | + int keep = 0, discard = 0, bad = 0; | |
310 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
311 | + | |
312 | + for (i = 0; i < dataurb->number_of_packets; i++) { | |
313 | + int button = cam->buttonsts; | |
314 | + unsigned char sts; | |
315 | + int n = dataurb->iso_frame_desc[i].actual_length; | |
316 | + int st = dataurb->iso_frame_desc[i].status; | |
317 | + cdata = dataurb->transfer_buffer + | |
318 | + dataurb->iso_frame_desc[i].offset; | |
319 | + | |
320 | + /* Detect and ignore errored packets */ | |
321 | + if (st < 0) { | |
322 | + if (debug >= 1) | |
323 | + err("Data error: packet=%d. len=%d. status=%d.", | |
324 | + i, n, st); | |
325 | + uvd->stats.iso_err_count++; | |
326 | + continue; | |
327 | + } | |
328 | + | |
329 | + /* Detect and ignore empty packets */ | |
330 | + if (n <= 0) { | |
331 | + uvd->stats.iso_skip_count++; | |
332 | + continue; | |
333 | + } | |
334 | + | |
335 | + /* See what the status data said about the packet */ | |
336 | + sts = *(status+stsurb->iso_frame_desc[i].offset); | |
337 | + | |
338 | + /* sts: 0x80-0xff: frame start with frame number (ie 0-7f) | |
339 | + * otherwise: | |
340 | + * bit 0 0: keep packet | |
341 | + * 1: drop packet (padding data) | |
342 | + * | |
343 | + * bit 4 0 button not clicked | |
344 | + * 1 button clicked | |
345 | + * button is used to `take a picture' (in software) | |
346 | + */ | |
347 | + | |
348 | + if(sts < 0x80) { | |
349 | + button = sts & 0x40; | |
350 | + sts &= ~0x40; | |
351 | + } | |
352 | + | |
353 | + /* work out the button status, but dont do | |
354 | + anything with it for now */ | |
355 | + | |
356 | + if(button != cam->buttonsts) { | |
357 | + dbg("button: %sclicked", button ? "" : "un"); | |
358 | + cam->buttonsts = button; | |
359 | + } | |
360 | + | |
361 | + if(sts == 0x01) { /* drop frame */ | |
362 | + discard++; | |
363 | + continue; | |
364 | + } | |
365 | + | |
366 | + if((sts > 0x01) && (sts < 0x80)) { | |
367 | + info("unknown status %2.2x", sts); | |
368 | + bad++; | |
369 | + continue; | |
370 | + } | |
371 | + | |
372 | + keep++; | |
373 | + if(sts & 0x80) { /* frame start */ | |
374 | + unsigned char marker[] = { 0, 0xff, 0, 0x00 }; | |
375 | + | |
376 | + if(cam->skip_frame == 2) { | |
377 | + cam->skip_frame--; | |
378 | + continue; | |
379 | + } | |
380 | + | |
381 | + /* Do we have enough space for this frame? */ | |
382 | +#if 0 | |
383 | + dbg("RingQueue: need %d have %d", cam->cur_frame_size + 4, RingQueue_GetFreeSpace(&uvd->dp)); | |
384 | + if(RingQueue_GetFreeSpace(&uvd->dp) < cam->cur_frame_size + 4) { | |
385 | + info("Dropping frame"); | |
386 | + cam->skip_frame = 1; | |
387 | + continue; | |
388 | + } else { | |
389 | + cam->skip_frame = 0; | |
390 | + } | |
391 | +#endif | |
392 | + cam->skip_frame = 0; | |
393 | + | |
394 | + if(debug > 1) | |
395 | + dbg("Adding Marker packet = %d, frame = %2.2x", | |
396 | + i, *(status+i)); | |
397 | + marker[3] = sts & 0x7F; | |
398 | + if(RingQueue_GetFreeSpace(&uvd->dp) < (4+n)) { | |
399 | + err("RingQueue Full! (cant add header) - Dropping frame"); | |
400 | + cam->skip_frame = 1; | |
401 | + } else { | |
402 | + RingQueue_Enqueue(&uvd->dp, marker, 4); | |
403 | + } | |
404 | + | |
405 | + totlen += 4; | |
406 | + } | |
407 | + if(cam->skip_frame) | |
408 | + continue; | |
409 | + | |
410 | + totlen += n; /* Little local accounting */ | |
411 | + if(debug > 5) | |
412 | + dbg("Adding packet %d, bytes = %d", i, n); | |
413 | + if(RingQueue_GetFreeSpace(&uvd->dp) < n) { | |
414 | + err("RingQueue Full! (want %d got %d) - Dropping frame", n, | |
415 | + RingQueue_GetFreeSpace(&uvd->dp)); | |
416 | + cam->skip_frame = 1; | |
417 | + } else { | |
418 | + RingQueue_Enqueue(&uvd->dp, cdata, n); | |
419 | + } | |
420 | + } | |
421 | + if(debug > 8) { | |
422 | + dbg("finished: keep = %d discard = %d bad = %d added %d bytes", | |
423 | + keep, discard, bad, totlen); | |
424 | + } | |
425 | + return totlen; | |
426 | +} | |
427 | + | |
428 | + | |
429 | +static void konicawc_isoc_irq(struct urb *urb) | |
430 | +{ | |
431 | + int i, len = 0; | |
432 | + uvd_t *uvd = urb->context; | |
433 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
434 | + | |
435 | + /* We don't want to do anything if we are about to be removed! */ | |
436 | + if (!CAMERA_IS_OPERATIONAL(uvd)) | |
437 | + return; | |
438 | + | |
439 | + if(urb->status) { | |
440 | + if(urb->status == -EOVERFLOW) { | |
441 | + dbg("isoc_irq: got babble"); | |
442 | + } else if(urb->status == -ENOENT || urb->status == -EINPROGRESS) { | |
443 | + dbg("isoc_irq: URB unlinked"); | |
444 | + } else { | |
445 | + dbg("isoc_irq: status %d", urb->status); | |
446 | + } | |
447 | + return; | |
448 | + } | |
449 | + | |
450 | + if (urb->actual_length > 32) { | |
451 | + cam->last_data_urb = urb; | |
452 | + return; | |
453 | + } | |
454 | + | |
455 | + if (!uvd->streaming) { | |
456 | + if (debug >= 1) | |
457 | + info("Not streaming, but interrupt!"); | |
458 | + return; | |
459 | + } | |
460 | + | |
461 | + uvd->stats.urb_count++; | |
462 | + if (urb->actual_length <= 0) | |
463 | + goto urb_done_with; | |
464 | + | |
465 | + /* Copy the data received into ring queue */ | |
466 | + if(cam->last_data_urb) { | |
467 | + len = konicawc_compress_iso(uvd, cam->last_data_urb, urb); | |
468 | + for (i = 0; i < FRAMES_PER_DESC; i++) { | |
469 | + cam->last_data_urb->iso_frame_desc[i].status = 0; | |
470 | + cam->last_data_urb->iso_frame_desc[i].actual_length = 0; | |
471 | + } | |
472 | + cam->last_data_urb = NULL; | |
473 | + } | |
474 | + uvd->stats.urb_length = len; | |
475 | + uvd->stats.data_count += len; | |
476 | + | |
477 | + if(RingQueue_GetLength(&uvd->dp) >= 384) | |
478 | + RingQueue_WakeUpInterruptible(&uvd->dp); | |
479 | + | |
480 | +urb_done_with: | |
481 | + | |
482 | + for (i = 0; i < FRAMES_PER_DESC; i++) { | |
483 | + urb->iso_frame_desc[i].status = 0; | |
484 | + urb->iso_frame_desc[i].actual_length = 0; | |
485 | + } | |
486 | + return; | |
487 | +} | |
488 | + | |
489 | + | |
490 | +static int konicawc_start_data(uvd_t *uvd) | |
491 | +{ | |
492 | + struct usb_device *dev = uvd->dev; | |
493 | + int i, errFlag; | |
494 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
495 | + int pktsz; | |
496 | + struct usb_interface_descriptor *interface; | |
497 | + | |
498 | + interface = &dev->actconfig->interface[uvd->iface].altsetting[spd_to_iface[cam->speed]]; | |
499 | + pktsz = interface->endpoint[1].wMaxPacketSize; | |
500 | + dbg("pktsz = %d", pktsz); | |
501 | + if (!CAMERA_IS_OPERATIONAL(uvd)) { | |
502 | + err("Camera is not operational"); | |
503 | + return -EFAULT; | |
504 | + } | |
505 | + uvd->curframe = -1; | |
506 | + | |
507 | + /* Alternate interface 1 is is the biggest frame size */ | |
508 | + i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive); | |
509 | + if (i < 0) { | |
510 | + err("usb_set_interface error"); | |
511 | + uvd->last_error = i; | |
512 | + return -EBUSY; | |
513 | + } | |
514 | + | |
515 | + /* We double buffer the Iso lists */ | |
516 | + for (i=0; i < USBVIDEO_NUMSBUF; i++) { | |
517 | + int j, k; | |
518 | + struct urb *urb = uvd->sbuf[i].urb; | |
519 | + urb->dev = dev; | |
520 | + urb->context = uvd; | |
521 | + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp); | |
522 | + urb->transfer_flags = USB_ISO_ASAP; | |
523 | + urb->transfer_buffer = uvd->sbuf[i].data; | |
524 | + urb->complete = konicawc_isoc_irq; | |
525 | + urb->number_of_packets = FRAMES_PER_DESC; | |
526 | + urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; | |
527 | + for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { | |
528 | + urb->iso_frame_desc[j].offset = k; | |
529 | + urb->iso_frame_desc[j].length = pktsz; | |
530 | + } | |
531 | + | |
532 | + urb = cam->sts_urb[i]; | |
533 | + urb->dev = dev; | |
534 | + urb->context = uvd; | |
535 | + urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1); | |
536 | + urb->transfer_flags = USB_ISO_ASAP; | |
537 | + urb->transfer_buffer = cam->sts_buf[i]; | |
538 | + urb->complete = konicawc_isoc_irq; | |
539 | + urb->number_of_packets = FRAMES_PER_DESC; | |
540 | + urb->transfer_buffer_length = FRAMES_PER_DESC; | |
541 | + for (j=0; j < FRAMES_PER_DESC; j++) { | |
542 | + urb->iso_frame_desc[j].offset = j; | |
543 | + urb->iso_frame_desc[j].length = 1; | |
544 | + } | |
545 | + } | |
546 | + | |
547 | + cam->last_data_urb = NULL; | |
548 | + | |
549 | + /* Link URBs into a ring so that they invoke each other infinitely */ | |
550 | + for (i=0; i < USBVIDEO_NUMSBUF; i++) { | |
551 | + if ((i+1) < USBVIDEO_NUMSBUF) { | |
552 | + cam->sts_urb[i]->next = uvd->sbuf[i].urb; | |
553 | + uvd->sbuf[i].urb->next = cam->sts_urb[i+1]; | |
554 | + } else { | |
555 | + cam->sts_urb[i]->next = uvd->sbuf[i].urb; | |
556 | + uvd->sbuf[i].urb->next = cam->sts_urb[0]; | |
557 | + } | |
558 | + } | |
559 | + | |
560 | + /* Submit all URBs */ | |
561 | + for (i=0; i < USBVIDEO_NUMSBUF; i++) { | |
562 | + errFlag = usb_submit_urb(uvd->sbuf[i].urb); | |
563 | + if (errFlag) | |
564 | + err ("usb_submit_isoc(%d) ret %d", i, errFlag); | |
565 | + | |
566 | + errFlag = usb_submit_urb(cam->sts_urb[i]); | |
567 | + if (errFlag) | |
568 | + err("usb_submit_isoc(%d) ret %d", i, errFlag); | |
569 | + } | |
570 | + | |
571 | + uvd->streaming = 1; | |
572 | + if (debug > 1) | |
573 | + dbg("streaming=1 video_endp=$%02x", uvd->video_endp); | |
574 | + return 0; | |
575 | +} | |
576 | + | |
577 | + | |
578 | +static void konicawc_stop_data(uvd_t *uvd) | |
579 | +{ | |
580 | + int i, j; | |
581 | + struct konicawc *cam; | |
582 | + | |
583 | + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) | |
584 | + return; | |
585 | + | |
586 | + cam = (struct konicawc *)uvd->user_data; | |
587 | + cam->last_data_urb = NULL; | |
588 | + | |
589 | + /* Unschedule all of the iso td's */ | |
590 | + for (i=0; i < USBVIDEO_NUMSBUF; i++) { | |
591 | + j = usb_unlink_urb(uvd->sbuf[i].urb); | |
592 | + if (j < 0) | |
593 | + err("usb_unlink_urb() error %d.", j); | |
594 | + | |
595 | + j = usb_unlink_urb(cam->sts_urb[i]); | |
596 | + if (j < 0) | |
597 | + err("usb_unlink_urb() error %d.", j); | |
598 | + } | |
599 | + | |
600 | + uvd->streaming = 0; | |
601 | + | |
602 | + if (!uvd->remove_pending) { | |
603 | + /* Set packet size to 0 */ | |
604 | + j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive); | |
605 | + if (j < 0) { | |
606 | + err("usb_set_interface() error %d.", j); | |
607 | + uvd->last_error = j; | |
608 | + } | |
609 | + } | |
610 | +} | |
611 | + | |
612 | + | |
613 | +static void konicawc_process_isoc(uvd_t *uvd, usbvideo_frame_t *frame) | |
614 | +{ | |
615 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
616 | + int maxline = cam->maxline; | |
617 | + int yplanesz = cam->yplanesz; | |
618 | + | |
619 | + assert(frame != NULL); | |
620 | + | |
621 | + if(debug > 5) | |
622 | + dbg("maxline = %d yplanesz = %d", maxline, yplanesz); | |
623 | + | |
624 | + if(debug > 3) | |
625 | + dbg("Frame state = %d", frame->scanstate); | |
626 | + | |
627 | + if(frame->scanstate == ScanState_Scanning) { | |
628 | + int drop = 0; | |
629 | + int curframe; | |
630 | + int fdrops = 0; | |
631 | + if(debug > 3) | |
632 | + dbg("Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp)); | |
633 | + while(RingQueue_GetLength(&uvd->dp) >= 4) { | |
634 | + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && | |
635 | + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && | |
636 | + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && | |
637 | + (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) { | |
638 | + curframe = RING_QUEUE_PEEK(&uvd->dp, 3); | |
639 | + if(cam->lastframe != -1) { | |
640 | + fdrops = (0x80 + curframe - cam->lastframe) & 0x7F; | |
641 | + fdrops--; | |
642 | + if(fdrops) { | |
643 | + info("Dropped %d frames (%d -> %d)", fdrops, | |
644 | + cam->lastframe, curframe); | |
645 | + } | |
646 | + } | |
647 | + cam->lastframe = curframe; | |
648 | + frame->curline = 0; | |
649 | + frame->scanstate = ScanState_Lines; | |
650 | + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); | |
651 | + break; | |
652 | + } | |
653 | + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); | |
654 | + drop++; | |
655 | + } | |
656 | + if(drop) | |
657 | + dbg("dropped %d bytes looking for new frame", drop); | |
658 | + } | |
659 | + | |
660 | + if(frame->scanstate == ScanState_Scanning) | |
661 | + return; | |
662 | + | |
663 | + /* Try to move data from queue into frame buffer | |
664 | + * We get data in blocks of 384 bytes made up of: | |
665 | + * 256 Y, 64 U, 64 V. | |
666 | + * This needs to be written out as a Y plane, a U plane and a V plane. | |
667 | + */ | |
668 | + | |
669 | + while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) { | |
670 | + /* Y */ | |
671 | + RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256); | |
672 | + /* U */ | |
673 | + RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64); | |
674 | + /* V */ | |
675 | + RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64); | |
676 | + frame->seqRead_Length += 384; | |
677 | + frame->curline++; | |
678 | + } | |
679 | + /* See if we filled the frame */ | |
680 | + if (frame->curline == maxline) { | |
681 | + if(debug > 5) | |
682 | + dbg("got whole frame"); | |
683 | + | |
684 | + frame->frameState = FrameState_Done_Hold; | |
685 | + frame->curline = 0; | |
686 | + uvd->curframe = -1; | |
687 | + uvd->stats.frame_num++; | |
688 | + } | |
689 | +} | |
690 | + | |
691 | + | |
692 | +static int konicawc_find_fps(int size, int fps) | |
693 | +{ | |
694 | + int i; | |
695 | + | |
696 | + fps *= 3; | |
697 | + dbg("konica_find_fps: size = %d fps = %d", size, fps); | |
698 | + if(fps <= spd_to_fps[size][0]) | |
699 | + return 0; | |
700 | + | |
701 | + if(fps >= spd_to_fps[size][MAX_SPEED]) | |
702 | + return MAX_SPEED; | |
703 | + | |
704 | + for(i = 0; i < MAX_SPEED; i++) { | |
705 | + if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) { | |
706 | + dbg("fps %d between %d and %d", fps, i, i+1); | |
707 | + if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps)) | |
708 | + return i; | |
709 | + else | |
710 | + return i+1; | |
711 | + } | |
712 | + } | |
713 | + return MAX_SPEED+1; | |
714 | +} | |
715 | + | |
716 | + | |
717 | +static int konicawc_set_video_mode(uvd_t *uvd, int x, int y, int fps) | |
718 | +{ | |
719 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
720 | + int newspeed = cam->speed; | |
721 | + int newsize; | |
722 | + | |
723 | + if(x > 0 && y > 0) { | |
724 | + if(debug >= 2) | |
725 | + dbg("trying to find size %d,%d", x, y); | |
726 | + for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { | |
727 | + if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y)) | |
728 | + break; | |
729 | + } | |
730 | + } else { | |
731 | + newsize = cam->size; | |
732 | + } | |
733 | + | |
734 | + if(newsize > MAX_FRAME_SIZE) { | |
735 | + dbg("couldnt find size %d,%d", x, y); | |
736 | + return -EINVAL; | |
737 | + } | |
738 | + | |
739 | + if(fps > 0) { | |
740 | + dbg("trying to set fps to %d", fps); | |
741 | + newspeed = konicawc_find_fps(newsize, fps); | |
742 | + dbg("find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]); | |
743 | + } | |
744 | + | |
745 | + if(newspeed > MAX_SPEED) | |
746 | + return -EINVAL; | |
747 | + | |
748 | + dbg("setting size to %d speed to %d", newsize, newspeed); | |
749 | + if((newsize == cam->size) && (newspeed == cam->speed)) { | |
750 | + dbg("Nothing to do"); | |
751 | + return 0; | |
752 | + } | |
753 | + info("setting to %dx%d @ %d fps", camera_sizes[newsize].width, | |
754 | + camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3); | |
755 | + | |
756 | + konicawc_stop_data(uvd); | |
757 | + konicawc_set_misc(uvd, 0x2, 0, 0x0b); | |
758 | + uvd->ifaceAltActive = spd_to_iface[newspeed]; | |
759 | + dbg("new interface = %d", uvd->ifaceAltActive); | |
760 | + cam->speed = newspeed; | |
761 | + | |
762 | + if(cam->size != newsize) { | |
763 | + cam->size = newsize; | |
764 | + konicawc_set_camera_size(uvd); | |
765 | + } | |
766 | + | |
767 | + /* Flush the input queue and clear any current frame in progress */ | |
768 | + | |
769 | + RingQueue_Flush(&uvd->dp); | |
770 | + cam->skip_frame = 2; | |
771 | + cam->lastframe = -1; | |
772 | + if(uvd->curframe != -1) { | |
773 | + uvd->frame[uvd->curframe].curline = 0; | |
774 | + uvd->frame[uvd->curframe].seqRead_Length = 0; | |
775 | + uvd->frame[uvd->curframe].seqRead_Index = 0; | |
776 | + } | |
777 | + | |
778 | + konicawc_set_misc(uvd, 0x2, 1, 0x0b); | |
779 | + konicawc_start_data(uvd); | |
780 | + return 0; | |
781 | +} | |
782 | + | |
783 | + | |
784 | +static int konicawc_calculate_fps(uvd_t *uvd) | |
785 | +{ | |
786 | + struct konicawc *cam = uvd->user_data; | |
787 | + return spd_to_fps[cam->size][cam->speed]/3; | |
788 | +} | |
789 | + | |
790 | + | |
791 | +static void konicawc_configure_video(uvd_t *uvd) | |
792 | +{ | |
793 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
794 | + u8 buf[2]; | |
795 | + | |
796 | + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); | |
797 | + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); | |
798 | + | |
799 | + RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS); | |
800 | + RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST); | |
801 | + RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION); | |
802 | + RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS); | |
803 | + RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL); | |
804 | + | |
805 | + cam->brightness = brightness / 11; | |
806 | + cam->contrast = contrast / 11; | |
807 | + cam->saturation = saturation / 11; | |
808 | + cam->sharpness = sharpness / 11; | |
809 | + cam->white_bal = whitebal / 11; | |
810 | + | |
811 | + uvd->vpic.colour = 108; | |
812 | + uvd->vpic.hue = 108; | |
813 | + uvd->vpic.brightness = brightness; | |
814 | + uvd->vpic.contrast = contrast; | |
815 | + uvd->vpic.whiteness = whitebal; | |
816 | + uvd->vpic.depth = 6; | |
817 | + uvd->vpic.palette = VIDEO_PALETTE_YUV420P; | |
818 | + | |
819 | + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); | |
820 | + strcpy(uvd->vcap.name, "Konica Webcam"); | |
821 | + uvd->vcap.type = VID_TYPE_CAPTURE; | |
822 | + uvd->vcap.channels = 1; | |
823 | + uvd->vcap.audios = 0; | |
824 | + uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; | |
825 | + uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; | |
826 | + uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; | |
827 | + uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; | |
828 | + | |
829 | + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); | |
830 | + uvd->vchan.flags = 0 ; | |
831 | + uvd->vchan.tuners = 0; | |
832 | + uvd->vchan.channel = 0; | |
833 | + uvd->vchan.type = VIDEO_TYPE_CAMERA; | |
834 | + strcpy(uvd->vchan.name, "Camera"); | |
835 | + | |
836 | + /* Talk to device */ | |
837 | + dbg("device init"); | |
838 | + if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) | |
839 | + dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]); | |
840 | + if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2)) | |
841 | + dbg("3,10 -> %2.2x %2.2x", buf[0], buf[1]); | |
842 | + if(konicawc_set_misc(uvd, 0x2, 0, 0xd)) | |
843 | + dbg("2,0,d failed"); | |
844 | + dbg("setting initial values"); | |
845 | +} | |
846 | + | |
847 | + | |
848 | +static void *konicawc_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *devid) | |
849 | +{ | |
850 | + uvd_t *uvd = NULL; | |
851 | + int i, nas; | |
852 | + int actInterface=-1, inactInterface=-1, maxPS=0; | |
853 | + unsigned char video_ep = 0; | |
854 | + | |
855 | + if (debug >= 1) | |
856 | + dbg("konicawc_probe(%p,%u.)", dev, ifnum); | |
857 | + | |
858 | + /* We don't handle multi-config cameras */ | |
859 | + if (dev->descriptor.bNumConfigurations != 1) | |
860 | + return NULL; | |
861 | + | |
862 | + info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice); | |
863 | + RESTRICT_TO_RANGE(speed, 0, MAX_SPEED); | |
864 | + | |
865 | + /* Validate found interface: must have one ISO endpoint */ | |
866 | + nas = dev->actconfig->interface[ifnum].num_altsetting; | |
867 | + if (nas != 8) { | |
868 | + err("Incorrect number of alternate settings (%d) for this camera!", nas); | |
869 | + return NULL; | |
870 | + } | |
871 | + /* Validate all alternate settings */ | |
872 | + for (i=0; i < nas; i++) { | |
873 | + const struct usb_interface_descriptor *interface; | |
874 | + const struct usb_endpoint_descriptor *endpoint; | |
875 | + | |
876 | + interface = &dev->actconfig->interface[ifnum].altsetting[i]; | |
877 | + if (interface->bNumEndpoints != 2) { | |
878 | + err("Interface %d. has %u. endpoints!", | |
879 | + ifnum, (unsigned)(interface->bNumEndpoints)); | |
880 | + return NULL; | |
881 | + } | |
882 | + endpoint = &interface->endpoint[1]; | |
883 | + dbg("found endpoint: addr: 0x%2.2x maxps = 0x%4.4x", | |
884 | + endpoint->bEndpointAddress, endpoint->wMaxPacketSize); | |
885 | + if (video_ep == 0) | |
886 | + video_ep = endpoint->bEndpointAddress; | |
887 | + else if (video_ep != endpoint->bEndpointAddress) { | |
888 | + err("Alternate settings have different endpoint addresses!"); | |
889 | + return NULL; | |
890 | + } | |
891 | + if ((endpoint->bmAttributes & 0x03) != 0x01) { | |
892 | + err("Interface %d. has non-ISO endpoint!", ifnum); | |
893 | + return NULL; | |
894 | + } | |
895 | + if ((endpoint->bEndpointAddress & 0x80) == 0) { | |
896 | + err("Interface %d. has ISO OUT endpoint!", ifnum); | |
897 | + return NULL; | |
898 | + } | |
899 | + if (endpoint->wMaxPacketSize == 0) { | |
900 | + if (inactInterface < 0) | |
901 | + inactInterface = i; | |
902 | + else { | |
903 | + err("More than one inactive alt. setting!"); | |
904 | + return NULL; | |
905 | + } | |
906 | + } else { | |
907 | + if (i == spd_to_iface[speed]) { | |
908 | + /* This one is the requested one */ | |
909 | + actInterface = i; | |
910 | + } | |
911 | + } | |
912 | + if(endpoint->wMaxPacketSize > maxPS) | |
913 | + maxPS = endpoint->wMaxPacketSize; | |
914 | + } | |
915 | + if(actInterface == -1) { | |
916 | + err("Cant find required endpoint"); | |
917 | + return NULL; | |
918 | + } | |
919 | + | |
920 | + dbg("Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS); | |
921 | + | |
922 | + /* Code below may sleep, need to lock module while we are here */ | |
923 | + MOD_INC_USE_COUNT; | |
924 | + uvd = usbvideo_AllocateDevice(cams); | |
925 | + if (uvd != NULL) { | |
926 | + struct konicawc *cam = (struct konicawc *)(uvd->user_data); | |
927 | + /* Here uvd is a fully allocated uvd_t object */ | |
928 | + for(i = 0; i < USBVIDEO_NUMSBUF; i++) { | |
929 | + cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC); | |
930 | + if(cam->sts_urb[i] == NULL) { | |
931 | + while(i--) { | |
932 | + usb_free_urb(cam->sts_urb[i]); | |
933 | + } | |
934 | + err("cant allocate urbs"); | |
935 | + return NULL; | |
936 | + } | |
937 | + } | |
938 | + cam->speed = speed; | |
939 | + RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); | |
940 | + cam->width = camera_sizes[size].width; | |
941 | + cam->height = camera_sizes[size].height; | |
942 | + cam->size = size; | |
943 | + | |
944 | + uvd->flags = 0; | |
945 | + uvd->debug = debug; | |
946 | + uvd->dev = dev; | |
947 | + uvd->iface = ifnum; | |
948 | + uvd->ifaceAltInactive = inactInterface; | |
949 | + uvd->ifaceAltActive = actInterface; | |
950 | + uvd->video_endp = video_ep; | |
951 | + uvd->iso_packet_len = maxPS; | |
952 | + uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P; | |
953 | + uvd->defaultPalette = VIDEO_PALETTE_YUV420P; | |
954 | + uvd->canvas = VIDEOSIZE(320, 240); | |
955 | + uvd->videosize = VIDEOSIZE(cam->width, cam->height); | |
956 | + | |
957 | + /* Initialize konicawc specific data */ | |
958 | + konicawc_configure_video(uvd); | |
959 | + | |
960 | + i = usbvideo_RegisterVideoDevice(uvd); | |
961 | + uvd->max_frame_size = (320 * 240 * 3)/2; | |
962 | + if (i != 0) { | |
963 | + err("usbvideo_RegisterVideoDevice() failed."); | |
964 | + uvd = NULL; | |
965 | + } | |
966 | + } | |
967 | + MOD_DEC_USE_COUNT; | |
968 | + return uvd; | |
969 | +} | |
970 | + | |
971 | + | |
972 | +static void konicawc_free_uvd(uvd_t *uvd) | |
973 | +{ | |
974 | + int i; | |
975 | + struct konicawc *cam = (struct konicawc *)uvd->user_data; | |
976 | + | |
977 | + for (i=0; i < USBVIDEO_NUMSBUF; i++) { | |
978 | + usb_free_urb(cam->sts_urb[i]); | |
979 | + cam->sts_urb[i] = NULL; | |
980 | + } | |
981 | +} | |
982 | + | |
983 | + | |
984 | +static struct usb_device_id id_table[] = { | |
985 | + { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */ | |
986 | + { } /* Terminating entry */ | |
987 | +}; | |
988 | + | |
989 | + | |
990 | +static int __init konicawc_init(void) | |
991 | +{ | |
992 | + usbvideo_cb_t cbTbl; | |
993 | + info(DRIVER_DESC " " DRIVER_VERSION); | |
994 | + memset(&cbTbl, 0, sizeof(cbTbl)); | |
995 | + cbTbl.probe = konicawc_probe; | |
996 | + cbTbl.setupOnOpen = konicawc_setup_on_open; | |
997 | + cbTbl.processData = konicawc_process_isoc; | |
998 | + cbTbl.getFPS = konicawc_calculate_fps; | |
999 | + cbTbl.setVideoMode = konicawc_set_video_mode; | |
1000 | + cbTbl.startDataPump = konicawc_start_data; | |
1001 | + cbTbl.stopDataPump = konicawc_stop_data; | |
1002 | + cbTbl.adjustPicture = konicawc_adjust_picture; | |
1003 | + cbTbl.userFree = konicawc_free_uvd; | |
1004 | + return usbvideo_register( | |
1005 | + &cams, | |
1006 | + MAX_CAMERAS, | |
1007 | + sizeof(struct konicawc), | |
1008 | + "konicawc", | |
1009 | + &cbTbl, | |
1010 | + THIS_MODULE, | |
1011 | + id_table); | |
1012 | +} | |
1013 | + | |
1014 | + | |
1015 | +static void __exit konicawc_cleanup(void) | |
1016 | +{ | |
1017 | + usbvideo_Deregister(&cams); | |
1018 | +} | |
1019 | + | |
1020 | + | |
1021 | +MODULE_DEVICE_TABLE(usb, id_table); | |
1022 | + | |
1023 | +MODULE_LICENSE("GPL"); | |
1024 | +MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>"); | |
1025 | +MODULE_DESCRIPTION(DRIVER_DESC); | |
1026 | +MODULE_PARM(speed, "i"); | |
1027 | +MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)"); | |
1028 | +MODULE_PARM(size, "i"); | |
1029 | +MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240"); | |
1030 | +MODULE_PARM(brightness, "i"); | |
1031 | +MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108"); | |
1032 | +MODULE_PARM(contrast, "i"); | |
1033 | +MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108"); | |
1034 | +MODULE_PARM(saturation, "i"); | |
1035 | +MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108"); | |
1036 | +MODULE_PARM(sharpness, "i"); | |
1037 | +MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108"); | |
1038 | +MODULE_PARM(whitebal, "i"); | |
1039 | +MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363"); | |
1040 | +MODULE_PARM(debug, "i"); | |
1041 | +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); | |
1042 | +module_init(konicawc_init); | |
1043 | +module_exit(konicawc_cleanup); | |
1044 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/ultracam.c linux-2.4.19-pre8-konicawc/drivers/usb/ultracam.c | |
1045 | --- linux-2.4.19-pre8/drivers/usb/ultracam.c Wed Oct 17 22:34:06 2001 | |
1046 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/ultracam.c Sat May 11 01:34:30 2002 | |
1047 | @@ -659,6 +659,12 @@ | |
1048 | return uvd; | |
1049 | } | |
1050 | ||
1051 | + | |
1052 | +static struct usb_device_id id_table[] = { | |
1053 | + { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, | |
1054 | + { } /* Terminating entry */ | |
1055 | +}; | |
1056 | + | |
1057 | /* | |
1058 | * ultracam_init() | |
1059 | * | |
1060 | @@ -682,7 +688,8 @@ | |
1061 | sizeof(ultracam_t), | |
1062 | "ultracam", | |
1063 | &cbTbl, | |
1064 | - THIS_MODULE); | |
1065 | + THIS_MODULE, | |
1066 | + id_table); | |
1067 | } | |
1068 | ||
1069 | static void __exit ultracam_cleanup(void) | |
1070 | @@ -690,16 +697,7 @@ | |
1071 | usbvideo_Deregister(&cams); | |
1072 | } | |
1073 | ||
1074 | -#if defined(usb_device_id_ver) | |
1075 | - | |
1076 | -static __devinitdata struct usb_device_id id_table[] = { | |
1077 | - { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) }, | |
1078 | - { } /* Terminating entry */ | |
1079 | -}; | |
1080 | MODULE_DEVICE_TABLE(usb, id_table); | |
1081 | - | |
1082 | - | |
1083 | -#endif /* defined(usb_device_id_ver) */ | |
1084 | MODULE_LICENSE("GPL"); | |
1085 | ||
1086 | module_init(ultracam_init); | |
1087 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/usbvideo.c linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.c | |
1088 | --- linux-2.4.19-pre8/drivers/usb/usbvideo.c Thu Oct 11 07:42:46 2001 | |
1089 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.c Sat May 11 03:11:30 2002 | |
1090 | @@ -159,9 +159,21 @@ | |
1091 | ||
1092 | void RingQueue_Allocate(RingQueue_t *rq, int rqLen) | |
1093 | { | |
1094 | + /* Make sure the requested size is a power of 2 and | |
1095 | + round up if necessary. This allows index wrapping | |
1096 | + using masks rather than modulo */ | |
1097 | + | |
1098 | + int i = 1; | |
1099 | assert(rq != NULL); | |
1100 | assert(rqLen > 0); | |
1101 | + | |
1102 | + while(rqLen >> i) | |
1103 | + i++; | |
1104 | + if(rqLen != 1 << (i-1)) | |
1105 | + rqLen = 1 << i; | |
1106 | + | |
1107 | rq->length = rqLen; | |
1108 | + rq->ri = rq->wi = 0; | |
1109 | rq->queue = usbvideo_rvmalloc(rq->length); | |
1110 | assert(rq->queue != NULL); | |
1111 | } | |
1112 | @@ -185,12 +197,33 @@ | |
1113 | ||
1114 | int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len) | |
1115 | { | |
1116 | - int i; | |
1117 | + int rql, toread; | |
1118 | + | |
1119 | assert(rq != NULL); | |
1120 | assert(dst != NULL); | |
1121 | - for (i=0; i < len; i++) { | |
1122 | - dst[i] = rq->queue[rq->ri]; | |
1123 | - RING_QUEUE_DEQUEUE_BYTES(rq,1); | |
1124 | + | |
1125 | + | |
1126 | + rql = RingQueue_GetLength(rq); | |
1127 | + if(!rql) | |
1128 | + return 0; | |
1129 | + | |
1130 | + /* Clip requested length to available data */ | |
1131 | + if(len > rql) | |
1132 | + len = rql; | |
1133 | + | |
1134 | + toread = len; | |
1135 | + if(rq->ri > rq->wi) { | |
1136 | + /* Read data from tail */ | |
1137 | + int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri; | |
1138 | + memcpy(dst, rq->queue + rq->ri, read); | |
1139 | + toread -= read; | |
1140 | + dst += read; | |
1141 | + rq->ri = (rq->ri + read) & (rq->length-1); | |
1142 | + } | |
1143 | + if(toread) { | |
1144 | + /* Read data from head */ | |
1145 | + memcpy(dst, rq->queue + rq->ri, toread); | |
1146 | + rq->ri = (rq->ri + toread) & (rq->length-1); | |
1147 | } | |
1148 | return len; | |
1149 | } | |
1150 | @@ -216,7 +249,7 @@ | |
1151 | if (m > q_avail) | |
1152 | m = q_avail; | |
1153 | ||
1154 | - memmove(rq->queue + rq->wi, cdata, m); | |
1155 | + memcpy(rq->queue + rq->wi, cdata, m); | |
1156 | RING_QUEUE_ADVANCE_INDEX(rq, wi, m); | |
1157 | cdata += m; | |
1158 | enqueued += m; | |
1159 | @@ -225,22 +258,6 @@ | |
1160 | return enqueued; | |
1161 | } | |
1162 | ||
1163 | -int RingQueue_GetLength(const RingQueue_t *rq) | |
1164 | -{ | |
1165 | - int ri, wi; | |
1166 | - | |
1167 | - assert(rq != NULL); | |
1168 | - | |
1169 | - ri = rq->ri; | |
1170 | - wi = rq->wi; | |
1171 | - if (ri == wi) | |
1172 | - return 0; | |
1173 | - else if (ri < wi) | |
1174 | - return wi - ri; | |
1175 | - else | |
1176 | - return wi + (rq->length - ri); | |
1177 | -} | |
1178 | - | |
1179 | void RingQueue_InterruptibleSleepOn(RingQueue_t *rq) | |
1180 | { | |
1181 | assert(rq != NULL); | |
1182 | @@ -254,6 +271,14 @@ | |
1183 | wake_up_interruptible(&rq->wqh); | |
1184 | } | |
1185 | ||
1186 | +void RingQueue_Flush(RingQueue_t *rq) | |
1187 | +{ | |
1188 | + assert(rq != NULL); | |
1189 | + rq->ri = 0; | |
1190 | + rq->wi = 0; | |
1191 | +} | |
1192 | + | |
1193 | + | |
1194 | /* | |
1195 | * usbvideo_VideosizeToString() | |
1196 | * | |
1197 | @@ -390,7 +415,7 @@ | |
1198 | q_used = RingQueue_GetLength(&uvd->dp); | |
1199 | if ((uvd->dp.ri + q_used) >= uvd->dp.length) { | |
1200 | u_hi = uvd->dp.length; | |
1201 | - u_lo = (q_used + uvd->dp.ri) % uvd->dp.length; | |
1202 | + u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1); | |
1203 | } else { | |
1204 | u_hi = (q_used + uvd->dp.ri); | |
1205 | u_lo = -1; | |
1206 | @@ -757,7 +782,8 @@ | |
1207 | const int num_extra, | |
1208 | const char *driverName, | |
1209 | const usbvideo_cb_t *cbTbl, | |
1210 | - struct module *md ) | |
1211 | + struct module *md, | |
1212 | + const struct usb_device_id *id_table) | |
1213 | { | |
1214 | static const char proc[] = "usbvideo_register"; | |
1215 | usbvideo_t *cams; | |
1216 | @@ -791,6 +817,10 @@ | |
1217 | cams->cb.getFrame = usbvideo_GetFrame; | |
1218 | if (cams->cb.disconnect == NULL) | |
1219 | cams->cb.disconnect = usbvideo_Disconnect; | |
1220 | + if (cams->cb.startDataPump == NULL) | |
1221 | + cams->cb.startDataPump = usbvideo_StartDataPump; | |
1222 | + if (cams->cb.stopDataPump == NULL) | |
1223 | + cams->cb.stopDataPump = usbvideo_StopDataPump; | |
1224 | #if USES_PROC_FS | |
1225 | /* | |
1226 | * If both /proc fs callbacks are NULL then we assume that the driver | |
1227 | @@ -843,6 +873,7 @@ | |
1228 | cams->usbdrv.name = cams->drvName; | |
1229 | cams->usbdrv.probe = cams->cb.probe; | |
1230 | cams->usbdrv.disconnect = cams->cb.disconnect; | |
1231 | + cams->usbdrv.id_table = id_table; | |
1232 | ||
1233 | #if USES_PROC_FS | |
1234 | if (cams->uses_procfs) { | |
1235 | @@ -963,7 +994,7 @@ | |
1236 | uvd->remove_pending = 1; /* Now all ISO data will be ignored */ | |
1237 | ||
1238 | /* At this time we ask to cancel outstanding URBs */ | |
1239 | - usbvideo_StopDataPump(uvd); | |
1240 | + GET_CALLBACK(uvd, stopDataPump)(uvd); | |
1241 | ||
1242 | for (i=0; i < USBVIDEO_NUMSBUF; i++) | |
1243 | usb_free_urb(uvd->sbuf[i].urb); | |
1244 | @@ -1192,8 +1223,7 @@ | |
1245 | ||
1246 | if (!CAMERA_IS_OPERATIONAL(uvd)) | |
1247 | return -EFAULT; | |
1248 | - | |
1249 | - if (size > (((2 * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) | |
1250 | + if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) | |
1251 | return -EINVAL; | |
1252 | ||
1253 | pos = (unsigned long) uvd->fbuf; | |
1254 | @@ -1254,7 +1284,7 @@ | |
1255 | /* Allocate memory for the frame buffers */ | |
1256 | uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; | |
1257 | uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size); | |
1258 | - RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */ | |
1259 | + RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE); | |
1260 | if ((uvd->fbuf == NULL) || | |
1261 | (!RingQueue_IsAllocated(&uvd->dp))) { | |
1262 | err("%s: Failed to allocate fbuf or dp", proc); | |
1263 | @@ -1299,7 +1329,7 @@ | |
1264 | if (errCode == 0) { | |
1265 | /* Start data pump if we have valid endpoint */ | |
1266 | if (uvd->video_endp != 0) | |
1267 | - errCode = usbvideo_StartDataPump(uvd); | |
1268 | + errCode = GET_CALLBACK(uvd, startDataPump)(uvd); | |
1269 | if (errCode == 0) { | |
1270 | if (VALID_CALLBACK(uvd, setupOnOpen)) { | |
1271 | if (uvd->debug > 1) | |
1272 | @@ -1350,7 +1380,7 @@ | |
1273 | info("%s($%p)", proc, dev); | |
1274 | ||
1275 | down(&uvd->lock); | |
1276 | - usbvideo_StopDataPump(uvd); | |
1277 | + GET_CALLBACK(uvd, stopDataPump)(uvd); | |
1278 | usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size); | |
1279 | uvd->fbuf = NULL; | |
1280 | RingQueue_Free(&uvd->dp); | |
1281 | @@ -1458,8 +1488,8 @@ | |
1282 | ||
1283 | vw.x = 0; | |
1284 | vw.y = 0; | |
1285 | - vw.width = VIDEOSIZE_X(uvd->canvas); | |
1286 | - vw.height = VIDEOSIZE_Y(uvd->canvas); | |
1287 | + vw.width = VIDEOSIZE_X(uvd->videosize); | |
1288 | + vw.height = VIDEOSIZE_Y(uvd->videosize); | |
1289 | vw.chromakey = 0; | |
1290 | if (VALID_CALLBACK(uvd, getFPS)) | |
1291 | vw.flags = GET_CALLBACK(uvd, getFPS)(uvd); | |
1292 | @@ -1529,8 +1559,8 @@ | |
1293 | } | |
1294 | return -EINVAL; | |
1295 | } | |
1296 | - if ((vm.frame != 0) && (vm.frame != 1)) { | |
1297 | - err("VIDIOCMCAPTURE: vm.frame=%d. !E [0,1]", vm.frame); | |
1298 | + if ((vm.frame < 0) && (vm.frame >= USBVIDEO_NUMFRAMES)) { | |
1299 | + err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm.frame, USBVIDEO_NUMFRAMES-1); | |
1300 | return -EINVAL; | |
1301 | } | |
1302 | if (uvd->frame[vm.frame].frameState == FrameState_Grabbing) { | |
1303 | @@ -1629,7 +1659,7 @@ | |
1304 | { | |
1305 | static const char proc[] = "usbvideo_v4l_read"; | |
1306 | uvd_t *uvd = (uvd_t *) dev; | |
1307 | - int frmx = -1; | |
1308 | + int frmx = -1, i; | |
1309 | usbvideo_frame_t *frame; | |
1310 | ||
1311 | if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL)) | |
1312 | @@ -1641,14 +1671,13 @@ | |
1313 | down(&uvd->lock); | |
1314 | ||
1315 | /* See if a frame is completed, then use it. */ | |
1316 | - if ((uvd->frame[0].frameState == FrameState_Done) || | |
1317 | - (uvd->frame[0].frameState == FrameState_Done_Hold) || | |
1318 | - (uvd->frame[0].frameState == FrameState_Error)) { | |
1319 | - frmx = 0; | |
1320 | - } else if ((uvd->frame[1].frameState >= FrameState_Done) || | |
1321 | - (uvd->frame[1].frameState == FrameState_Done_Hold) || | |
1322 | - (uvd->frame[1].frameState >= FrameState_Done)) { | |
1323 | - frmx = 1; | |
1324 | + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { | |
1325 | + if ((uvd->frame[i].frameState == FrameState_Done) || | |
1326 | + (uvd->frame[i].frameState == FrameState_Done_Hold) || | |
1327 | + (uvd->frame[i].frameState == FrameState_Error)) { | |
1328 | + frmx = i; | |
1329 | + break; | |
1330 | + } | |
1331 | } | |
1332 | ||
1333 | /* FIXME: If we don't start a frame here then who ever does? */ | |
1334 | @@ -1663,10 +1692,12 @@ | |
1335 | * We will need to wait until it becomes cooked, of course. | |
1336 | */ | |
1337 | if (frmx == -1) { | |
1338 | - if (uvd->frame[0].frameState == FrameState_Grabbing) | |
1339 | - frmx = 0; | |
1340 | - else if (uvd->frame[1].frameState == FrameState_Grabbing) | |
1341 | - frmx = 1; | |
1342 | + for(i = 0; i < USBVIDEO_NUMFRAMES; i++) { | |
1343 | + if (uvd->frame[i].frameState == FrameState_Grabbing) { | |
1344 | + frmx = i; | |
1345 | + break; | |
1346 | + } | |
1347 | + } | |
1348 | } | |
1349 | ||
1350 | /* | |
1351 | @@ -1764,7 +1795,7 @@ | |
1352 | ||
1353 | /* Mark it as available to be used again. */ | |
1354 | uvd->frame[frmx].frameState = FrameState_Unused; | |
1355 | - if (usbvideo_NewFrame(uvd, frmx ? 0 : 1)) { | |
1356 | + if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) { | |
1357 | err("%s: usbvideo_NewFrame failed.", proc); | |
1358 | } | |
1359 | } | |
1360 | @@ -2001,7 +2032,7 @@ | |
1361 | uvd->settingsAdjusted = 1; | |
1362 | } | |
1363 | ||
1364 | - n = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; | |
1365 | + n = (framenum + 1) % USBVIDEO_NUMFRAMES; | |
1366 | if (uvd->frame[n].frameState == FrameState_Ready) | |
1367 | framenum = n; | |
1368 | ||
1369 | @@ -2033,7 +2064,8 @@ | |
1370 | */ | |
1371 | if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) { | |
1372 | /* This copies previous frame into this one to mask losses */ | |
1373 | - memmove(frame->data, uvd->frame[1-framenum].data, uvd->max_frame_size); | |
1374 | + int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES; | |
1375 | + memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size); | |
1376 | } else { | |
1377 | if (uvd->flags & FLAGS_CLEAN_FRAMES) { | |
1378 | /* This provides a "clean" frame but slows things down */ | |
1379 | diff -urN -X /home/spse/dontdiff linux-2.4.19-pre8/drivers/usb/usbvideo.h linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.h | |
1380 | --- linux-2.4.19-pre8/drivers/usb/usbvideo.h Thu Oct 11 07:42:46 2001 | |
1381 | +++ linux-2.4.19-pre8-konicawc/drivers/usb/usbvideo.h Sat May 11 01:58:58 2002 | |
1382 | @@ -113,9 +113,10 @@ | |
1383 | mr = LIMIT_RGB(mm_r); \ | |
1384 | } | |
1385 | ||
1386 | -#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length | |
1387 | +#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */ | |
1388 | +#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1) | |
1389 | #define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n) | |
1390 | -#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length]) | |
1391 | +#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)]) | |
1392 | ||
1393 | typedef struct { | |
1394 | unsigned char *queue; /* Data from the Isoc data pump */ | |
1395 | @@ -269,6 +270,9 @@ | |
1396 | int (*getFrame)(uvd_t *, int); | |
1397 | int (*procfs_read)(char *page,char **start,off_t off,int count,int *eof,void *data); | |
1398 | int (*procfs_write)(struct file *file,const char *buffer,unsigned long count,void *data); | |
1399 | + int (*startDataPump)(uvd_t *uvd); | |
1400 | + void (*stopDataPump)(uvd_t *uvd); | |
1401 | + int (*setVideoMode)(uvd_t *, int, int, int); | |
1402 | } usbvideo_cb_t; | |
1403 | ||
1404 | struct s_usbvideo_t { | |
1405 | @@ -302,15 +306,20 @@ | |
1406 | #define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \ | |
1407 | ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL) | |
1408 | ||
1409 | -void RingQueue_Initialize(RingQueue_t *rq); | |
1410 | -void RingQueue_Allocate(RingQueue_t *rq, int rqLen); | |
1411 | -int RingQueue_IsAllocated(const RingQueue_t *rq); | |
1412 | -void RingQueue_Free(RingQueue_t *rq); | |
1413 | int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len); | |
1414 | int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n); | |
1415 | -int RingQueue_GetLength(const RingQueue_t *rq); | |
1416 | -void RingQueue_InterruptibleSleepOn(RingQueue_t *rq); | |
1417 | void RingQueue_WakeUpInterruptible(RingQueue_t *rq); | |
1418 | +void RingQueue_Flush(RingQueue_t *rq); | |
1419 | + | |
1420 | +static inline int RingQueue_GetLength(const RingQueue_t *rq) | |
1421 | +{ | |
1422 | + return (rq->wi - rq->ri + rq->length) & (rq->length-1); | |
1423 | +} | |
1424 | + | |
1425 | +static inline int RingQueue_GetFreeSpace(const RingQueue_t *rq) | |
1426 | +{ | |
1427 | + return rq->length - RingQueue_GetLength(rq); | |
1428 | +} | |
1429 | ||
1430 | void usbvideo_CollectRawData(uvd_t *uvd, usbvideo_frame_t *frame); | |
1431 | void usbvideo_DrawLine( | |
1432 | @@ -339,7 +348,8 @@ | |
1433 | const int num_extra, | |
1434 | const char *driverName, | |
1435 | const usbvideo_cb_t *cbTable, | |
1436 | - struct module *md); | |
1437 | + struct module *md, | |
1438 | + const struct usb_device_id *id_table); | |
1439 | uvd_t *usbvideo_AllocateDevice(usbvideo_t *cams); | |
1440 | int usbvideo_RegisterVideoDevice(uvd_t *uvd); | |
1441 | void usbvideo_Deregister(usbvideo_t **uvt); |