aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/usbvideo
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2006-03-25 07:05:39 -0500
committerMauro Carvalho Chehab <mchehab@infradead.org>2006-03-25 07:29:04 -0500
commit9f6933be665ce3b049c274c99810ac754edabf19 (patch)
tree70a670d030c5d5a4175076724e4720a5b967e2bc /drivers/media/video/usbvideo
parent7fa033b103bc3f5c37f934695473f63adf140dba (diff)
V4L/DVB (3599a): Move drivers/usb/media to drivers/media/video
Because of historic reasons, there are two separate directories with V4L stuff. Most drivers are located at driver/media/video. However, some code for USB Webcams were inserted under drivers/usb/media. This makes difficult for module authors to know were things should be. Also, makes Kconfig menu confusing for normal users. This patch moves all V4L content under drivers/usb/media to drivers/media/video, and fixes Kconfig/Makefile entries. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/usbvideo')
-rw-r--r--drivers/media/video/usbvideo/Makefile4
-rw-r--r--drivers/media/video/usbvideo/ibmcam.c3932
-rw-r--r--drivers/media/video/usbvideo/konicawc.c978
-rw-r--r--drivers/media/video/usbvideo/ultracam.c679
-rw-r--r--drivers/media/video/usbvideo/usbvideo.c2190
-rw-r--r--drivers/media/video/usbvideo/usbvideo.h394
-rw-r--r--drivers/media/video/usbvideo/vicam.c1411
7 files changed, 9588 insertions, 0 deletions
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
new file mode 100644
index 000000000000..ed410a5ee8c9
--- /dev/null
+++ b/drivers/media/video/usbvideo/Makefile
@@ -0,0 +1,4 @@
1obj-$(CONFIG_USB_IBMCAM) += ibmcam.o usbvideo.o ultracam.o
2obj-$(CONFIG_USB_KONICAWC) += konicawc.o usbvideo.o
3obj-$(CONFIG_USB_VICAM) += vicam.o usbvideo.o
4
diff --git a/drivers/media/video/usbvideo/ibmcam.c b/drivers/media/video/usbvideo/ibmcam.c
new file mode 100644
index 000000000000..a42c22294124
--- /dev/null
+++ b/drivers/media/video/usbvideo/ibmcam.c
@@ -0,0 +1,3932 @@
1/*
2 * USB IBM C-It Video Camera driver
3 *
4 * Supports Xirlink C-It Video Camera, IBM PC Camera,
5 * IBM NetCamera and Veo Stingray.
6 *
7 * This driver is based on earlier work of:
8 *
9 * (C) Copyright 1999 Johannes Erdfelt
10 * (C) Copyright 1999 Randy Dunlap
11 *
12 * 5/24/00 Removed optional (and unnecessary) locking of the driver while
13 * the device remains plugged in. Corrected race conditions in ibmcam_open
14 * and ibmcam_probe() routines using this as a guideline:
15 */
16
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/module.h>
20#include <linux/init.h>
21
22#include "usbvideo.h"
23
24#define IBMCAM_VENDOR_ID 0x0545
25#define IBMCAM_PRODUCT_ID 0x8080
26#define NETCAM_PRODUCT_ID 0x8002 /* IBM NetCamera, close to model 2 */
27#define VEO_800C_PRODUCT_ID 0x800C /* Veo Stingray, repackaged Model 2 */
28#define VEO_800D_PRODUCT_ID 0x800D /* Veo Stingray, repackaged Model 4 */
29
30#define MAX_IBMCAM 4 /* How many devices we allow to connect */
31#define USES_IBMCAM_PUTPIXEL 0 /* 0=Fast/oops 1=Slow/secure */
32
33/* Header signatures */
34
35/* Model 1 header: 00 FF 00 xx */
36#define HDRSIG_MODEL1_128x96 0x06 /* U Y V Y ... */
37#define HDRSIG_MODEL1_176x144 0x0e /* U Y V Y ... */
38#define HDRSIG_MODEL1_352x288 0x00 /* V Y U Y ... */
39
40#define IBMCAM_MODEL_1 1 /* XVP-501, 3 interfaces, rev. 0.02 */
41#define IBMCAM_MODEL_2 2 /* KSX-X9903, 2 interfaces, rev. 3.0a */
42#define IBMCAM_MODEL_3 3 /* KSX-X9902, 2 interfaces, rev. 3.01 */
43#define IBMCAM_MODEL_4 4 /* IBM NetCamera, 0545/8002/3.0a */
44
45/* Video sizes supported */
46#define VIDEOSIZE_128x96 VIDEOSIZE(128, 96)
47#define VIDEOSIZE_176x144 VIDEOSIZE(176,144)
48#define VIDEOSIZE_352x288 VIDEOSIZE(352,288)
49#define VIDEOSIZE_320x240 VIDEOSIZE(320,240)
50#define VIDEOSIZE_352x240 VIDEOSIZE(352,240)
51#define VIDEOSIZE_640x480 VIDEOSIZE(640,480)
52#define VIDEOSIZE_160x120 VIDEOSIZE(160,120)
53
54/* Video sizes supported */
55enum {
56 SIZE_128x96 = 0,
57 SIZE_160x120,
58 SIZE_176x144,
59 SIZE_320x240,
60 SIZE_352x240,
61 SIZE_352x288,
62 SIZE_640x480,
63 /* Add/remove/rearrange items before this line */
64 SIZE_LastItem
65};
66
67/*
68 * This structure lives in uvd->user field.
69 */
70typedef struct {
71 int initialized; /* Had we already sent init sequence? */
72 int camera_model; /* What type of IBM camera we got? */
73 int has_hdr;
74} ibmcam_t;
75#define IBMCAM_T(uvd) ((ibmcam_t *)((uvd)->user_data))
76
77static struct usbvideo *cams;
78
79static int debug;
80
81static int flags; /* = FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
82
83static const int min_canvasWidth = 8;
84static const int min_canvasHeight = 4;
85
86static int lighting = 1; /* Medium */
87
88#define SHARPNESS_MIN 0
89#define SHARPNESS_MAX 6
90static int sharpness = 4; /* Low noise, good details */
91
92#define FRAMERATE_MIN 0
93#define FRAMERATE_MAX 6
94static int framerate = -1;
95
96static int size = SIZE_352x288;
97
98/*
99 * Here we define several initialization variables. They may
100 * be used to automatically set color, hue, brightness and
101 * contrast to desired values. This is particularly useful in
102 * case of webcams (which have no controls and no on-screen
103 * output) and also when a client V4L software is used that
104 * does not have some of those controls. In any case it's
105 * good to have startup values as options.
106 *
107 * These values are all in [0..255] range. This simplifies
108 * operation. Note that actual values of V4L variables may
109 * be scaled up (as much as << 8). User can see that only
110 * on overlay output, however, or through a V4L client.
111 */
112static int init_brightness = 128;
113static int init_contrast = 192;
114static int init_color = 128;
115static int init_hue = 128;
116static int hue_correction = 128;
117
118/* Settings for camera model 2 */
119static int init_model2_rg2 = -1;
120static int init_model2_sat = -1;
121static int init_model2_yb = -1;
122
123/* 01.01.08 - Added for RCA video in support -LO */
124/* Settings for camera model 3 */
125static int init_model3_input = 0;
126
127module_param(debug, int, 0);
128MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
129module_param(flags, int, 0);
130MODULE_PARM_DESC(flags, "Bitfield: 0=VIDIOCSYNC, 1=B/W, 2=show hints, 3=show stats, 4=test pattern, 5=separate frames, 6=clean frames");
131module_param(framerate, int, 0);
132MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
133module_param(lighting, int, 0);
134MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
135module_param(sharpness, int, 0);
136MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
137module_param(size, int, 0);
138MODULE_PARM_DESC(size, "Image size: 0=128x96 1=160x120 2=176x144 3=320x240 4=352x240 5=352x288 6=640x480 (default=5)");
139module_param(init_brightness, int, 0);
140MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
141module_param(init_contrast, int, 0);
142MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
143module_param(init_color, int, 0);
144MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
145module_param(init_hue, int, 0);
146MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
147module_param(hue_correction, int, 0);
148MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
149
150module_param(init_model2_rg2, int, 0);
151MODULE_PARM_DESC(init_model2_rg2, "Model2 preconfiguration: 0-255 (default=47)");
152module_param(init_model2_sat, int, 0);
153MODULE_PARM_DESC(init_model2_sat, "Model2 preconfiguration: 0-255 (default=52)");
154module_param(init_model2_yb, int, 0);
155MODULE_PARM_DESC(init_model2_yb, "Model2 preconfiguration: 0-255 (default=160)");
156
157/* 01.01.08 - Added for RCA video in support -LO */
158module_param(init_model3_input, int, 0);
159MODULE_PARM_DESC(init_model3_input, "Model3 input: 0=CCD 1=RCA");
160
161MODULE_AUTHOR ("Dmitri");
162MODULE_DESCRIPTION ("IBM/Xirlink C-it USB Camera Driver for Linux (c) 2000");
163MODULE_LICENSE("GPL");
164
165/* Still mysterious i2c commands */
166static const unsigned short unknown_88 = 0x0088;
167static const unsigned short unknown_89 = 0x0089;
168static const unsigned short bright_3x[3] = { 0x0031, 0x0032, 0x0033 };
169static const unsigned short contrast_14 = 0x0014;
170static const unsigned short light_27 = 0x0027;
171static const unsigned short sharp_13 = 0x0013;
172
173/* i2c commands for Model 2 cameras */
174static const unsigned short mod2_brightness = 0x001a; /* $5b .. $ee; default=$5a */
175static const unsigned short mod2_set_framerate = 0x001c; /* 0 (fast).. $1F (slow) */
176static const unsigned short mod2_color_balance_rg2 = 0x001e; /* 0 (red) .. $7F (green) */
177static const unsigned short mod2_saturation = 0x0020; /* 0 (b/w) - $7F (full color) */
178static const unsigned short mod2_color_balance_yb = 0x0022; /* 0..$7F, $50 is about right */
179static const unsigned short mod2_hue = 0x0024; /* 0..$7F, $70 is about right */
180static const unsigned short mod2_sensitivity = 0x0028; /* 0 (min) .. $1F (max) */
181
182struct struct_initData {
183 unsigned char req;
184 unsigned short value;
185 unsigned short index;
186};
187
188/*
189 * ibmcam_size_to_videosize()
190 *
191 * This procedure converts module option 'size' into the actual
192 * videosize_t that defines the image size in pixels. We need
193 * simplified 'size' because user wants a simple enumerated list
194 * of choices, not an infinite set of possibilities.
195 */
196static videosize_t ibmcam_size_to_videosize(int size)
197{
198 videosize_t vs = VIDEOSIZE_352x288;
199 RESTRICT_TO_RANGE(size, 0, (SIZE_LastItem-1));
200 switch (size) {
201 case SIZE_128x96:
202 vs = VIDEOSIZE_128x96;
203 break;
204 case SIZE_160x120:
205 vs = VIDEOSIZE_160x120;
206 break;
207 case SIZE_176x144:
208 vs = VIDEOSIZE_176x144;
209 break;
210 case SIZE_320x240:
211 vs = VIDEOSIZE_320x240;
212 break;
213 case SIZE_352x240:
214 vs = VIDEOSIZE_352x240;
215 break;
216 case SIZE_352x288:
217 vs = VIDEOSIZE_352x288;
218 break;
219 case SIZE_640x480:
220 vs = VIDEOSIZE_640x480;
221 break;
222 default:
223 err("size=%d. is not valid", size);
224 break;
225 }
226 return vs;
227}
228
229/*
230 * ibmcam_find_header()
231 *
232 * Locate one of supported header markers in the queue.
233 * Once found, remove all preceding bytes AND the marker (4 bytes)
234 * from the data pump queue. Whatever follows must be video lines.
235 *
236 * History:
237 * 1/21/00 Created.
238 */
239static enum ParseState ibmcam_find_header(struct uvd *uvd) /* FIXME: Add frame here */
240{
241 struct usbvideo_frame *frame;
242 ibmcam_t *icam;
243
244 if ((uvd->curframe) < 0 || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
245 err("ibmcam_find_header: Illegal frame %d.", uvd->curframe);
246 return scan_EndParse;
247 }
248 icam = IBMCAM_T(uvd);
249 assert(icam != NULL);
250 frame = &uvd->frame[uvd->curframe];
251 icam->has_hdr = 0;
252 switch (icam->camera_model) {
253 case IBMCAM_MODEL_1:
254 {
255 const int marker_len = 4;
256 while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
257 if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
258 (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
259 (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00))
260 {
261#if 0 /* This code helps to detect new frame markers */
262 info("Header sig: 00 FF 00 %02X", RING_QUEUE_PEEK(&uvd->dp, 3));
263#endif
264 frame->header = RING_QUEUE_PEEK(&uvd->dp, 3);
265 if ((frame->header == HDRSIG_MODEL1_128x96) ||
266 (frame->header == HDRSIG_MODEL1_176x144) ||
267 (frame->header == HDRSIG_MODEL1_352x288))
268 {
269#if 0
270 info("Header found.");
271#endif
272 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
273 icam->has_hdr = 1;
274 break;
275 }
276 }
277 /* If we are still here then this doesn't look like a header */
278 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
279 }
280 break;
281 }
282 case IBMCAM_MODEL_2:
283case IBMCAM_MODEL_4:
284 {
285 int marker_len = 0;
286 switch (uvd->videosize) {
287 case VIDEOSIZE_176x144:
288 marker_len = 10;
289 break;
290 default:
291 marker_len = 2;
292 break;
293 }
294 while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
295 if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
296 (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF))
297 {
298#if 0
299 info("Header found.");
300#endif
301 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
302 icam->has_hdr = 1;
303 frame->header = HDRSIG_MODEL1_176x144;
304 break;
305 }
306 /* If we are still here then this doesn't look like a header */
307 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
308 }
309 break;
310 }
311 case IBMCAM_MODEL_3:
312 { /*
313 * Headers: (one precedes every frame). nc=no compression,
314 * bq=best quality bf=best frame rate.
315 *
316 * 176x144: 00 FF 02 { 0A=nc CA=bq EA=bf }
317 * 320x240: 00 FF 02 { 08=nc 28=bq 68=bf }
318 * 640x480: 00 FF 03 { 08=nc 28=bq 68=bf }
319 *
320 * Bytes '00 FF' seem to indicate header. Other two bytes
321 * encode the frame type. This is a set of bit fields that
322 * encode image size, compression type etc. These fields
323 * do NOT contain frame number because all frames carry
324 * the same header.
325 */
326 const int marker_len = 4;
327 while (RingQueue_GetLength(&uvd->dp) >= marker_len) {
328 if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
329 (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xFF) &&
330 (RING_QUEUE_PEEK(&uvd->dp, 2) != 0xFF))
331 {
332 /*
333 * Combine 2 bytes of frame type into one
334 * easy to use value
335 */
336 unsigned long byte3, byte4;
337
338 byte3 = RING_QUEUE_PEEK(&uvd->dp, 2);
339 byte4 = RING_QUEUE_PEEK(&uvd->dp, 3);
340 frame->header = (byte3 << 8) | byte4;
341#if 0
342 info("Header found.");
343#endif
344 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, marker_len);
345 icam->has_hdr = 1;
346 break;
347 }
348 /* If we are still here then this doesn't look like a header */
349 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
350 }
351 break;
352 }
353 default:
354 break;
355 }
356 if (!icam->has_hdr) {
357 if (uvd->debug > 2)
358 info("Skipping frame, no header");
359 return scan_EndParse;
360 }
361
362 /* Header found */
363 icam->has_hdr = 1;
364 uvd->stats.header_count++;
365 frame->scanstate = ScanState_Lines;
366 frame->curline = 0;
367
368 if (flags & FLAGS_FORCE_TESTPATTERN) {
369 usbvideo_TestPattern(uvd, 1, 1);
370 return scan_NextFrame;
371 }
372 return scan_Continue;
373}
374
375/*
376 * ibmcam_parse_lines()
377 *
378 * Parse one line (interlaced) from the buffer, put
379 * decoded RGB value into the current frame buffer
380 * and add the written number of bytes (RGB) to
381 * the *pcopylen.
382 *
383 * History:
384 * 21-Jan-2000 Created.
385 * 12-Oct-2000 Reworked to reflect interlaced nature of the data.
386 */
387static enum ParseState ibmcam_parse_lines(
388 struct uvd *uvd,
389 struct usbvideo_frame *frame,
390 long *pcopylen)
391{
392 unsigned char *f;
393 ibmcam_t *icam;
394 unsigned int len, scanLength, scanHeight, order_uv, order_yc;
395 int v4l_linesize; /* V4L line offset */
396 const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */
397 const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */
398 const int ccm = 128; /* Color correction median - see below */
399 int y, u, v, i, frame_done=0, color_corr;
400 static unsigned char lineBuffer[640*3];
401 unsigned const char *chromaLine, *lumaLine;
402
403 assert(uvd != NULL);
404 assert(frame != NULL);
405 icam = IBMCAM_T(uvd);
406 assert(icam != NULL);
407 color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
408 RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
409
410 v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
411
412 if (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_4) {
413 /* Model 4 frame markers do not carry image size identification */
414 switch (uvd->videosize) {
415 case VIDEOSIZE_128x96:
416 case VIDEOSIZE_160x120:
417 case VIDEOSIZE_176x144:
418 scanLength = VIDEOSIZE_X(uvd->videosize);
419 scanHeight = VIDEOSIZE_Y(uvd->videosize);
420 break;
421 default:
422 err("ibmcam_parse_lines: Wrong mode.");
423 return scan_Out;
424 }
425 order_yc = 1; /* order_yc: true=Yc false=cY ('c'=either U or V) */
426 order_uv = 1; /* Always true in this algorithm */
427 } else {
428 switch (frame->header) {
429 case HDRSIG_MODEL1_128x96:
430 scanLength = 128;
431 scanHeight = 96;
432 order_uv = 1; /* U Y V Y ... */
433 break;
434 case HDRSIG_MODEL1_176x144:
435 scanLength = 176;
436 scanHeight = 144;
437 order_uv = 1; /* U Y V Y ... */
438 break;
439 case HDRSIG_MODEL1_352x288:
440 scanLength = 352;
441 scanHeight = 288;
442 order_uv = 0; /* Y V Y V ... */
443 break;
444 default:
445 err("Unknown header signature 00 FF 00 %02lX", frame->header);
446 return scan_NextFrame;
447 }
448 /* order_yc: true=Yc false=cY ('c'=either U or V) */
449 order_yc = (IBMCAM_T(uvd)->camera_model == IBMCAM_MODEL_2);
450 }
451
452 len = scanLength * 3;
453 assert(len <= sizeof(lineBuffer));
454
455 /*
456 * Lines are organized this way:
457 *
458 * I420:
459 * ~~~~
460 * <scanLength->
461 * ___________________________________
462 * |-----Y-----|---UVUVUV...UVUV-----| \
463 * |-----------+---------------------| \
464 * |<-- 176 -->|<------ 176*2 ------>| Total 72. lines (interlaced)
465 * |... ... | ... | /
466 * |<-- 352 -->|<------ 352*2 ------>| Total 144. lines (interlaced)
467 * |___________|_____________________| /
468 * \ \
469 * lumaLine chromaLine
470 */
471
472 /* Make sure there's enough data for the entire line */
473 if (RingQueue_GetLength(&uvd->dp) < len)
474 return scan_Out;
475
476 /* Suck one line out of the ring queue */
477 RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
478
479 /*
480 * Make sure that our writing into output buffer
481 * will not exceed the buffer. Mind that we may write
482 * not into current output scanline but in several after
483 * it as well (if we enlarge image vertically.)
484 */
485 if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
486 return scan_NextFrame;
487
488 /*
489 * Now we are sure that entire line (representing all 'scanLength'
490 * pixels from the camera) is available in the buffer. We
491 * start copying the line left-aligned to the V4L buffer.
492 * If the camera line is shorter then we should pad the V4L
493 * buffer with something (black) to complete the line.
494 */
495 assert(frame->data != NULL);
496 f = frame->data + (v4l_linesize * frame->curline);
497
498 /*
499 * To obtain chrominance data from the 'chromaLine' use this:
500 * v = chromaLine[0]; // 0-1:[0], 2-3:[4], 4-5:[8]...
501 * u = chromaLine[2]; // 0-1:[2], 2-3:[6], 4-5:[10]...
502 *
503 * Indices must be calculated this way:
504 * v_index = (i >> 1) << 2;
505 * u_index = (i >> 1) << 2 + 2;
506 *
507 * where 'i' is the column number [0..VIDEOSIZE_X(frame->request)-1]
508 */
509 lumaLine = lineBuffer;
510 chromaLine = lineBuffer + scanLength;
511 for (i = 0; i < VIDEOSIZE_X(frame->request); i++)
512 {
513 unsigned char rv, gv, bv; /* RGB components */
514
515 /* Check for various visual debugging hints (colorized pixels) */
516 if ((flags & FLAGS_DISPLAY_HINTS) && (icam->has_hdr)) {
517 /*
518 * This is bad and should not happen. This means that
519 * we somehow overshoot the line and encountered new
520 * frame! Obviously our camera/V4L frame size is out
521 * of whack. This cyan dot will help you to figure
522 * out where exactly the new frame arrived.
523 */
524 if (icam->has_hdr == 1) {
525 bv = 0; /* Yellow marker */
526 gv = 0xFF;
527 rv = 0xFF;
528 } else {
529 bv = 0xFF; /* Cyan marker */
530 gv = 0xFF;
531 rv = 0;
532 }
533 icam->has_hdr = 0;
534 goto make_pixel;
535 }
536
537 /*
538 * Check if we are still in range. We may be out of range if our
539 * V4L canvas is wider or taller than the camera "native" image.
540 * Then we quickly fill the remainder of the line with zeros to
541 * make black color and quit the horizontal scanning loop.
542 */
543 if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
544 const int j = i * V4L_BYTES_PER_PIXEL;
545#if USES_IBMCAM_PUTPIXEL
546 /* Refresh 'f' because we don't use it much with PUTPIXEL */
547 f = frame->data + (v4l_linesize * frame->curline) + j;
548#endif
549 memset(f, 0, v4l_linesize - j);
550 break;
551 }
552
553 y = lumaLine[i];
554 if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
555 rv = gv = bv = y;
556 else {
557 int off_0, off_2;
558
559 off_0 = (i >> 1) << 2;
560 off_2 = off_0 + 2;
561
562 if (order_yc) {
563 off_0++;
564 off_2++;
565 }
566 if (!order_uv) {
567 off_0 += 2;
568 off_2 -= 2;
569 }
570 u = chromaLine[off_0] + hue_corr;
571 v = chromaLine[off_2] + hue2_corr;
572
573 /* Apply color correction */
574 if (color_corr != 0) {
575 /* Magnify up to 2 times, reduce down to zero saturation */
576 u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
577 v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
578 }
579 YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
580 }
581
582 make_pixel:
583 /*
584 * The purpose of creating the pixel here, in one,
585 * dedicated place is that we may need to make the
586 * pixel wider and taller than it actually is. This
587 * may be used if camera generates small frames for
588 * sake of frame rate (or any other reason.)
589 *
590 * The output data consists of B, G, R bytes
591 * (in this order).
592 */
593#if USES_IBMCAM_PUTPIXEL
594 RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
595#else
596 *f++ = bv;
597 *f++ = gv;
598 *f++ = rv;
599#endif
600 /*
601 * Typically we do not decide within a legitimate frame
602 * that we want to end the frame. However debugging code
603 * may detect marker of new frame within the data. Then
604 * this condition activates. The 'data' pointer is already
605 * pointing at the new marker, so we'd better leave it as is.
606 */
607 if (frame_done)
608 break; /* End scanning of lines */
609 }
610 /*
611 * Account for number of bytes that we wrote into output V4L frame.
612 * We do it here, after we are done with the scanline, because we
613 * may fill more than one output scanline if we do vertical
614 * enlargement.
615 */
616 frame->curline += 2;
617 if (pcopylen != NULL)
618 *pcopylen += 2 * v4l_linesize;
619 frame->deinterlace = Deinterlace_FillOddLines;
620
621 if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
622 return scan_NextFrame;
623 else
624 return scan_Continue;
625}
626
627/*
628 * ibmcam_model2_320x240_parse_lines()
629 *
630 * This procedure deals with a weird RGB format that is produced by IBM
631 * camera model 2 in modes 320x240 and above; 'x' below is 159 or 175,
632 * depending on horizontal size of the picture:
633 *
634 * <--- 160 or 176 pairs of RA,RB bytes ----->
635 * *-----------------------------------------* \
636 * | RA0 | RB0 | RA1 | RB1 | ... | RAx | RBx | \ This is pair of horizontal lines,
637 * |-----+-----+-----+-----+ ... +-----+-----| *- or one interlaced line, total
638 * | B0 | G0 | B1 | G1 | ... | Bx | Gx | / 120 or 144 such pairs which yield
639 * |=====+=====+=====+=====+ ... +=====+=====| / 240 or 288 lines after deinterlacing.
640 *
641 * Each group of FOUR bytes (RAi, RBi, Bi, Gi) where i=0..frame_width/2-1
642 * defines ONE pixel. Therefore this format yields 176x144 "decoded"
643 * resolution at best. I do not know why camera sends such format - the
644 * previous model (1) just used interlaced I420 and everyone was happy.
645 *
646 * I do not know what is the difference between RAi and RBi bytes. Both
647 * seemingly represent R component, but slightly vary in value (so that
648 * the picture looks a bit colored if one or another is used). I use
649 * them both as R component in attempt to at least partially recover the
650 * lost resolution.
651 */
652static enum ParseState ibmcam_model2_320x240_parse_lines(
653 struct uvd *uvd,
654 struct usbvideo_frame *frame,
655 long *pcopylen)
656{
657 unsigned char *f, *la, *lb;
658 unsigned int len;
659 int v4l_linesize; /* V4L line offset */
660 int i, j, frame_done=0, color_corr;
661 int scanLength, scanHeight;
662 static unsigned char lineBuffer[352*2];
663
664 switch (uvd->videosize) {
665 case VIDEOSIZE_320x240:
666 case VIDEOSIZE_352x240:
667 case VIDEOSIZE_352x288:
668 scanLength = VIDEOSIZE_X(uvd->videosize);
669 scanHeight = VIDEOSIZE_Y(uvd->videosize);
670 break;
671 default:
672 err("ibmcam_model2_320x240_parse_lines: Wrong mode.");
673 return scan_Out;
674 }
675
676 color_corr = (uvd->vpic.colour) >> 8; /* 0..+255 */
677 v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
678
679 len = scanLength * 2; /* See explanation above */
680 assert(len <= sizeof(lineBuffer));
681
682 /* Make sure there's enough data for the entire line */
683 if (RingQueue_GetLength(&uvd->dp) < len)
684 return scan_Out;
685
686 /* Suck one line out of the ring queue */
687 RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
688
689 /*
690 * Make sure that our writing into output buffer
691 * will not exceed the buffer. Mind that we may write
692 * not into current output scanline but in several after
693 * it as well (if we enlarge image vertically.)
694 */
695 if ((frame->curline + 2) >= VIDEOSIZE_Y(frame->request))
696 return scan_NextFrame;
697
698 la = lineBuffer;
699 lb = lineBuffer + scanLength;
700
701 /*
702 * Now we are sure that entire line (representing all
703 * VIDEOSIZE_X(frame->request)
704 * pixels from the camera) is available in the scratch buffer. We
705 * start copying the line left-aligned to the V4L buffer (which
706 * might be larger - not smaller, hopefully). If the camera
707 * line is shorter then we should pad the V4L buffer with something
708 * (black in this case) to complete the line.
709 */
710 f = frame->data + (v4l_linesize * frame->curline);
711
712 /* Fill the 2-line strip */
713 for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
714 int y, rv, gv, bv; /* RGB components */
715
716 j = i & (~1);
717
718 /* Check for various visual debugging hints (colorized pixels) */
719 if ((flags & FLAGS_DISPLAY_HINTS) && (IBMCAM_T(uvd)->has_hdr)) {
720 if (IBMCAM_T(uvd)->has_hdr == 1) {
721 bv = 0; /* Yellow marker */
722 gv = 0xFF;
723 rv = 0xFF;
724 } else {
725 bv = 0xFF; /* Cyan marker */
726 gv = 0xFF;
727 rv = 0;
728 }
729 IBMCAM_T(uvd)->has_hdr = 0;
730 goto make_pixel;
731 }
732
733 /*
734 * Check if we are still in range. We may be out of range if our
735 * V4L canvas is wider or taller than the camera "native" image.
736 * Then we quickly fill the remainder of the line with zeros to
737 * make black color and quit the horizontal scanning loop.
738 */
739 if (((frame->curline + 2) >= scanHeight) || (i >= scanLength)) {
740 const int j = i * V4L_BYTES_PER_PIXEL;
741#if USES_IBMCAM_PUTPIXEL
742 /* Refresh 'f' because we don't use it much with PUTPIXEL */
743 f = frame->data + (v4l_linesize * frame->curline) + j;
744#endif
745 memset(f, 0, v4l_linesize - j);
746 break;
747 }
748
749 /*
750 * Here I use RA and RB components, one per physical pixel.
751 * This causes fine vertical grid on the picture but may improve
752 * horizontal resolution. If you prefer replicating, use this:
753 * rv = la[j + 0]; ... or ... rv = la[j + 1];
754 * then the pixel will be replicated.
755 */
756 rv = la[i];
757 gv = lb[j + 1];
758 bv = lb[j + 0];
759
760 y = (rv + gv + bv) / 3; /* Brightness (badly calculated) */
761
762 if (flags & FLAGS_MONOCHROME) /* Use monochrome for debugging */
763 rv = gv = bv = y;
764 else if (color_corr != 128) {
765
766 /* Calculate difference between color and brightness */
767 rv -= y;
768 gv -= y;
769 bv -= y;
770
771 /* Scale differences */
772 rv = (rv * color_corr) / 128;
773 gv = (gv * color_corr) / 128;
774 bv = (bv * color_corr) / 128;
775
776 /* Reapply brightness */
777 rv += y;
778 gv += y;
779 bv += y;
780
781 /* Watch for overflows */
782 RESTRICT_TO_RANGE(rv, 0, 255);
783 RESTRICT_TO_RANGE(gv, 0, 255);
784 RESTRICT_TO_RANGE(bv, 0, 255);
785 }
786
787 make_pixel:
788 RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
789 }
790 /*
791 * Account for number of bytes that we wrote into output V4L frame.
792 * We do it here, after we are done with the scanline, because we
793 * may fill more than one output scanline if we do vertical
794 * enlargement.
795 */
796 frame->curline += 2;
797 *pcopylen += v4l_linesize * 2;
798 frame->deinterlace = Deinterlace_FillOddLines;
799
800 if (frame_done || (frame->curline >= VIDEOSIZE_Y(frame->request)))
801 return scan_NextFrame;
802 else
803 return scan_Continue;
804}
805
806static enum ParseState ibmcam_model3_parse_lines(
807 struct uvd *uvd,
808 struct usbvideo_frame *frame,
809 long *pcopylen)
810{
811 unsigned char *data;
812 const unsigned char *color;
813 unsigned int len;
814 int v4l_linesize; /* V4L line offset */
815 const int hue_corr = (uvd->vpic.hue - 0x8000) >> 10; /* -32..+31 */
816 const int hue2_corr = (hue_correction - 128) / 4; /* -32..+31 */
817 const int ccm = 128; /* Color correction median - see below */
818 int i, u, v, rw, data_w=0, data_h=0, color_corr;
819 static unsigned char lineBuffer[640*3];
820
821 color_corr = (uvd->vpic.colour - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
822 RESTRICT_TO_RANGE(color_corr, -ccm, ccm+1);
823
824 v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
825
826 /* The header tells us what sort of data is in this frame */
827 switch (frame->header) {
828 /*
829 * Uncompressed modes (that are easy to decode).
830 */
831 case 0x0308:
832 data_w = 640;
833 data_h = 480;
834 break;
835 case 0x0208:
836 data_w = 320;
837 data_h = 240;
838 break;
839 case 0x020A:
840 data_w = 160;
841 data_h = 120;
842 break;
843 /*
844 * Compressed modes (ViCE - that I don't know how to decode).
845 */
846 case 0x0328: /* 640x480, best quality compression */
847 case 0x0368: /* 640x480, best frame rate compression */
848 case 0x0228: /* 320x240, best quality compression */
849 case 0x0268: /* 320x240, best frame rate compression */
850 case 0x02CA: /* 160x120, best quality compression */
851 case 0x02EA: /* 160x120, best frame rate compression */
852 /* Do nothing with this - not supported */
853 err("Unsupported mode $%04lx", frame->header);
854 return scan_NextFrame;
855 default:
856 /* Catch unknown headers, may help in learning new headers */
857 err("Strange frame->header=$%08lx", frame->header);
858 return scan_NextFrame;
859 }
860
861 /*
862 * Make sure that our writing into output buffer
863 * will not exceed the buffer. Note that we may write
864 * not into current output scanline but in several after
865 * it as well (if we enlarge image vertically.)
866 */
867 if ((frame->curline + 1) >= data_h) {
868 if (uvd->debug >= 3)
869 info("Reached line %d. (frame is done)", frame->curline);
870 return scan_NextFrame;
871 }
872
873 /* Make sure there's enough data for the entire line */
874 len = 3 * data_w; /* <y-data> <uv-data> */
875 assert(len <= sizeof(lineBuffer));
876
877 /* Make sure there's enough data for the entire line */
878 if (RingQueue_GetLength(&uvd->dp) < len)
879 return scan_Out;
880
881 /* Suck one line out of the ring queue */
882 RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
883
884 data = lineBuffer;
885 color = data + data_w; /* Point to where color planes begin */
886
887 /* Bottom-to-top scanning */
888 rw = (int)VIDEOSIZE_Y(frame->request) - (int)(frame->curline) - 1;
889 RESTRICT_TO_RANGE(rw, 0, VIDEOSIZE_Y(frame->request)-1);
890
891 for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
892 int y, rv, gv, bv; /* RGB components */
893
894 if (i < data_w) {
895 y = data[i]; /* Luminosity is the first line */
896
897 /* Apply static color correction */
898 u = color[i*2] + hue_corr;
899 v = color[i*2 + 1] + hue2_corr;
900
901 /* Apply color correction */
902 if (color_corr != 0) {
903 /* Magnify up to 2 times, reduce down to zero saturation */
904 u = 128 + ((ccm + color_corr) * (u - 128)) / ccm;
905 v = 128 + ((ccm + color_corr) * (v - 128)) / ccm;
906 }
907 } else
908 y = 0, u = v = 128;
909
910 YUV_TO_RGB_BY_THE_BOOK(y, u, v, rv, gv, bv);
911 RGB24_PUTPIXEL(frame, i, rw, rv, gv, bv); /* Done by deinterlacing now */
912 }
913 frame->deinterlace = Deinterlace_FillEvenLines;
914
915 /*
916 * Account for number of bytes that we wrote into output V4L frame.
917 * We do it here, after we are done with the scanline, because we
918 * may fill more than one output scanline if we do vertical
919 * enlargement.
920 */
921 frame->curline += 2;
922 *pcopylen += 2 * v4l_linesize;
923
924 if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
925 if (uvd->debug >= 3) {
926 info("All requested lines (%ld.) done.",
927 VIDEOSIZE_Y(frame->request));
928 }
929 return scan_NextFrame;
930 } else
931 return scan_Continue;
932}
933
934/*
935 * ibmcam_model4_128x96_parse_lines()
936 *
937 * This decoder is for one strange data format that is produced by Model 4
938 * camera only in 128x96 mode. This is RGB format and here is its description.
939 * First of all, this is non-interlaced stream, meaning that all scan lines
940 * are present in the datastream. There are 96 consecutive blocks of data
941 * that describe all 96 lines of the image. Each block is 5*128 bytes long
942 * and carries R, G, B components. The format of the block is shown in the
943 * code below. First 128*2 bytes are interleaved R and G components. Then
944 * we have a gap (junk data) 64 bytes long. Then follow B and something
945 * else, also interleaved (this makes another 128*2 bytes). After that
946 * probably another 64 bytes of junk follow.
947 *
948 * History:
949 * 10-Feb-2001 Created.
950 */
951static enum ParseState ibmcam_model4_128x96_parse_lines(
952 struct uvd *uvd,
953 struct usbvideo_frame *frame,
954 long *pcopylen)
955{
956 const unsigned char *data_rv, *data_gv, *data_bv;
957 unsigned int len;
958 int i, v4l_linesize; /* V4L line offset */
959 const int data_w=128, data_h=96;
960 static unsigned char lineBuffer[128*5];
961
962 v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
963
964 /*
965 * Make sure that our writing into output buffer
966 * will not exceed the buffer. Note that we may write
967 * not into current output scanline but in several after
968 * it as well (if we enlarge image vertically.)
969 */
970 if ((frame->curline + 1) >= data_h) {
971 if (uvd->debug >= 3)
972 info("Reached line %d. (frame is done)", frame->curline);
973 return scan_NextFrame;
974 }
975
976 /*
977 * RGRGRG .... RGRG_____________B?B?B? ... B?B?____________
978 * <---- 128*2 ---><---- 64 ---><--- 128*2 ---><--- 64 --->
979 */
980
981 /* Make sure there's enough data for the entire line */
982 len = 5 * data_w;
983 assert(len <= sizeof(lineBuffer));
984
985 /* Make sure there's enough data for the entire line */
986 if (RingQueue_GetLength(&uvd->dp) < len)
987 return scan_Out;
988
989 /* Suck one line out of the ring queue */
990 RingQueue_Dequeue(&uvd->dp, lineBuffer, len);
991
992 data_rv = lineBuffer;
993 data_gv = lineBuffer + 1;
994 data_bv = lineBuffer + data_w*2 + data_w/2;
995 for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
996 int rv, gv, bv; /* RGB components */
997 if (i < data_w) {
998 const int j = i * 2;
999 gv = data_rv[j];
1000 rv = data_gv[j];
1001 bv = data_bv[j];
1002 if (flags & FLAGS_MONOCHROME) {
1003 unsigned long y;
1004 y = rv + gv + bv;
1005 y /= 3;
1006 if (y > 0xFF)
1007 y = 0xFF;
1008 rv = gv = bv = (unsigned char) y;
1009 }
1010 } else {
1011 rv = gv = bv = 0;
1012 }
1013 RGB24_PUTPIXEL(frame, i, frame->curline, rv, gv, bv);
1014 }
1015 frame->deinterlace = Deinterlace_None;
1016 frame->curline++;
1017 *pcopylen += v4l_linesize;
1018
1019 if (frame->curline >= VIDEOSIZE_Y(frame->request)) {
1020 if (uvd->debug >= 3) {
1021 info("All requested lines (%ld.) done.",
1022 VIDEOSIZE_Y(frame->request));
1023 }
1024 return scan_NextFrame;
1025 } else
1026 return scan_Continue;
1027}
1028
1029/*
1030 * ibmcam_ProcessIsocData()
1031 *
1032 * Generic routine to parse the ring queue data. It employs either
1033 * ibmcam_find_header() or ibmcam_parse_lines() to do most
1034 * of work.
1035 *
1036 * History:
1037 * 1/21/00 Created.
1038 */
1039static void ibmcam_ProcessIsocData(struct uvd *uvd,
1040 struct usbvideo_frame *frame)
1041{
1042 enum ParseState newstate;
1043 long copylen = 0;
1044 int mod = IBMCAM_T(uvd)->camera_model;
1045
1046 while (1) {
1047 newstate = scan_Out;
1048 if (RingQueue_GetLength(&uvd->dp) > 0) {
1049 if (frame->scanstate == ScanState_Scanning) {
1050 newstate = ibmcam_find_header(uvd);
1051 } else if (frame->scanstate == ScanState_Lines) {
1052 if ((mod == IBMCAM_MODEL_2) &&
1053 ((uvd->videosize == VIDEOSIZE_352x288) ||
1054 (uvd->videosize == VIDEOSIZE_320x240) ||
1055 (uvd->videosize == VIDEOSIZE_352x240)))
1056 {
1057 newstate = ibmcam_model2_320x240_parse_lines(
1058 uvd, frame, &copylen);
1059 } else if (mod == IBMCAM_MODEL_4) {
1060 /*
1061 * Model 4 cameras (IBM NetCamera) use Model 2 decoder (RGB)
1062 * for 320x240 and above; 160x120 and 176x144 uses Model 1
1063 * decoder (YUV), and 128x96 mode uses ???
1064 */
1065 if ((uvd->videosize == VIDEOSIZE_352x288) ||
1066 (uvd->videosize == VIDEOSIZE_320x240) ||
1067 (uvd->videosize == VIDEOSIZE_352x240))
1068 {
1069 newstate = ibmcam_model2_320x240_parse_lines(uvd, frame, &copylen);
1070 } else if (uvd->videosize == VIDEOSIZE_128x96) {
1071 newstate = ibmcam_model4_128x96_parse_lines(uvd, frame, &copylen);
1072 } else {
1073 newstate = ibmcam_parse_lines(uvd, frame, &copylen);
1074 }
1075 } else if (mod == IBMCAM_MODEL_3) {
1076 newstate = ibmcam_model3_parse_lines(uvd, frame, &copylen);
1077 } else {
1078 newstate = ibmcam_parse_lines(uvd, frame, &copylen);
1079 }
1080 }
1081 }
1082 if (newstate == scan_Continue)
1083 continue;
1084 else if ((newstate == scan_NextFrame) || (newstate == scan_Out))
1085 break;
1086 else
1087 return; /* scan_EndParse */
1088 }
1089
1090 if (newstate == scan_NextFrame) {
1091 frame->frameState = FrameState_Done;
1092 uvd->curframe = -1;
1093 uvd->stats.frame_num++;
1094 if ((mod == IBMCAM_MODEL_2) || (mod == IBMCAM_MODEL_4)) {
1095 /* Need software contrast adjustment for those cameras */
1096 frame->flags |= USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST;
1097 }
1098 }
1099
1100 /* Update the frame's uncompressed length. */
1101 frame->seqRead_Length += copylen;
1102
1103#if 0
1104 {
1105 static unsigned char j=0;
1106 memset(frame->data, j++, uvd->max_frame_size);
1107 frame->frameState = FrameState_Ready;
1108 }
1109#endif
1110}
1111
1112/*
1113 * ibmcam_veio()
1114 *
1115 * History:
1116 * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged.
1117 */
1118static int ibmcam_veio(
1119 struct uvd *uvd,
1120 unsigned char req,
1121 unsigned short value,
1122 unsigned short index)
1123{
1124 static const char proc[] = "ibmcam_veio";
1125 unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
1126 int i;
1127
1128 if (!CAMERA_IS_OPERATIONAL(uvd))
1129 return 0;
1130
1131 if (req == 1) {
1132 i = usb_control_msg(
1133 uvd->dev,
1134 usb_rcvctrlpipe(uvd->dev, 0),
1135 req,
1136 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
1137 value,
1138 index,
1139 cp,
1140 sizeof(cp),
1141 1000);
1142#if 0
1143 info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
1144 "(req=$%02x val=$%04x ind=$%04x)",
1145 cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
1146 req, value, index);
1147#endif
1148 } else {
1149 i = usb_control_msg(
1150 uvd->dev,
1151 usb_sndctrlpipe(uvd->dev, 0),
1152 req,
1153 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT,
1154 value,
1155 index,
1156 NULL,
1157 0,
1158 1000);
1159 }
1160 if (i < 0) {
1161 err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
1162 proc, i);
1163 uvd->last_error = i;
1164 }
1165 return i;
1166}
1167
1168/*
1169 * ibmcam_calculate_fps()
1170 *
1171 * This procedure roughly calculates the real frame rate based
1172 * on FPS code (framerate=NNN option). Actual FPS differs
1173 * slightly depending on lighting conditions, so that actual frame
1174 * rate is determined by the camera. Since I don't know how to ask
1175 * the camera what FPS is now I have to use the FPS code instead.
1176 *
1177 * The FPS code is in range [0..6], 0 is slowest, 6 is fastest.
1178 * Corresponding real FPS should be in range [3..30] frames per second.
1179 * The conversion formula is obvious:
1180 *
1181 * real_fps = 3 + (fps_code * 4.5)
1182 *
1183 * History:
1184 * 1/18/00 Created.
1185 */
1186static int ibmcam_calculate_fps(struct uvd *uvd)
1187{
1188 return 3 + framerate*4 + framerate/2;
1189}
1190
1191/*
1192 * ibmcam_send_FF_04_02()
1193 *
1194 * This procedure sends magic 3-command prefix to the camera.
1195 * The purpose of this prefix is not known.
1196 *
1197 * History:
1198 * 1/2/00 Created.
1199 */
1200static void ibmcam_send_FF_04_02(struct uvd *uvd)
1201{
1202 ibmcam_veio(uvd, 0, 0x00FF, 0x0127);
1203 ibmcam_veio(uvd, 0, 0x0004, 0x0124);
1204 ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1205}
1206
1207static void ibmcam_send_00_04_06(struct uvd *uvd)
1208{
1209 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
1210 ibmcam_veio(uvd, 0, 0x0004, 0x0124);
1211 ibmcam_veio(uvd, 0, 0x0006, 0x0124);
1212}
1213
1214static void ibmcam_send_x_00(struct uvd *uvd, unsigned short x)
1215{
1216 ibmcam_veio(uvd, 0, x, 0x0127);
1217 ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1218}
1219
1220static void ibmcam_send_x_00_05(struct uvd *uvd, unsigned short x)
1221{
1222 ibmcam_send_x_00(uvd, x);
1223 ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1224}
1225
1226static void ibmcam_send_x_00_05_02(struct uvd *uvd, unsigned short x)
1227{
1228 ibmcam_veio(uvd, 0, x, 0x0127);
1229 ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1230 ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1231 ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1232}
1233
1234static void ibmcam_send_x_01_00_05(struct uvd *uvd, unsigned short x)
1235{
1236 ibmcam_veio(uvd, 0, x, 0x0127);
1237 ibmcam_veio(uvd, 0, 0x0001, 0x0124);
1238 ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1239 ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1240}
1241
1242static void ibmcam_send_x_00_05_02_01(struct uvd *uvd, unsigned short x)
1243{
1244 ibmcam_veio(uvd, 0, x, 0x0127);
1245 ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1246 ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1247 ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1248 ibmcam_veio(uvd, 0, 0x0001, 0x0124);
1249}
1250
1251static void ibmcam_send_x_00_05_02_08_01(struct uvd *uvd, unsigned short x)
1252{
1253 ibmcam_veio(uvd, 0, x, 0x0127);
1254 ibmcam_veio(uvd, 0, 0x0000, 0x0124);
1255 ibmcam_veio(uvd, 0, 0x0005, 0x0124);
1256 ibmcam_veio(uvd, 0, 0x0002, 0x0124);
1257 ibmcam_veio(uvd, 0, 0x0008, 0x0124);
1258 ibmcam_veio(uvd, 0, 0x0001, 0x0124);
1259}
1260
1261static void ibmcam_Packet_Format1(struct uvd *uvd, unsigned char fkey, unsigned char val)
1262{
1263 ibmcam_send_x_01_00_05(uvd, unknown_88);
1264 ibmcam_send_x_00_05(uvd, fkey);
1265 ibmcam_send_x_00_05_02_08_01(uvd, val);
1266 ibmcam_send_x_00_05(uvd, unknown_88);
1267 ibmcam_send_x_00_05_02_01(uvd, fkey);
1268 ibmcam_send_x_00_05(uvd, unknown_89);
1269 ibmcam_send_x_00(uvd, fkey);
1270 ibmcam_send_00_04_06(uvd);
1271 ibmcam_veio(uvd, 1, 0x0000, 0x0126);
1272 ibmcam_send_FF_04_02(uvd);
1273}
1274
1275static void ibmcam_PacketFormat2(struct uvd *uvd, unsigned char fkey, unsigned char val)
1276{
1277 ibmcam_send_x_01_00_05 (uvd, unknown_88);
1278 ibmcam_send_x_00_05 (uvd, fkey);
1279 ibmcam_send_x_00_05_02 (uvd, val);
1280}
1281
1282static void ibmcam_model2_Packet2(struct uvd *uvd)
1283{
1284 ibmcam_veio(uvd, 0, 0x00ff, 0x012d);
1285 ibmcam_veio(uvd, 0, 0xfea3, 0x0124);
1286}
1287
1288static void ibmcam_model2_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
1289{
1290 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
1291 ibmcam_veio(uvd, 0, 0x00ff, 0x012e);
1292 ibmcam_veio(uvd, 0, v1, 0x012f);
1293 ibmcam_veio(uvd, 0, 0x00ff, 0x0130);
1294 ibmcam_veio(uvd, 0, 0xc719, 0x0124);
1295 ibmcam_veio(uvd, 0, v2, 0x0127);
1296
1297 ibmcam_model2_Packet2(uvd);
1298}
1299
1300/*
1301 * ibmcam_model3_Packet1()
1302 *
1303 * 00_0078_012d
1304 * 00_0097_012f
1305 * 00_d141_0124
1306 * 00_0096_0127
1307 * 00_fea8_0124
1308*/
1309static void ibmcam_model3_Packet1(struct uvd *uvd, unsigned short v1, unsigned short v2)
1310{
1311 ibmcam_veio(uvd, 0, 0x0078, 0x012d);
1312 ibmcam_veio(uvd, 0, v1, 0x012f);
1313 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
1314 ibmcam_veio(uvd, 0, v2, 0x0127);
1315 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
1316}
1317
1318static void ibmcam_model4_BrightnessPacket(struct uvd *uvd, int i)
1319{
1320 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
1321 ibmcam_veio(uvd, 0, 0x0026, 0x012f);
1322 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
1323 ibmcam_veio(uvd, 0, i, 0x0127);
1324 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
1325 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
1326 ibmcam_veio(uvd, 0, 0x0038, 0x012d);
1327 ibmcam_veio(uvd, 0, 0x0004, 0x012f);
1328 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
1329 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
1330}
1331
1332/*
1333 * ibmcam_adjust_contrast()
1334 *
1335 * The contrast value changes from 0 (high contrast) to 15 (low contrast).
1336 * This is in reverse to usual order of things (such as TV controls), so
1337 * we reverse it again here.
1338 *
1339 * TODO: we probably don't need to send the setup 5 times...
1340 *
1341 * History:
1342 * 1/2/00 Created.
1343 */
1344static void ibmcam_adjust_contrast(struct uvd *uvd)
1345{
1346 unsigned char a_contrast = uvd->vpic.contrast >> 12;
1347 unsigned char new_contrast;
1348
1349 if (a_contrast >= 16)
1350 a_contrast = 15;
1351 new_contrast = 15 - a_contrast;
1352 if (new_contrast == uvd->vpic_old.contrast)
1353 return;
1354 uvd->vpic_old.contrast = new_contrast;
1355 switch (IBMCAM_T(uvd)->camera_model) {
1356 case IBMCAM_MODEL_1:
1357 {
1358 const int ntries = 5;
1359 int i;
1360 for (i=0; i < ntries; i++) {
1361 ibmcam_Packet_Format1(uvd, contrast_14, new_contrast);
1362 ibmcam_send_FF_04_02(uvd);
1363 }
1364 break;
1365 }
1366 case IBMCAM_MODEL_2:
1367 case IBMCAM_MODEL_4:
1368 /* Models 2, 4 do not have this control; implemented in software. */
1369 break;
1370 case IBMCAM_MODEL_3:
1371 { /* Preset hardware values */
1372 static const struct {
1373 unsigned short cv1;
1374 unsigned short cv2;
1375 unsigned short cv3;
1376 } cv[7] = {
1377 { 0x05, 0x05, 0x0f }, /* Minimum */
1378 { 0x04, 0x04, 0x16 },
1379 { 0x02, 0x03, 0x16 },
1380 { 0x02, 0x08, 0x16 },
1381 { 0x01, 0x0c, 0x16 },
1382 { 0x01, 0x0e, 0x16 },
1383 { 0x01, 0x10, 0x16 } /* Maximum */
1384 };
1385 int i = a_contrast / 2;
1386 RESTRICT_TO_RANGE(i, 0, 6);
1387 ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */
1388 ibmcam_model3_Packet1(uvd, 0x0067, cv[i].cv1);
1389 ibmcam_model3_Packet1(uvd, 0x005b, cv[i].cv2);
1390 ibmcam_model3_Packet1(uvd, 0x005c, cv[i].cv3);
1391 ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1392 ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */
1393 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1394 break;
1395 }
1396 default:
1397 break;
1398 }
1399}
1400
1401/*
1402 * ibmcam_change_lighting_conditions()
1403 *
1404 * Camera model 1:
1405 * We have 3 levels of lighting conditions: 0=Bright, 1=Medium, 2=Low.
1406 *
1407 * Camera model 2:
1408 * We have 16 levels of lighting, 0 for bright light and up to 15 for
1409 * low light. But values above 5 or so are useless because camera is
1410 * not really capable to produce anything worth viewing at such light.
1411 * This setting may be altered only in certain camera state.
1412 *
1413 * Low lighting forces slower FPS. Lighting is set as a module parameter.
1414 *
1415 * History:
1416 * 1/5/00 Created.
1417 * 2/20/00 Added support for Model 2 cameras.
1418 */
1419static void ibmcam_change_lighting_conditions(struct uvd *uvd)
1420{
1421 static const char proc[] = "ibmcam_change_lighting_conditions";
1422
1423 if (debug > 0)
1424 info("%s: Set lighting to %hu.", proc, lighting);
1425
1426 switch (IBMCAM_T(uvd)->camera_model) {
1427 case IBMCAM_MODEL_1:
1428 {
1429 const int ntries = 5;
1430 int i;
1431 for (i=0; i < ntries; i++)
1432 ibmcam_Packet_Format1(uvd, light_27, (unsigned short) lighting);
1433 break;
1434 }
1435 case IBMCAM_MODEL_2:
1436#if 0
1437 /*
1438 * This command apparently requires camera to be stopped. My
1439 * experiments showed that it -is- possible to alter the lighting
1440 * conditions setting "on the fly", but why bother? This setting does
1441 * not work reliably in all cases, so I decided simply to leave the
1442 * setting where Xirlink put it - in the camera setup phase. This code
1443 * is commented out because it does not work at -any- moment, so its
1444 * presence makes no sense. You may use it for experiments.
1445 */
1446 ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop camera */
1447 ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
1448 ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Start camera */
1449#endif
1450 break;
1451 case IBMCAM_MODEL_3:
1452 case IBMCAM_MODEL_4:
1453 default:
1454 break;
1455 }
1456}
1457
1458/*
1459 * ibmcam_set_sharpness()
1460 *
1461 * Cameras model 1 have internal smoothing feature. It is controlled by value in
1462 * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
1463 * Recommended value is 4. Cameras model 2 do not have this feature at all.
1464 */
1465static void ibmcam_set_sharpness(struct uvd *uvd)
1466{
1467 static const char proc[] = "ibmcam_set_sharpness";
1468
1469 switch (IBMCAM_T(uvd)->camera_model) {
1470 case IBMCAM_MODEL_1:
1471 {
1472 static const unsigned short sa[] = { 0x11, 0x13, 0x16, 0x18, 0x1a, 0x8, 0x0a };
1473 unsigned short i, sv;
1474
1475 RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
1476 if (debug > 0)
1477 info("%s: Set sharpness to %hu.", proc, sharpness);
1478
1479 sv = sa[sharpness - SHARPNESS_MIN];
1480 for (i=0; i < 2; i++) {
1481 ibmcam_send_x_01_00_05 (uvd, unknown_88);
1482 ibmcam_send_x_00_05 (uvd, sharp_13);
1483 ibmcam_send_x_00_05_02 (uvd, sv);
1484 }
1485 break;
1486 }
1487 case IBMCAM_MODEL_2:
1488 case IBMCAM_MODEL_4:
1489 /* Models 2, 4 do not have this control */
1490 break;
1491 case IBMCAM_MODEL_3:
1492 { /*
1493 * "Use a table of magic numbers.
1494 * This setting doesn't really change much.
1495 * But that's how Windows does it."
1496 */
1497 static const struct {
1498 unsigned short sv1;
1499 unsigned short sv2;
1500 unsigned short sv3;
1501 unsigned short sv4;
1502 } sv[7] = {
1503 { 0x00, 0x00, 0x05, 0x14 }, /* Smoothest */
1504 { 0x01, 0x04, 0x05, 0x14 },
1505 { 0x02, 0x04, 0x05, 0x14 },
1506 { 0x03, 0x04, 0x05, 0x14 },
1507 { 0x03, 0x05, 0x05, 0x14 },
1508 { 0x03, 0x06, 0x05, 0x14 },
1509 { 0x03, 0x07, 0x05, 0x14 } /* Sharpest */
1510 };
1511 RESTRICT_TO_RANGE(sharpness, SHARPNESS_MIN, SHARPNESS_MAX);
1512 RESTRICT_TO_RANGE(sharpness, 0, 6);
1513 ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */
1514 ibmcam_model3_Packet1(uvd, 0x0060, sv[sharpness].sv1);
1515 ibmcam_model3_Packet1(uvd, 0x0061, sv[sharpness].sv2);
1516 ibmcam_model3_Packet1(uvd, 0x0062, sv[sharpness].sv3);
1517 ibmcam_model3_Packet1(uvd, 0x0063, sv[sharpness].sv4);
1518 ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1519 ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */
1520 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1521 ibmcam_veio(uvd, 0, 0x0001, 0x0113);
1522 break;
1523 }
1524 default:
1525 break;
1526 }
1527}
1528
1529/*
1530 * ibmcam_set_brightness()
1531 *
1532 * This procedure changes brightness of the picture.
1533 */
1534static void ibmcam_set_brightness(struct uvd *uvd)
1535{
1536 static const char proc[] = "ibmcam_set_brightness";
1537 static const unsigned short n = 1;
1538
1539 if (debug > 0)
1540 info("%s: Set brightness to %hu.", proc, uvd->vpic.brightness);
1541
1542 switch (IBMCAM_T(uvd)->camera_model) {
1543 case IBMCAM_MODEL_1:
1544 {
1545 unsigned short i, j, bv[3];
1546 bv[0] = bv[1] = bv[2] = uvd->vpic.brightness >> 10;
1547 if (bv[0] == (uvd->vpic_old.brightness >> 10))
1548 return;
1549 uvd->vpic_old.brightness = bv[0];
1550 for (j=0; j < 3; j++)
1551 for (i=0; i < n; i++)
1552 ibmcam_Packet_Format1(uvd, bright_3x[j], bv[j]);
1553 break;
1554 }
1555 case IBMCAM_MODEL_2:
1556 {
1557 unsigned short i, j;
1558 i = uvd->vpic.brightness >> 12; /* 0 .. 15 */
1559 j = 0x60 + i * ((0xee - 0x60) / 16); /* 0x60 .. 0xee or so */
1560 if (uvd->vpic_old.brightness == j)
1561 break;
1562 uvd->vpic_old.brightness = j;
1563 ibmcam_model2_Packet1(uvd, mod2_brightness, j);
1564 break;
1565 }
1566 case IBMCAM_MODEL_3:
1567 {
1568 /* Model 3: Brightness range 'i' in [0x0C..0x3F] */
1569 unsigned short i =
1570 0x0C + (uvd->vpic.brightness / (0xFFFF / (0x3F - 0x0C + 1)));
1571 RESTRICT_TO_RANGE(i, 0x0C, 0x3F);
1572 if (uvd->vpic_old.brightness == i)
1573 break;
1574 uvd->vpic_old.brightness = i;
1575 ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */
1576 ibmcam_model3_Packet1(uvd, 0x0036, i);
1577 ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1578 ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */
1579 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1580 ibmcam_veio(uvd, 0, 0x0001, 0x0113);
1581 break;
1582 }
1583 case IBMCAM_MODEL_4:
1584 {
1585 /* Model 4: Brightness range 'i' in [0x04..0xb4] */
1586 unsigned short i = 0x04 + (uvd->vpic.brightness / (0xFFFF / (0xb4 - 0x04 + 1)));
1587 RESTRICT_TO_RANGE(i, 0x04, 0xb4);
1588 if (uvd->vpic_old.brightness == i)
1589 break;
1590 uvd->vpic_old.brightness = i;
1591 ibmcam_model4_BrightnessPacket(uvd, i);
1592 break;
1593 }
1594 default:
1595 break;
1596 }
1597}
1598
1599static void ibmcam_set_hue(struct uvd *uvd)
1600{
1601 switch (IBMCAM_T(uvd)->camera_model) {
1602 case IBMCAM_MODEL_2:
1603 {
1604 unsigned short hue = uvd->vpic.hue >> 9; /* 0 .. 7F */
1605 if (uvd->vpic_old.hue == hue)
1606 return;
1607 uvd->vpic_old.hue = hue;
1608 ibmcam_model2_Packet1(uvd, mod2_hue, hue);
1609 /* ibmcam_model2_Packet1(uvd, mod2_saturation, sat); */
1610 break;
1611 }
1612 case IBMCAM_MODEL_3:
1613 {
1614#if 0 /* This seems not to work. No problem, will fix programmatically */
1615 unsigned short hue = 0x05 + (uvd->vpic.hue / (0xFFFF / (0x37 - 0x05 + 1)));
1616 RESTRICT_TO_RANGE(hue, 0x05, 0x37);
1617 if (uvd->vpic_old.hue == hue)
1618 return;
1619 uvd->vpic_old.hue = hue;
1620 ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop */
1621 ibmcam_model3_Packet1(uvd, 0x007e, hue);
1622 ibmcam_veio(uvd, 0, 0x0001, 0x0114);
1623 ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go! */
1624 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
1625 ibmcam_veio(uvd, 0, 0x0001, 0x0113);
1626#endif
1627 break;
1628 }
1629 case IBMCAM_MODEL_4:
1630 {
1631 unsigned short r_gain, g_gain, b_gain, hue;
1632
1633 /*
1634 * I am not sure r/g/b_gain variables exactly control gain
1635 * of those channels. Most likely they subtly change some
1636 * very internal image processing settings in the camera.
1637 * In any case, here is what they do, and feel free to tweak:
1638 *
1639 * r_gain: seriously affects red gain
1640 * g_gain: seriously affects green gain
1641 * b_gain: seriously affects blue gain
1642 * hue: changes average color from violet (0) to red (0xFF)
1643 *
1644 * These settings are preset for a decent white balance in
1645 * 320x240, 352x288 modes. Low-res modes exhibit higher contrast
1646 * and therefore may need different values here.
1647 */
1648 hue = 20 + (uvd->vpic.hue >> 9);
1649 switch (uvd->videosize) {
1650 case VIDEOSIZE_128x96:
1651 r_gain = 90;
1652 g_gain = 166;
1653 b_gain = 175;
1654 break;
1655 case VIDEOSIZE_160x120:
1656 r_gain = 70;
1657 g_gain = 166;
1658 b_gain = 185;
1659 break;
1660 case VIDEOSIZE_176x144:
1661 r_gain = 160;
1662 g_gain = 175;
1663 b_gain = 185;
1664 break;
1665 default:
1666 r_gain = 120;
1667 g_gain = 166;
1668 b_gain = 175;
1669 break;
1670 }
1671 RESTRICT_TO_RANGE(hue, 1, 0x7f);
1672
1673 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
1674 ibmcam_veio(uvd, 0, 0x001e, 0x012f);
1675 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
1676 ibmcam_veio(uvd, 0, g_gain, 0x0127); /* Green gain */
1677 ibmcam_veio(uvd, 0, r_gain, 0x012e); /* Red gain */
1678 ibmcam_veio(uvd, 0, b_gain, 0x0130); /* Blue gain */
1679 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
1680 ibmcam_veio(uvd, 0, hue, 0x012d); /* Hue */
1681 ibmcam_veio(uvd, 0, 0xf545, 0x0124);
1682 break;
1683 }
1684 default:
1685 break;
1686 }
1687}
1688
1689/*
1690 * ibmcam_adjust_picture()
1691 *
1692 * This procedure gets called from V4L interface to update picture settings.
1693 * Here we change brightness and contrast.
1694 */
1695static void ibmcam_adjust_picture(struct uvd *uvd)
1696{
1697 ibmcam_adjust_contrast(uvd);
1698 ibmcam_set_brightness(uvd);
1699 ibmcam_set_hue(uvd);
1700}
1701
1702static int ibmcam_model1_setup(struct uvd *uvd)
1703{
1704 const int ntries = 5;
1705 int i;
1706
1707 ibmcam_veio(uvd, 1, 0x00, 0x0128);
1708 ibmcam_veio(uvd, 1, 0x00, 0x0100);
1709 ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */
1710 ibmcam_veio(uvd, 1, 0x00, 0x0100);
1711 ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */
1712 ibmcam_veio(uvd, 1, 0x00, 0x0100);
1713 ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */
1714 ibmcam_veio(uvd, 0, 0x01, 0x0108);
1715
1716 ibmcam_veio(uvd, 0, 0x03, 0x0112);
1717 ibmcam_veio(uvd, 1, 0x00, 0x0115);
1718 ibmcam_veio(uvd, 0, 0x06, 0x0115);
1719 ibmcam_veio(uvd, 1, 0x00, 0x0116);
1720 ibmcam_veio(uvd, 0, 0x44, 0x0116);
1721 ibmcam_veio(uvd, 1, 0x00, 0x0116);
1722 ibmcam_veio(uvd, 0, 0x40, 0x0116);
1723 ibmcam_veio(uvd, 1, 0x00, 0x0115);
1724 ibmcam_veio(uvd, 0, 0x0e, 0x0115);
1725 ibmcam_veio(uvd, 0, 0x19, 0x012c);
1726
1727 ibmcam_Packet_Format1(uvd, 0x00, 0x1e);
1728 ibmcam_Packet_Format1(uvd, 0x39, 0x0d);
1729 ibmcam_Packet_Format1(uvd, 0x39, 0x09);
1730 ibmcam_Packet_Format1(uvd, 0x3b, 0x00);
1731 ibmcam_Packet_Format1(uvd, 0x28, 0x22);
1732 ibmcam_Packet_Format1(uvd, light_27, 0);
1733 ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
1734 ibmcam_Packet_Format1(uvd, 0x39, 0x08);
1735
1736 for (i=0; i < ntries; i++)
1737 ibmcam_Packet_Format1(uvd, 0x2c, 0x00);
1738
1739 for (i=0; i < ntries; i++)
1740 ibmcam_Packet_Format1(uvd, 0x30, 0x14);
1741
1742 ibmcam_PacketFormat2(uvd, 0x39, 0x02);
1743 ibmcam_PacketFormat2(uvd, 0x01, 0xe1);
1744 ibmcam_PacketFormat2(uvd, 0x02, 0xcd);
1745 ibmcam_PacketFormat2(uvd, 0x03, 0xcd);
1746 ibmcam_PacketFormat2(uvd, 0x04, 0xfa);
1747 ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
1748 ibmcam_PacketFormat2(uvd, 0x39, 0x00);
1749
1750 ibmcam_PacketFormat2(uvd, 0x39, 0x02);
1751 ibmcam_PacketFormat2(uvd, 0x0a, 0x37);
1752 ibmcam_PacketFormat2(uvd, 0x0b, 0xb8);
1753 ibmcam_PacketFormat2(uvd, 0x0c, 0xf3);
1754 ibmcam_PacketFormat2(uvd, 0x0d, 0xe3);
1755 ibmcam_PacketFormat2(uvd, 0x0e, 0x0d);
1756 ibmcam_PacketFormat2(uvd, 0x0f, 0xf2);
1757 ibmcam_PacketFormat2(uvd, 0x10, 0xd5);
1758 ibmcam_PacketFormat2(uvd, 0x11, 0xba);
1759 ibmcam_PacketFormat2(uvd, 0x12, 0x53);
1760 ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
1761 ibmcam_PacketFormat2(uvd, 0x39, 0x00);
1762
1763 ibmcam_PacketFormat2(uvd, 0x39, 0x02);
1764 ibmcam_PacketFormat2(uvd, 0x16, 0x00);
1765 ibmcam_PacketFormat2(uvd, 0x17, 0x28);
1766 ibmcam_PacketFormat2(uvd, 0x18, 0x7d);
1767 ibmcam_PacketFormat2(uvd, 0x19, 0xbe);
1768 ibmcam_PacketFormat2(uvd, 0x3f, 0xff);
1769 ibmcam_PacketFormat2(uvd, 0x39, 0x00);
1770
1771 for (i=0; i < ntries; i++)
1772 ibmcam_Packet_Format1(uvd, 0x00, 0x18);
1773 for (i=0; i < ntries; i++)
1774 ibmcam_Packet_Format1(uvd, 0x13, 0x18);
1775 for (i=0; i < ntries; i++)
1776 ibmcam_Packet_Format1(uvd, 0x14, 0x06);
1777
1778 /* This is default brightness */
1779 for (i=0; i < ntries; i++)
1780 ibmcam_Packet_Format1(uvd, 0x31, 0x37);
1781 for (i=0; i < ntries; i++)
1782 ibmcam_Packet_Format1(uvd, 0x32, 0x46);
1783 for (i=0; i < ntries; i++)
1784 ibmcam_Packet_Format1(uvd, 0x33, 0x55);
1785
1786 ibmcam_Packet_Format1(uvd, 0x2e, 0x04);
1787 for (i=0; i < ntries; i++)
1788 ibmcam_Packet_Format1(uvd, 0x2d, 0x04);
1789 for (i=0; i < ntries; i++)
1790 ibmcam_Packet_Format1(uvd, 0x29, 0x80);
1791 ibmcam_Packet_Format1(uvd, 0x2c, 0x01);
1792 ibmcam_Packet_Format1(uvd, 0x30, 0x17);
1793 ibmcam_Packet_Format1(uvd, 0x39, 0x08);
1794 for (i=0; i < ntries; i++)
1795 ibmcam_Packet_Format1(uvd, 0x34, 0x00);
1796
1797 ibmcam_veio(uvd, 0, 0x00, 0x0101);
1798 ibmcam_veio(uvd, 0, 0x00, 0x010a);
1799
1800 switch (uvd->videosize) {
1801 case VIDEOSIZE_128x96:
1802 ibmcam_veio(uvd, 0, 0x80, 0x0103);
1803 ibmcam_veio(uvd, 0, 0x60, 0x0105);
1804 ibmcam_veio(uvd, 0, 0x0c, 0x010b);
1805 ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */
1806 ibmcam_veio(uvd, 0, 0x0b, 0x011d);
1807 ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */
1808 ibmcam_veio(uvd, 0, 0x00, 0x0129);
1809 break;
1810 case VIDEOSIZE_176x144:
1811 ibmcam_veio(uvd, 0, 0xb0, 0x0103);
1812 ibmcam_veio(uvd, 0, 0x8f, 0x0105);
1813 ibmcam_veio(uvd, 0, 0x06, 0x010b);
1814 ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */
1815 ibmcam_veio(uvd, 0, 0x0d, 0x011d);
1816 ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */
1817 ibmcam_veio(uvd, 0, 0x03, 0x0129);
1818 break;
1819 case VIDEOSIZE_352x288:
1820 ibmcam_veio(uvd, 0, 0xb0, 0x0103);
1821 ibmcam_veio(uvd, 0, 0x90, 0x0105);
1822 ibmcam_veio(uvd, 0, 0x02, 0x010b);
1823 ibmcam_veio(uvd, 0, 0x04, 0x011b); /* Same everywhere */
1824 ibmcam_veio(uvd, 0, 0x05, 0x011d);
1825 ibmcam_veio(uvd, 0, 0x00, 0x011e); /* Same everywhere */
1826 ibmcam_veio(uvd, 0, 0x00, 0x0129);
1827 break;
1828 }
1829
1830 ibmcam_veio(uvd, 0, 0xff, 0x012b);
1831
1832 /* This is another brightness - don't know why */
1833 for (i=0; i < ntries; i++)
1834 ibmcam_Packet_Format1(uvd, 0x31, 0xc3);
1835 for (i=0; i < ntries; i++)
1836 ibmcam_Packet_Format1(uvd, 0x32, 0xd2);
1837 for (i=0; i < ntries; i++)
1838 ibmcam_Packet_Format1(uvd, 0x33, 0xe1);
1839
1840 /* Default contrast */
1841 for (i=0; i < ntries; i++)
1842 ibmcam_Packet_Format1(uvd, contrast_14, 0x0a);
1843
1844 /* Default sharpness */
1845 for (i=0; i < 2; i++)
1846 ibmcam_PacketFormat2(uvd, sharp_13, 0x1a); /* Level 4 FIXME */
1847
1848 /* Default lighting conditions */
1849 ibmcam_Packet_Format1(uvd, light_27, lighting); /* 0=Bright 2=Low */
1850
1851 /* Assorted init */
1852
1853 switch (uvd->videosize) {
1854 case VIDEOSIZE_128x96:
1855 ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
1856 ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */
1857 ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */
1858 ibmcam_veio(uvd, 0, 0x36, 0x0102);
1859 ibmcam_veio(uvd, 0, 0x1a, 0x0104);
1860 ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */
1861 ibmcam_veio(uvd, 0, 0x2b, 0x011c);
1862 ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */
1863#if 0
1864 ibmcam_veio(uvd, 0, 0x00, 0x0106);
1865 ibmcam_veio(uvd, 0, 0x38, 0x0107);
1866#else
1867 ibmcam_veio(uvd, 0, 0x02, 0x0106);
1868 ibmcam_veio(uvd, 0, 0x2a, 0x0107);
1869#endif
1870 break;
1871 case VIDEOSIZE_176x144:
1872 ibmcam_Packet_Format1(uvd, 0x2b, 0x1e);
1873 ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */
1874 ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */
1875 ibmcam_veio(uvd, 0, 0x04, 0x0102);
1876 ibmcam_veio(uvd, 0, 0x02, 0x0104);
1877 ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */
1878 ibmcam_veio(uvd, 0, 0x2b, 0x011c);
1879 ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */
1880 ibmcam_veio(uvd, 0, 0x01, 0x0106);
1881 ibmcam_veio(uvd, 0, 0xca, 0x0107);
1882 break;
1883 case VIDEOSIZE_352x288:
1884 ibmcam_Packet_Format1(uvd, 0x2b, 0x1f);
1885 ibmcam_veio(uvd, 0, 0xc9, 0x0119); /* Same everywhere */
1886 ibmcam_veio(uvd, 0, 0x80, 0x0109); /* Same everywhere */
1887 ibmcam_veio(uvd, 0, 0x08, 0x0102);
1888 ibmcam_veio(uvd, 0, 0x01, 0x0104);
1889 ibmcam_veio(uvd, 0, 0x04, 0x011a); /* Same everywhere */
1890 ibmcam_veio(uvd, 0, 0x2f, 0x011c);
1891 ibmcam_veio(uvd, 0, 0x23, 0x012a); /* Same everywhere */
1892 ibmcam_veio(uvd, 0, 0x03, 0x0106);
1893 ibmcam_veio(uvd, 0, 0xf6, 0x0107);
1894 break;
1895 }
1896 return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
1897}
1898
1899static int ibmcam_model2_setup(struct uvd *uvd)
1900{
1901 ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */
1902 ibmcam_veio(uvd, 1, 0x0000, 0x0116);
1903 ibmcam_veio(uvd, 0, 0x0060, 0x0116);
1904 ibmcam_veio(uvd, 0, 0x0002, 0x0112);
1905 ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
1906 ibmcam_veio(uvd, 0, 0x0008, 0x012b);
1907 ibmcam_veio(uvd, 0, 0x0000, 0x0108);
1908 ibmcam_veio(uvd, 0, 0x0001, 0x0133);
1909 ibmcam_veio(uvd, 0, 0x0001, 0x0102);
1910 switch (uvd->videosize) {
1911 case VIDEOSIZE_176x144:
1912 ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */
1913 ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */
1914 ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */
1915 ibmcam_veio(uvd, 0, 0x00b9, 0x010a); /* Unique to this mode */
1916 ibmcam_veio(uvd, 0, 0x0038, 0x0119); /* Unique to this mode */
1917 ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */
1918 ibmcam_veio(uvd, 0, 0x0090, 0x0107); /* Unique to every mode*/
1919 break;
1920 case VIDEOSIZE_320x240:
1921 ibmcam_veio(uvd, 0, 0x0028, 0x0103); /* Unique to this mode */
1922 ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */
1923 ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */
1924 ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */
1925 ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */
1926 ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */
1927 ibmcam_veio(uvd, 0, 0x0098, 0x0107); /* Unique to every mode*/
1928 break;
1929 case VIDEOSIZE_352x240:
1930 ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */
1931 ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */
1932 ibmcam_veio(uvd, 0, 0x001e, 0x0105); /* 320x240, 352x240 */
1933 ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */
1934 ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */
1935 ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */
1936 ibmcam_veio(uvd, 0, 0x00da, 0x0107); /* Unique to every mode*/
1937 break;
1938 case VIDEOSIZE_352x288:
1939 ibmcam_veio(uvd, 0, 0x002c, 0x0103); /* All except 320x240 */
1940 ibmcam_veio(uvd, 0, 0x0000, 0x0104); /* Same */
1941 ibmcam_veio(uvd, 0, 0x0024, 0x0105); /* 176x144, 352x288 */
1942 ibmcam_veio(uvd, 0, 0x0039, 0x010a); /* All except 176x144 */
1943 ibmcam_veio(uvd, 0, 0x0070, 0x0119); /* All except 176x144 */
1944 ibmcam_veio(uvd, 0, 0x0003, 0x0106); /* Same */
1945 ibmcam_veio(uvd, 0, 0x00fe, 0x0107); /* Unique to every mode*/
1946 break;
1947 }
1948 return (CAMERA_IS_OPERATIONAL(uvd) ? 0 : -EFAULT);
1949}
1950
1951/*
1952 * ibmcam_model1_setup_after_video_if()
1953 *
1954 * This code adds finishing touches to the video data interface.
1955 * Here we configure the frame rate and turn on the LED.
1956 */
1957static void ibmcam_model1_setup_after_video_if(struct uvd *uvd)
1958{
1959 unsigned short internal_frame_rate;
1960
1961 RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
1962 internal_frame_rate = FRAMERATE_MAX - framerate; /* 0=Fast 6=Slow */
1963 ibmcam_veio(uvd, 0, 0x01, 0x0100); /* LED On */
1964 ibmcam_veio(uvd, 0, internal_frame_rate, 0x0111);
1965 ibmcam_veio(uvd, 0, 0x01, 0x0114);
1966 ibmcam_veio(uvd, 0, 0xc0, 0x010c);
1967}
1968
1969static void ibmcam_model2_setup_after_video_if(struct uvd *uvd)
1970{
1971 unsigned short setup_model2_rg2, setup_model2_sat, setup_model2_yb;
1972
1973 ibmcam_veio(uvd, 0, 0x0000, 0x0100); /* LED on */
1974
1975 switch (uvd->videosize) {
1976 case VIDEOSIZE_176x144:
1977 ibmcam_veio(uvd, 0, 0x0050, 0x0111);
1978 ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
1979 break;
1980 case VIDEOSIZE_320x240:
1981 case VIDEOSIZE_352x240:
1982 case VIDEOSIZE_352x288:
1983 ibmcam_veio(uvd, 0, 0x0040, 0x0111);
1984 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
1985 break;
1986 }
1987 ibmcam_veio(uvd, 0, 0x009b, 0x010f);
1988 ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
1989
1990 /*
1991 * Hardware settings, may affect CMOS sensor; not user controls!
1992 * -------------------------------------------------------------
1993 * 0x0004: no effect
1994 * 0x0006: hardware effect
1995 * 0x0008: no effect
1996 * 0x000a: stops video stream, probably important h/w setting
1997 * 0x000c: changes color in hardware manner (not user setting)
1998 * 0x0012: changes number of colors (does not affect speed)
1999 * 0x002a: no effect
2000 * 0x002c: hardware setting (related to scan lines)
2001 * 0x002e: stops video stream, probably important h/w setting
2002 */
2003 ibmcam_model2_Packet1(uvd, 0x000a, 0x005c);
2004 ibmcam_model2_Packet1(uvd, 0x0004, 0x0000);
2005 ibmcam_model2_Packet1(uvd, 0x0006, 0x00fb);
2006 ibmcam_model2_Packet1(uvd, 0x0008, 0x0000);
2007 ibmcam_model2_Packet1(uvd, 0x000c, 0x0009);
2008 ibmcam_model2_Packet1(uvd, 0x0012, 0x000a);
2009 ibmcam_model2_Packet1(uvd, 0x002a, 0x0000);
2010 ibmcam_model2_Packet1(uvd, 0x002c, 0x0000);
2011 ibmcam_model2_Packet1(uvd, 0x002e, 0x0008);
2012
2013 /*
2014 * Function 0x0030 pops up all over the place. Apparently
2015 * it is a hardware control register, with every bit assigned to
2016 * do something.
2017 */
2018 ibmcam_model2_Packet1(uvd, 0x0030, 0x0000);
2019
2020 /*
2021 * Magic control of CMOS sensor. Only lower values like
2022 * 0-3 work, and picture shifts left or right. Don't change.
2023 */
2024 switch (uvd->videosize) {
2025 case VIDEOSIZE_176x144:
2026 ibmcam_model2_Packet1(uvd, 0x0014, 0x0002);
2027 ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
2028 ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
2029 break;
2030 case VIDEOSIZE_320x240:
2031 ibmcam_model2_Packet1(uvd, 0x0014, 0x0009);
2032 ibmcam_model2_Packet1(uvd, 0x0016, 0x0005); /* Horizontal shift */
2033 ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Another hardware setting */
2034 break;
2035 case VIDEOSIZE_352x240:
2036 /* This mode doesn't work as Windows programs it; changed to work */
2037 ibmcam_model2_Packet1(uvd, 0x0014, 0x0009); /* Windows sets this to 8 */
2038 ibmcam_model2_Packet1(uvd, 0x0016, 0x0003); /* Horizontal shift */
2039 ibmcam_model2_Packet1(uvd, 0x0018, 0x0044); /* Windows sets this to 0x0045 */
2040 break;
2041 case VIDEOSIZE_352x288:
2042 ibmcam_model2_Packet1(uvd, 0x0014, 0x0003);
2043 ibmcam_model2_Packet1(uvd, 0x0016, 0x0002); /* Horizontal shift */
2044 ibmcam_model2_Packet1(uvd, 0x0018, 0x004a); /* Another hardware setting */
2045 break;
2046 }
2047
2048 ibmcam_model2_Packet1(uvd, mod2_brightness, 0x005a);
2049
2050 /*
2051 * We have our own frame rate setting varying from 0 (slowest) to 6 (fastest).
2052 * The camera model 2 allows frame rate in range [0..0x1F] where 0 is also the
2053 * slowest setting. However for all practical reasons high settings make no
2054 * sense because USB is not fast enough to support high FPS. Be aware that
2055 * the picture datastream will be severely disrupted if you ask for
2056 * frame rate faster than allowed for the video size - see below:
2057 *
2058 * Allowable ranges (obtained experimentally on OHCI, K6-3, 450 MHz):
2059 * -----------------------------------------------------------------
2060 * 176x144: [6..31]
2061 * 320x240: [8..31]
2062 * 352x240: [10..31]
2063 * 352x288: [16..31] I have to raise lower threshold for stability...
2064 *
2065 * As usual, slower FPS provides better sensitivity.
2066 */
2067 {
2068 short hw_fps=31, i_framerate;
2069
2070 RESTRICT_TO_RANGE(framerate, FRAMERATE_MIN, FRAMERATE_MAX);
2071 i_framerate = FRAMERATE_MAX - framerate + FRAMERATE_MIN;
2072 switch (uvd->videosize) {
2073 case VIDEOSIZE_176x144:
2074 hw_fps = 6 + i_framerate*4;
2075 break;
2076 case VIDEOSIZE_320x240:
2077 hw_fps = 8 + i_framerate*3;
2078 break;
2079 case VIDEOSIZE_352x240:
2080 hw_fps = 10 + i_framerate*2;
2081 break;
2082 case VIDEOSIZE_352x288:
2083 hw_fps = 28 + i_framerate/2;
2084 break;
2085 }
2086 if (uvd->debug > 0)
2087 info("Framerate (hardware): %hd.", hw_fps);
2088 RESTRICT_TO_RANGE(hw_fps, 0, 31);
2089 ibmcam_model2_Packet1(uvd, mod2_set_framerate, hw_fps);
2090 }
2091
2092 /*
2093 * This setting does not visibly affect pictures; left it here
2094 * because it was present in Windows USB data stream. This function
2095 * does not allow arbitrary values and apparently is a bit mask, to
2096 * be activated only at appropriate time. Don't change it randomly!
2097 */
2098 switch (uvd->videosize) {
2099 case VIDEOSIZE_176x144:
2100 ibmcam_model2_Packet1(uvd, 0x0026, 0x00c2);
2101 break;
2102 case VIDEOSIZE_320x240:
2103 ibmcam_model2_Packet1(uvd, 0x0026, 0x0044);
2104 break;
2105 case VIDEOSIZE_352x240:
2106 ibmcam_model2_Packet1(uvd, 0x0026, 0x0046);
2107 break;
2108 case VIDEOSIZE_352x288:
2109 ibmcam_model2_Packet1(uvd, 0x0026, 0x0048);
2110 break;
2111 }
2112
2113 ibmcam_model2_Packet1(uvd, mod2_sensitivity, lighting);
2114
2115 if (init_model2_rg2 >= 0) {
2116 RESTRICT_TO_RANGE(init_model2_rg2, 0, 255);
2117 setup_model2_rg2 = init_model2_rg2;
2118 } else
2119 setup_model2_rg2 = 0x002f;
2120
2121 if (init_model2_sat >= 0) {
2122 RESTRICT_TO_RANGE(init_model2_sat, 0, 255);
2123 setup_model2_sat = init_model2_sat;
2124 } else
2125 setup_model2_sat = 0x0034;
2126
2127 if (init_model2_yb >= 0) {
2128 RESTRICT_TO_RANGE(init_model2_yb, 0, 255);
2129 setup_model2_yb = init_model2_yb;
2130 } else
2131 setup_model2_yb = 0x00a0;
2132
2133 ibmcam_model2_Packet1(uvd, mod2_color_balance_rg2, setup_model2_rg2);
2134 ibmcam_model2_Packet1(uvd, mod2_saturation, setup_model2_sat);
2135 ibmcam_model2_Packet1(uvd, mod2_color_balance_yb, setup_model2_yb);
2136 ibmcam_model2_Packet1(uvd, mod2_hue, uvd->vpic.hue >> 9); /* 0 .. 7F */;
2137
2138 /* Hardware control command */
2139 ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
2140
2141 ibmcam_veio(uvd, 0, 0x00c0, 0x010c); /* Go camera, go! */
2142 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
2143}
2144
2145static void ibmcam_model4_setup_after_video_if(struct uvd *uvd)
2146{
2147 switch (uvd->videosize) {
2148 case VIDEOSIZE_128x96:
2149 ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2150 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2151 ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2152 ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2153 ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2154 ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2155 ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2156 ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2157 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2158 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2159 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2160 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2161 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2162 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2163 ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2164 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2165 ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2166 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2167 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2168 ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2169 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2170 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2171 ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2172 ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2173 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2174 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2175 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2176 ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2177 ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2178 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2179 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2180 ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2181 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2182 ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2183 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2184 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2185 ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2186 ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2187 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2188 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2189 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2190 ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2191 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2192 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2193 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2194 ibmcam_veio(uvd, 0, 0x0070, 0x0119);
2195 ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
2196 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2197 ibmcam_veio(uvd, 0, 0x005e, 0x0107);
2198 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2199 ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2200 ibmcam_veio(uvd, 0, 0x0039, 0x010a);
2201 ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2202 ibmcam_veio(uvd, 0, 0x0028, 0x0103);
2203 ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2204 ibmcam_veio(uvd, 0, 0x001e, 0x0105);
2205 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2206 ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2207 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2208 ibmcam_veio(uvd, 0, 0x000a, 0x0127);
2209 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2210 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2211 ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2212 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2213 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2214 ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2215 ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2216 ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2217 ibmcam_veio(uvd, 0, 0x005a, 0x012d);
2218 ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2219 ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2220 ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2221 ibmcam_veio(uvd, 0, 0x0043, 0x0130);
2222 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2223 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2224 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2225 ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2226 ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
2227 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2228 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2229 ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2230 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2231 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2232 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2233 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2234 ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2235 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2236 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2237 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2238 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2239 ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2240 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2241 ibmcam_veio(uvd, 0, 0x0017, 0x0127);
2242 ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2243 ibmcam_veio(uvd, 0, 0x0031, 0x0130);
2244 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2245 ibmcam_veio(uvd, 0, 0x0017, 0x012d);
2246 ibmcam_veio(uvd, 0, 0x0078, 0x012f);
2247 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2248 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2249 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2250 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2251 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2252 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2253 ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2254 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2255 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2256 break;
2257 case VIDEOSIZE_160x120:
2258 ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2259 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2260 ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2261 ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2262 ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2263 ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2264 ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2265 ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2266 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2267 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2268 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2269 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2270 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2271 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2272 ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2273 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2274 ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2275 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2276 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2277 ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2278 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2279 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2280 ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2281 ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2282 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2283 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2284 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2285 ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2286 ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2287 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2288 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2289 ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2290 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2291 ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2292 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2293 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2294 ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2295 ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2296 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2297 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2298 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2299 ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2300 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2301 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2302 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2303 ibmcam_veio(uvd, 0, 0x0038, 0x0119);
2304 ibmcam_veio(uvd, 0, 0x00d8, 0x0107);
2305 ibmcam_veio(uvd, 0, 0x0002, 0x0106);
2306 ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2307 ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
2308 ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2309 ibmcam_veio(uvd, 0, 0x0028, 0x0103);
2310 ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2311 ibmcam_veio(uvd, 0, 0x001e, 0x0105);
2312 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2313 ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2314 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2315 ibmcam_veio(uvd, 0, 0x000b, 0x0127);
2316 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2317 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2318 ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2319 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2320 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2321 ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2322 ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2323 ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2324 ibmcam_veio(uvd, 0, 0x005a, 0x012d);
2325 ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2326 ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2327 ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2328 ibmcam_veio(uvd, 0, 0x0043, 0x0130);
2329 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2330 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2331 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2332 ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2333 ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
2334 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2335 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2336 ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2337 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2338 ibmcam_veio(uvd, 0, 0x0025, 0x0127);
2339 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2340 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2341 ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2342 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2343 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2344 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2345 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2346 ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2347 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2348 ibmcam_veio(uvd, 0, 0x0048, 0x0127);
2349 ibmcam_veio(uvd, 0, 0x0035, 0x012e);
2350 ibmcam_veio(uvd, 0, 0x00d0, 0x0130);
2351 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2352 ibmcam_veio(uvd, 0, 0x0048, 0x012d);
2353 ibmcam_veio(uvd, 0, 0x0090, 0x012f);
2354 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2355 ibmcam_veio(uvd, 0, 0x0001, 0x0127);
2356 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2357 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2358 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2359 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2360 ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2361 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2362 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2363 break;
2364 case VIDEOSIZE_176x144:
2365 ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2366 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2367 ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2368 ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2369 ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2370 ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2371 ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2372 ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2373 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2374 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2375 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2376 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2377 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2378 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2379 ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2380 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2381 ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2382 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2383 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2384 ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2385 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2386 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2387 ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2388 ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2389 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2390 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2391 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2392 ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2393 ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2394 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2395 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2396 ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2397 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2398 ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2399 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2400 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2401 ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2402 ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2403 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2404 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2405 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2406 ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2407 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2408 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2409 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2410 ibmcam_veio(uvd, 0, 0x0038, 0x0119);
2411 ibmcam_veio(uvd, 0, 0x00d6, 0x0107);
2412 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2413 ibmcam_veio(uvd, 0, 0x0018, 0x0107);
2414 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2415 ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2416 ibmcam_veio(uvd, 0, 0x00b9, 0x010a);
2417 ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2418 ibmcam_veio(uvd, 0, 0x002c, 0x0103);
2419 ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2420 ibmcam_veio(uvd, 0, 0x0024, 0x0105);
2421 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2422 ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2423 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2424 ibmcam_veio(uvd, 0, 0x0007, 0x0127);
2425 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2426 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2427 ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2428 ibmcam_veio(uvd, 0, 0x0001, 0x012f);
2429 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2430 ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2431 ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2432 ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2433 ibmcam_veio(uvd, 0, 0x005e, 0x012d);
2434 ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2435 ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2436 ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2437 ibmcam_veio(uvd, 0, 0x0049, 0x0130);
2438 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2439 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2440 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2441 ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2442 ibmcam_veio(uvd, 0, 0x00c7, 0x012e);
2443 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2444 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2445 ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2446 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2447 ibmcam_veio(uvd, 0, 0x0028, 0x0127);
2448 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2449 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2450 ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2451 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2452 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2453 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2454 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2455 ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2456 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2457 ibmcam_veio(uvd, 0, 0x0010, 0x0127);
2458 ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2459 ibmcam_veio(uvd, 0, 0x002a, 0x0130);
2460 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2461 ibmcam_veio(uvd, 0, 0x0010, 0x012d);
2462 ibmcam_veio(uvd, 0, 0x006d, 0x012f);
2463 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2464 ibmcam_veio(uvd, 0, 0x0001, 0x0127);
2465 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2466 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2467 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2468 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2469 ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2470 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2471 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2472 break;
2473 case VIDEOSIZE_320x240:
2474 ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2475 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2476 ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2477 ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2478 ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2479 ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2480 ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2481 ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2482 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2483 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2484 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2485 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2486 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2487 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2488 ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2489 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2490 ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2491 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2492 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2493 ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2494 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2495 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2496 ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2497 ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2498 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2499 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2500 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2501 ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2502 ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2503 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2504 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2505 ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2506 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2507 ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2508 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2509 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2510 ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2511 ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2512 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2513 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2514 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2515 ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2516 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2517 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2518 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2519 ibmcam_veio(uvd, 0, 0x0070, 0x0119);
2520 ibmcam_veio(uvd, 0, 0x00d2, 0x0107);
2521 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2522 ibmcam_veio(uvd, 0, 0x005e, 0x0107);
2523 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2524 ibmcam_veio(uvd, 0, 0x00d0, 0x0111);
2525 ibmcam_veio(uvd, 0, 0x0039, 0x010a);
2526 ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2527 ibmcam_veio(uvd, 0, 0x0028, 0x0103);
2528 ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2529 ibmcam_veio(uvd, 0, 0x001e, 0x0105);
2530 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2531 ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2532 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2533 ibmcam_veio(uvd, 0, 0x000a, 0x0127);
2534 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2535 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2536 ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2537 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2538 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2539 ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2540 ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2541 ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2542 ibmcam_veio(uvd, 0, 0x005a, 0x012d);
2543 ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2544 ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2545 ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2546 ibmcam_veio(uvd, 0, 0x0043, 0x0130);
2547 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2548 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2549 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2550 ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2551 ibmcam_veio(uvd, 0, 0x00eb, 0x012e);
2552 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2553 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2554 ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2555 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2556 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2557 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2558 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2559 ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2560 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2561 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2562 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2563 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2564 ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2565 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2566 ibmcam_veio(uvd, 0, 0x0017, 0x0127);
2567 ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2568 ibmcam_veio(uvd, 0, 0x0031, 0x0130);
2569 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2570 ibmcam_veio(uvd, 0, 0x0017, 0x012d);
2571 ibmcam_veio(uvd, 0, 0x0078, 0x012f);
2572 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2573 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2574 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2575 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2576 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2577 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2578 ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2579 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2580 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2581 break;
2582 case VIDEOSIZE_352x288:
2583 ibmcam_veio(uvd, 0, 0x0000, 0x0100);
2584 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2585 ibmcam_veio(uvd, 0, 0x00bc, 0x012c);
2586 ibmcam_veio(uvd, 0, 0x0080, 0x012b);
2587 ibmcam_veio(uvd, 0, 0x0000, 0x0108);
2588 ibmcam_veio(uvd, 0, 0x0001, 0x0133);
2589 ibmcam_veio(uvd, 0, 0x009b, 0x010f);
2590 ibmcam_veio(uvd, 0, 0x00bb, 0x010f);
2591 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2592 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2593 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2594 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2595 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2596 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2597 ibmcam_veio(uvd, 0, 0x000a, 0x012f);
2598 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2599 ibmcam_veio(uvd, 0, 0x005c, 0x0127);
2600 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2601 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2602 ibmcam_veio(uvd, 0, 0x0004, 0x012f);
2603 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2604 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2605 ibmcam_veio(uvd, 0, 0x00fb, 0x012e);
2606 ibmcam_veio(uvd, 0, 0x0000, 0x0130);
2607 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2608 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2609 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2610 ibmcam_veio(uvd, 0, 0x000c, 0x0127);
2611 ibmcam_veio(uvd, 0, 0x0009, 0x012e);
2612 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2613 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2614 ibmcam_veio(uvd, 0, 0x0012, 0x012f);
2615 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2616 ibmcam_veio(uvd, 0, 0x0008, 0x0127);
2617 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2618 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2619 ibmcam_veio(uvd, 0, 0x002a, 0x012d);
2620 ibmcam_veio(uvd, 0, 0x0000, 0x012f);
2621 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2622 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2623 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2624 ibmcam_veio(uvd, 0, 0x0034, 0x012f);
2625 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2626 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2627 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2628 ibmcam_veio(uvd, 0, 0x0070, 0x0119);
2629 ibmcam_veio(uvd, 0, 0x00f2, 0x0107);
2630 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2631 ibmcam_veio(uvd, 0, 0x008c, 0x0107);
2632 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
2633 ibmcam_veio(uvd, 0, 0x00c0, 0x0111);
2634 ibmcam_veio(uvd, 0, 0x0039, 0x010a);
2635 ibmcam_veio(uvd, 0, 0x0001, 0x0102);
2636 ibmcam_veio(uvd, 0, 0x002c, 0x0103);
2637 ibmcam_veio(uvd, 0, 0x0000, 0x0104);
2638 ibmcam_veio(uvd, 0, 0x0024, 0x0105);
2639 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2640 ibmcam_veio(uvd, 0, 0x0016, 0x012f);
2641 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2642 ibmcam_veio(uvd, 0, 0x0006, 0x0127);
2643 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2644 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2645 ibmcam_veio(uvd, 0, 0x0014, 0x012d);
2646 ibmcam_veio(uvd, 0, 0x0002, 0x012f);
2647 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2648 ibmcam_veio(uvd, 0, 0x00aa, 0x012e);
2649 ibmcam_veio(uvd, 0, 0x001a, 0x0130);
2650 ibmcam_veio(uvd, 0, 0x8a0a, 0x0124);
2651 ibmcam_veio(uvd, 0, 0x005e, 0x012d);
2652 ibmcam_veio(uvd, 0, 0x9545, 0x0124);
2653 ibmcam_veio(uvd, 0, 0x00aa, 0x0127);
2654 ibmcam_veio(uvd, 0, 0x0018, 0x012e);
2655 ibmcam_veio(uvd, 0, 0x0049, 0x0130);
2656 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2657 ibmcam_veio(uvd, 0, 0x00aa, 0x012f);
2658 ibmcam_veio(uvd, 0, 0xd055, 0x0124);
2659 ibmcam_veio(uvd, 0, 0x001c, 0x0127);
2660 ibmcam_veio(uvd, 0, 0x00cf, 0x012e);
2661 ibmcam_veio(uvd, 0, 0xaa28, 0x0124);
2662 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2663 ibmcam_veio(uvd, 0, 0x0032, 0x012f);
2664 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2665 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2666 ibmcam_veio(uvd, 0, 0x00aa, 0x0130);
2667 ibmcam_veio(uvd, 0, 0x82a8, 0x0124);
2668 ibmcam_veio(uvd, 0, 0x0036, 0x012d);
2669 ibmcam_veio(uvd, 0, 0x0008, 0x012f);
2670 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2671 ibmcam_veio(uvd, 0, 0xfffa, 0x0124);
2672 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2673 ibmcam_veio(uvd, 0, 0x001e, 0x012f);
2674 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2675 ibmcam_veio(uvd, 0, 0x0010, 0x0127);
2676 ibmcam_veio(uvd, 0, 0x0013, 0x012e);
2677 ibmcam_veio(uvd, 0, 0x0025, 0x0130);
2678 ibmcam_veio(uvd, 0, 0x8a28, 0x0124);
2679 ibmcam_veio(uvd, 0, 0x0010, 0x012d);
2680 ibmcam_veio(uvd, 0, 0x0048, 0x012f);
2681 ibmcam_veio(uvd, 0, 0xd145, 0x0124);
2682 ibmcam_veio(uvd, 0, 0x0000, 0x0127);
2683 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2684 ibmcam_veio(uvd, 0, 0x00aa, 0x012d);
2685 ibmcam_veio(uvd, 0, 0x0038, 0x012f);
2686 ibmcam_veio(uvd, 0, 0xd141, 0x0124);
2687 ibmcam_veio(uvd, 0, 0x0004, 0x0127);
2688 ibmcam_veio(uvd, 0, 0xfea8, 0x0124);
2689 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
2690 break;
2691 }
2692 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
2693}
2694
2695static void ibmcam_model3_setup_after_video_if(struct uvd *uvd)
2696{
2697 int i;
2698 /*
2699 * 01.01.08 - Added for RCA video in support -LO
2700 * This struct is used to init the Model3 cam to use the RCA video in port
2701 * instead of the CCD sensor.
2702 */
2703 static const struct struct_initData initData[] = {
2704 {0, 0x0000, 0x010c},
2705 {0, 0x0006, 0x012c},
2706 {0, 0x0078, 0x012d},
2707 {0, 0x0046, 0x012f},
2708 {0, 0xd141, 0x0124},
2709 {0, 0x0000, 0x0127},
2710 {0, 0xfea8, 0x0124},
2711 {1, 0x0000, 0x0116},
2712 {0, 0x0064, 0x0116},
2713 {1, 0x0000, 0x0115},
2714 {0, 0x0003, 0x0115},
2715 {0, 0x0008, 0x0123},
2716 {0, 0x0000, 0x0117},
2717 {0, 0x0000, 0x0112},
2718 {0, 0x0080, 0x0100},
2719 {0, 0x0000, 0x0100},
2720 {1, 0x0000, 0x0116},
2721 {0, 0x0060, 0x0116},
2722 {0, 0x0002, 0x0112},
2723 {0, 0x0000, 0x0123},
2724 {0, 0x0001, 0x0117},
2725 {0, 0x0040, 0x0108},
2726 {0, 0x0019, 0x012c},
2727 {0, 0x0040, 0x0116},
2728 {0, 0x000a, 0x0115},
2729 {0, 0x000b, 0x0115},
2730 {0, 0x0078, 0x012d},
2731 {0, 0x0046, 0x012f},
2732 {0, 0xd141, 0x0124},
2733 {0, 0x0000, 0x0127},
2734 {0, 0xfea8, 0x0124},
2735 {0, 0x0064, 0x0116},
2736 {0, 0x0000, 0x0115},
2737 {0, 0x0001, 0x0115},
2738 {0, 0xffff, 0x0124},
2739 {0, 0xfff9, 0x0124},
2740 {0, 0x0086, 0x0127},
2741 {0, 0xfff8, 0x0124},
2742 {0, 0xfffd, 0x0124},
2743 {0, 0x00aa, 0x0127},
2744 {0, 0xfff8, 0x0124},
2745 {0, 0xfffd, 0x0124},
2746 {0, 0x0000, 0x0127},
2747 {0, 0xfff8, 0x0124},
2748 {0, 0xfffd, 0x0124},
2749 {0, 0xfffa, 0x0124},
2750 {0, 0xffff, 0x0124},
2751 {0, 0xfff9, 0x0124},
2752 {0, 0x0086, 0x0127},
2753 {0, 0xfff8, 0x0124},
2754 {0, 0xfffd, 0x0124},
2755 {0, 0x00f2, 0x0127},
2756 {0, 0xfff8, 0x0124},
2757 {0, 0xfffd, 0x0124},
2758 {0, 0x000f, 0x0127},
2759 {0, 0xfff8, 0x0124},
2760 {0, 0xfffd, 0x0124},
2761 {0, 0xfffa, 0x0124},
2762 {0, 0xffff, 0x0124},
2763 {0, 0xfff9, 0x0124},
2764 {0, 0x0086, 0x0127},
2765 {0, 0xfff8, 0x0124},
2766 {0, 0xfffd, 0x0124},
2767 {0, 0x00f8, 0x0127},
2768 {0, 0xfff8, 0x0124},
2769 {0, 0xfffd, 0x0124},
2770 {0, 0x00fc, 0x0127},
2771 {0, 0xfff8, 0x0124},
2772 {0, 0xfffd, 0x0124},
2773 {0, 0xfffa, 0x0124},
2774 {0, 0xffff, 0x0124},
2775 {0, 0xfff9, 0x0124},
2776 {0, 0x0086, 0x0127},
2777 {0, 0xfff8, 0x0124},
2778 {0, 0xfffd, 0x0124},
2779 {0, 0x00f9, 0x0127},
2780 {0, 0xfff8, 0x0124},
2781 {0, 0xfffd, 0x0124},
2782 {0, 0x003c, 0x0127},
2783 {0, 0xfff8, 0x0124},
2784 {0, 0xfffd, 0x0124},
2785 {0, 0xfffa, 0x0124},
2786 {0, 0xffff, 0x0124},
2787 {0, 0xfff9, 0x0124},
2788 {0, 0x0086, 0x0127},
2789 {0, 0xfff8, 0x0124},
2790 {0, 0xfffd, 0x0124},
2791 {0, 0x0027, 0x0127},
2792 {0, 0xfff8, 0x0124},
2793 {0, 0xfffd, 0x0124},
2794 {0, 0x0019, 0x0127},
2795 {0, 0xfff8, 0x0124},
2796 {0, 0xfffd, 0x0124},
2797 {0, 0xfffa, 0x0124},
2798 {0, 0xfff9, 0x0124},
2799 {0, 0x0086, 0x0127},
2800 {0, 0xfff8, 0x0124},
2801 {0, 0xfffd, 0x0124},
2802 {0, 0x0037, 0x0127},
2803 {0, 0xfff8, 0x0124},
2804 {0, 0xfffd, 0x0124},
2805 {0, 0x0000, 0x0127},
2806 {0, 0xfff8, 0x0124},
2807 {0, 0xfffd, 0x0124},
2808 {0, 0x0021, 0x0127},
2809 {0, 0xfff8, 0x0124},
2810 {0, 0xfffd, 0x0124},
2811 {0, 0xfffa, 0x0124},
2812 {0, 0xfff9, 0x0124},
2813 {0, 0x0086, 0x0127},
2814 {0, 0xfff8, 0x0124},
2815 {0, 0xfffd, 0x0124},
2816 {0, 0x0038, 0x0127},
2817 {0, 0xfff8, 0x0124},
2818 {0, 0xfffd, 0x0124},
2819 {0, 0x0006, 0x0127},
2820 {0, 0xfff8, 0x0124},
2821 {0, 0xfffd, 0x0124},
2822 {0, 0x0045, 0x0127},
2823 {0, 0xfff8, 0x0124},
2824 {0, 0xfffd, 0x0124},
2825 {0, 0xfffa, 0x0124},
2826 {0, 0xfff9, 0x0124},
2827 {0, 0x0086, 0x0127},
2828 {0, 0xfff8, 0x0124},
2829 {0, 0xfffd, 0x0124},
2830 {0, 0x0037, 0x0127},
2831 {0, 0xfff8, 0x0124},
2832 {0, 0xfffd, 0x0124},
2833 {0, 0x0001, 0x0127},
2834 {0, 0xfff8, 0x0124},
2835 {0, 0xfffd, 0x0124},
2836 {0, 0x002a, 0x0127},
2837 {0, 0xfff8, 0x0124},
2838 {0, 0xfffd, 0x0124},
2839 {0, 0xfffa, 0x0124},
2840 {0, 0xfff9, 0x0124},
2841 {0, 0x0086, 0x0127},
2842 {0, 0xfff8, 0x0124},
2843 {0, 0xfffd, 0x0124},
2844 {0, 0x0038, 0x0127},
2845 {0, 0xfff8, 0x0124},
2846 {0, 0xfffd, 0x0124},
2847 {0, 0x0000, 0x0127},
2848 {0, 0xfff8, 0x0124},
2849 {0, 0xfffd, 0x0124},
2850 {0, 0x000e, 0x0127},
2851 {0, 0xfff8, 0x0124},
2852 {0, 0xfffd, 0x0124},
2853 {0, 0xfffa, 0x0124},
2854 {0, 0xfff9, 0x0124},
2855 {0, 0x0086, 0x0127},
2856 {0, 0xfff8, 0x0124},
2857 {0, 0xfffd, 0x0124},
2858 {0, 0x0037, 0x0127},
2859 {0, 0xfff8, 0x0124},
2860 {0, 0xfffd, 0x0124},
2861 {0, 0x0001, 0x0127},
2862 {0, 0xfff8, 0x0124},
2863 {0, 0xfffd, 0x0124},
2864 {0, 0x002b, 0x0127},
2865 {0, 0xfff8, 0x0124},
2866 {0, 0xfffd, 0x0124},
2867 {0, 0xfffa, 0x0124},
2868 {0, 0xfff9, 0x0124},
2869 {0, 0x0086, 0x0127},
2870 {0, 0xfff8, 0x0124},
2871 {0, 0xfffd, 0x0124},
2872 {0, 0x0038, 0x0127},
2873 {0, 0xfff8, 0x0124},
2874 {0, 0xfffd, 0x0124},
2875 {0, 0x0001, 0x0127},
2876 {0, 0xfff8, 0x0124},
2877 {0, 0xfffd, 0x0124},
2878 {0, 0x00f4, 0x0127},
2879 {0, 0xfff8, 0x0124},
2880 {0, 0xfffd, 0x0124},
2881 {0, 0xfffa, 0x0124},
2882 {0, 0xfff9, 0x0124},
2883 {0, 0x0086, 0x0127},
2884 {0, 0xfff8, 0x0124},
2885 {0, 0xfffd, 0x0124},
2886 {0, 0x0037, 0x0127},
2887 {0, 0xfff8, 0x0124},
2888 {0, 0xfffd, 0x0124},
2889 {0, 0x0001, 0x0127},
2890 {0, 0xfff8, 0x0124},
2891 {0, 0xfffd, 0x0124},
2892 {0, 0x002c, 0x0127},
2893 {0, 0xfff8, 0x0124},
2894 {0, 0xfffd, 0x0124},
2895 {0, 0xfffa, 0x0124},
2896 {0, 0xfff9, 0x0124},
2897 {0, 0x0086, 0x0127},
2898 {0, 0xfff8, 0x0124},
2899 {0, 0xfffd, 0x0124},
2900 {0, 0x0038, 0x0127},
2901 {0, 0xfff8, 0x0124},
2902 {0, 0xfffd, 0x0124},
2903 {0, 0x0001, 0x0127},
2904 {0, 0xfff8, 0x0124},
2905 {0, 0xfffd, 0x0124},
2906 {0, 0x0004, 0x0127},
2907 {0, 0xfff8, 0x0124},
2908 {0, 0xfffd, 0x0124},
2909 {0, 0xfffa, 0x0124},
2910 {0, 0xfff9, 0x0124},
2911 {0, 0x0086, 0x0127},
2912 {0, 0xfff8, 0x0124},
2913 {0, 0xfffd, 0x0124},
2914 {0, 0x0037, 0x0127},
2915 {0, 0xfff8, 0x0124},
2916 {0, 0xfffd, 0x0124},
2917 {0, 0x0001, 0x0127},
2918 {0, 0xfff8, 0x0124},
2919 {0, 0xfffd, 0x0124},
2920 {0, 0x002d, 0x0127},
2921 {0, 0xfff8, 0x0124},
2922 {0, 0xfffd, 0x0124},
2923 {0, 0xfffa, 0x0124},
2924 {0, 0xfff9, 0x0124},
2925 {0, 0x0086, 0x0127},
2926 {0, 0xfff8, 0x0124},
2927 {0, 0xfffd, 0x0124},
2928 {0, 0x0038, 0x0127},
2929 {0, 0xfff8, 0x0124},
2930 {0, 0xfffd, 0x0124},
2931 {0, 0x0000, 0x0127},
2932 {0, 0xfff8, 0x0124},
2933 {0, 0xfffd, 0x0124},
2934 {0, 0x0014, 0x0127},
2935 {0, 0xfff8, 0x0124},
2936 {0, 0xfffd, 0x0124},
2937 {0, 0xfffa, 0x0124},
2938 {0, 0xfff9, 0x0124},
2939 {0, 0x0086, 0x0127},
2940 {0, 0xfff8, 0x0124},
2941 {0, 0xfffd, 0x0124},
2942 {0, 0x0037, 0x0127},
2943 {0, 0xfff8, 0x0124},
2944 {0, 0xfffd, 0x0124},
2945 {0, 0x0001, 0x0127},
2946 {0, 0xfff8, 0x0124},
2947 {0, 0xfffd, 0x0124},
2948 {0, 0x002e, 0x0127},
2949 {0, 0xfff8, 0x0124},
2950 {0, 0xfffd, 0x0124},
2951 {0, 0xfffa, 0x0124},
2952 {0, 0xfff9, 0x0124},
2953 {0, 0x0086, 0x0127},
2954 {0, 0xfff8, 0x0124},
2955 {0, 0xfffd, 0x0124},
2956 {0, 0x0038, 0x0127},
2957 {0, 0xfff8, 0x0124},
2958 {0, 0xfffd, 0x0124},
2959 {0, 0x0003, 0x0127},
2960 {0, 0xfff8, 0x0124},
2961 {0, 0xfffd, 0x0124},
2962 {0, 0x0000, 0x0127},
2963 {0, 0xfff8, 0x0124},
2964 {0, 0xfffd, 0x0124},
2965 {0, 0xfffa, 0x0124},
2966 {0, 0xfff9, 0x0124},
2967 {0, 0x0086, 0x0127},
2968 {0, 0xfff8, 0x0124},
2969 {0, 0xfffd, 0x0124},
2970 {0, 0x0037, 0x0127},
2971 {0, 0xfff8, 0x0124},
2972 {0, 0xfffd, 0x0124},
2973 {0, 0x0001, 0x0127},
2974 {0, 0xfff8, 0x0124},
2975 {0, 0xfffd, 0x0124},
2976 {0, 0x002f, 0x0127},
2977 {0, 0xfff8, 0x0124},
2978 {0, 0xfffd, 0x0124},
2979 {0, 0xfffa, 0x0124},
2980 {0, 0xfff9, 0x0124},
2981 {0, 0x0086, 0x0127},
2982 {0, 0xfff8, 0x0124},
2983 {0, 0xfffd, 0x0124},
2984 {0, 0x0038, 0x0127},
2985 {0, 0xfff8, 0x0124},
2986 {0, 0xfffd, 0x0124},
2987 {0, 0x0003, 0x0127},
2988 {0, 0xfff8, 0x0124},
2989 {0, 0xfffd, 0x0124},
2990 {0, 0x0014, 0x0127},
2991 {0, 0xfff8, 0x0124},
2992 {0, 0xfffd, 0x0124},
2993 {0, 0xfffa, 0x0124},
2994 {0, 0xfff9, 0x0124},
2995 {0, 0x0086, 0x0127},
2996 {0, 0xfff8, 0x0124},
2997 {0, 0xfffd, 0x0124},
2998 {0, 0x0037, 0x0127},
2999 {0, 0xfff8, 0x0124},
3000 {0, 0xfffd, 0x0124},
3001 {0, 0x0001, 0x0127},
3002 {0, 0xfff8, 0x0124},
3003 {0, 0xfffd, 0x0124},
3004 {0, 0x0040, 0x0127},
3005 {0, 0xfff8, 0x0124},
3006 {0, 0xfffd, 0x0124},
3007 {0, 0xfffa, 0x0124},
3008 {0, 0xfff9, 0x0124},
3009 {0, 0x0086, 0x0127},
3010 {0, 0xfff8, 0x0124},
3011 {0, 0xfffd, 0x0124},
3012 {0, 0x0038, 0x0127},
3013 {0, 0xfff8, 0x0124},
3014 {0, 0xfffd, 0x0124},
3015 {0, 0x0000, 0x0127},
3016 {0, 0xfff8, 0x0124},
3017 {0, 0xfffd, 0x0124},
3018 {0, 0x0040, 0x0127},
3019 {0, 0xfff8, 0x0124},
3020 {0, 0xfffd, 0x0124},
3021 {0, 0xfffa, 0x0124},
3022 {0, 0xfff9, 0x0124},
3023 {0, 0x0086, 0x0127},
3024 {0, 0xfff8, 0x0124},
3025 {0, 0xfffd, 0x0124},
3026 {0, 0x0037, 0x0127},
3027 {0, 0xfff8, 0x0124},
3028 {0, 0xfffd, 0x0124},
3029 {0, 0x0001, 0x0127},
3030 {0, 0xfff8, 0x0124},
3031 {0, 0xfffd, 0x0124},
3032 {0, 0x0053, 0x0127},
3033 {0, 0xfff8, 0x0124},
3034 {0, 0xfffd, 0x0124},
3035 {0, 0xfffa, 0x0124},
3036 {0, 0xfff9, 0x0124},
3037 {0, 0x0086, 0x0127},
3038 {0, 0xfff8, 0x0124},
3039 {0, 0xfffd, 0x0124},
3040 {0, 0x0038, 0x0127},
3041 {0, 0xfff8, 0x0124},
3042 {0, 0xfffd, 0x0124},
3043 {0, 0x0000, 0x0127},
3044 {0, 0xfff8, 0x0124},
3045 {0, 0xfffd, 0x0124},
3046 {0, 0x0038, 0x0127},
3047 {0, 0xfff8, 0x0124},
3048 {0, 0xfffd, 0x0124},
3049 {0, 0xfffa, 0x0124},
3050 {0, 0x0000, 0x0101},
3051 {0, 0x00a0, 0x0103},
3052 {0, 0x0078, 0x0105},
3053 {0, 0x0000, 0x010a},
3054 {0, 0x0024, 0x010b},
3055 {0, 0x0028, 0x0119},
3056 {0, 0x0088, 0x011b},
3057 {0, 0x0002, 0x011d},
3058 {0, 0x0003, 0x011e},
3059 {0, 0x0000, 0x0129},
3060 {0, 0x00fc, 0x012b},
3061 {0, 0x0008, 0x0102},
3062 {0, 0x0000, 0x0104},
3063 {0, 0x0008, 0x011a},
3064 {0, 0x0028, 0x011c},
3065 {0, 0x0021, 0x012a},
3066 {0, 0x0000, 0x0118},
3067 {0, 0x0000, 0x0132},
3068 {0, 0x0000, 0x0109},
3069 {0, 0xfff9, 0x0124},
3070 {0, 0x0086, 0x0127},
3071 {0, 0xfff8, 0x0124},
3072 {0, 0xfffd, 0x0124},
3073 {0, 0x0037, 0x0127},
3074 {0, 0xfff8, 0x0124},
3075 {0, 0xfffd, 0x0124},
3076 {0, 0x0001, 0x0127},
3077 {0, 0xfff8, 0x0124},
3078 {0, 0xfffd, 0x0124},
3079 {0, 0x0031, 0x0127},
3080 {0, 0xfff8, 0x0124},
3081 {0, 0xfffd, 0x0124},
3082 {0, 0xfffa, 0x0124},
3083 {0, 0xfff9, 0x0124},
3084 {0, 0x0086, 0x0127},
3085 {0, 0xfff8, 0x0124},
3086 {0, 0xfffd, 0x0124},
3087 {0, 0x0038, 0x0127},
3088 {0, 0xfff8, 0x0124},
3089 {0, 0xfffd, 0x0124},
3090 {0, 0x0000, 0x0127},
3091 {0, 0xfff8, 0x0124},
3092 {0, 0xfffd, 0x0124},
3093 {0, 0x0000, 0x0127},
3094 {0, 0xfff8, 0x0124},
3095 {0, 0xfffd, 0x0124},
3096 {0, 0xfffa, 0x0124},
3097 {0, 0xfff9, 0x0124},
3098 {0, 0x0086, 0x0127},
3099 {0, 0xfff8, 0x0124},
3100 {0, 0xfffd, 0x0124},
3101 {0, 0x0037, 0x0127},
3102 {0, 0xfff8, 0x0124},
3103 {0, 0xfffd, 0x0124},
3104 {0, 0x0001, 0x0127},
3105 {0, 0xfff8, 0x0124},
3106 {0, 0xfffd, 0x0124},
3107 {0, 0x0040, 0x0127},
3108 {0, 0xfff8, 0x0124},
3109 {0, 0xfffd, 0x0124},
3110 {0, 0xfffa, 0x0124},
3111 {0, 0xfff9, 0x0124},
3112 {0, 0x0086, 0x0127},
3113 {0, 0xfff8, 0x0124},
3114 {0, 0xfffd, 0x0124},
3115 {0, 0x0038, 0x0127},
3116 {0, 0xfff8, 0x0124},
3117 {0, 0xfffd, 0x0124},
3118 {0, 0x0000, 0x0127},
3119 {0, 0xfff8, 0x0124},
3120 {0, 0xfffd, 0x0124},
3121 {0, 0x0040, 0x0127},
3122 {0, 0xfff8, 0x0124},
3123 {0, 0xfffd, 0x0124},
3124 {0, 0xfffa, 0x0124},
3125 {0, 0xfff9, 0x0124},
3126 {0, 0x0086, 0x0127},
3127 {0, 0xfff8, 0x0124},
3128 {0, 0xfffd, 0x0124},
3129 {0, 0x0037, 0x0127},
3130 {0, 0xfff8, 0x0124},
3131 {0, 0xfffd, 0x0124},
3132 {0, 0x0000, 0x0127},
3133 {0, 0xfff8, 0x0124},
3134 {0, 0xfffd, 0x0124},
3135 {0, 0x00dc, 0x0127},
3136 {0, 0xfff8, 0x0124},
3137 {0, 0xfffd, 0x0124},
3138 {0, 0xfffa, 0x0124},
3139 {0, 0xfff9, 0x0124},
3140 {0, 0x0086, 0x0127},
3141 {0, 0xfff8, 0x0124},
3142 {0, 0xfffd, 0x0124},
3143 {0, 0x0038, 0x0127},
3144 {0, 0xfff8, 0x0124},
3145 {0, 0xfffd, 0x0124},
3146 {0, 0x0000, 0x0127},
3147 {0, 0xfff8, 0x0124},
3148 {0, 0xfffd, 0x0124},
3149 {0, 0x0000, 0x0127},
3150 {0, 0xfff8, 0x0124},
3151 {0, 0xfffd, 0x0124},
3152 {0, 0xfffa, 0x0124},
3153 {0, 0xfff9, 0x0124},
3154 {0, 0x0086, 0x0127},
3155 {0, 0xfff8, 0x0124},
3156 {0, 0xfffd, 0x0124},
3157 {0, 0x0037, 0x0127},
3158 {0, 0xfff8, 0x0124},
3159 {0, 0xfffd, 0x0124},
3160 {0, 0x0001, 0x0127},
3161 {0, 0xfff8, 0x0124},
3162 {0, 0xfffd, 0x0124},
3163 {0, 0x0032, 0x0127},
3164 {0, 0xfff8, 0x0124},
3165 {0, 0xfffd, 0x0124},
3166 {0, 0xfffa, 0x0124},
3167 {0, 0xfff9, 0x0124},
3168 {0, 0x0086, 0x0127},
3169 {0, 0xfff8, 0x0124},
3170 {0, 0xfffd, 0x0124},
3171 {0, 0x0038, 0x0127},
3172 {0, 0xfff8, 0x0124},
3173 {0, 0xfffd, 0x0124},
3174 {0, 0x0001, 0x0127},
3175 {0, 0xfff8, 0x0124},
3176 {0, 0xfffd, 0x0124},
3177 {0, 0x0020, 0x0127},
3178 {0, 0xfff8, 0x0124},
3179 {0, 0xfffd, 0x0124},
3180 {0, 0xfffa, 0x0124},
3181 {0, 0xfff9, 0x0124},
3182 {0, 0x0086, 0x0127},
3183 {0, 0xfff8, 0x0124},
3184 {0, 0xfffd, 0x0124},
3185 {0, 0x0037, 0x0127},
3186 {0, 0xfff8, 0x0124},
3187 {0, 0xfffd, 0x0124},
3188 {0, 0x0001, 0x0127},
3189 {0, 0xfff8, 0x0124},
3190 {0, 0xfffd, 0x0124},
3191 {0, 0x0040, 0x0127},
3192 {0, 0xfff8, 0x0124},
3193 {0, 0xfffd, 0x0124},
3194 {0, 0xfffa, 0x0124},
3195 {0, 0xfff9, 0x0124},
3196 {0, 0x0086, 0x0127},
3197 {0, 0xfff8, 0x0124},
3198 {0, 0xfffd, 0x0124},
3199 {0, 0x0038, 0x0127},
3200 {0, 0xfff8, 0x0124},
3201 {0, 0xfffd, 0x0124},
3202 {0, 0x0000, 0x0127},
3203 {0, 0xfff8, 0x0124},
3204 {0, 0xfffd, 0x0124},
3205 {0, 0x0040, 0x0127},
3206 {0, 0xfff8, 0x0124},
3207 {0, 0xfffd, 0x0124},
3208 {0, 0xfffa, 0x0124},
3209 {0, 0xfff9, 0x0124},
3210 {0, 0x0086, 0x0127},
3211 {0, 0xfff8, 0x0124},
3212 {0, 0xfffd, 0x0124},
3213 {0, 0x0037, 0x0127},
3214 {0, 0xfff8, 0x0124},
3215 {0, 0xfffd, 0x0124},
3216 {0, 0x0000, 0x0127},
3217 {0, 0xfff8, 0x0124},
3218 {0, 0xfffd, 0x0124},
3219 {0, 0x0030, 0x0127},
3220 {0, 0xfff8, 0x0124},
3221 {0, 0xfffd, 0x0124},
3222 {0, 0xfffa, 0x0124},
3223 {0, 0xfff9, 0x0124},
3224 {0, 0x0086, 0x0127},
3225 {0, 0xfff8, 0x0124},
3226 {0, 0xfffd, 0x0124},
3227 {0, 0x0038, 0x0127},
3228 {0, 0xfff8, 0x0124},
3229 {0, 0xfffd, 0x0124},
3230 {0, 0x0008, 0x0127},
3231 {0, 0xfff8, 0x0124},
3232 {0, 0xfffd, 0x0124},
3233 {0, 0x0000, 0x0127},
3234 {0, 0xfff8, 0x0124},
3235 {0, 0xfffd, 0x0124},
3236 {0, 0xfffa, 0x0124},
3237 {0, 0x0003, 0x0106},
3238 {0, 0x0062, 0x0107},
3239 {0, 0x0003, 0x0111},
3240 };
3241#define NUM_INIT_DATA
3242
3243 unsigned short compression = 0; /* 0=none, 7=best frame rate */
3244 int f_rate; /* 0=Fastest 7=slowest */
3245
3246 if (IBMCAM_T(uvd)->initialized)
3247 return;
3248
3249 /* Internal frame rate is controlled by f_rate value */
3250 f_rate = 7 - framerate;
3251 RESTRICT_TO_RANGE(f_rate, 0, 7);
3252
3253 ibmcam_veio(uvd, 0, 0x0000, 0x0100);
3254 ibmcam_veio(uvd, 1, 0x0000, 0x0116);
3255 ibmcam_veio(uvd, 0, 0x0060, 0x0116);
3256 ibmcam_veio(uvd, 0, 0x0002, 0x0112);
3257 ibmcam_veio(uvd, 0, 0x0000, 0x0123);
3258 ibmcam_veio(uvd, 0, 0x0001, 0x0117);
3259 ibmcam_veio(uvd, 0, 0x0040, 0x0108);
3260 ibmcam_veio(uvd, 0, 0x0019, 0x012c);
3261 ibmcam_veio(uvd, 0, 0x0060, 0x0116);
3262 ibmcam_veio(uvd, 0, 0x0002, 0x0115);
3263 ibmcam_veio(uvd, 0, 0x0003, 0x0115);
3264 ibmcam_veio(uvd, 1, 0x0000, 0x0115);
3265 ibmcam_veio(uvd, 0, 0x000b, 0x0115);
3266 ibmcam_model3_Packet1(uvd, 0x000a, 0x0040);
3267 ibmcam_model3_Packet1(uvd, 0x000b, 0x00f6);
3268 ibmcam_model3_Packet1(uvd, 0x000c, 0x0002);
3269 ibmcam_model3_Packet1(uvd, 0x000d, 0x0020);
3270 ibmcam_model3_Packet1(uvd, 0x000e, 0x0033);
3271 ibmcam_model3_Packet1(uvd, 0x000f, 0x0007);
3272 ibmcam_model3_Packet1(uvd, 0x0010, 0x0000);
3273 ibmcam_model3_Packet1(uvd, 0x0011, 0x0070);
3274 ibmcam_model3_Packet1(uvd, 0x0012, 0x0030);
3275 ibmcam_model3_Packet1(uvd, 0x0013, 0x0000);
3276 ibmcam_model3_Packet1(uvd, 0x0014, 0x0001);
3277 ibmcam_model3_Packet1(uvd, 0x0015, 0x0001);
3278 ibmcam_model3_Packet1(uvd, 0x0016, 0x0001);
3279 ibmcam_model3_Packet1(uvd, 0x0017, 0x0001);
3280 ibmcam_model3_Packet1(uvd, 0x0018, 0x0000);
3281 ibmcam_model3_Packet1(uvd, 0x001e, 0x00c3);
3282 ibmcam_model3_Packet1(uvd, 0x0020, 0x0000);
3283 ibmcam_model3_Packet1(uvd, 0x0028, 0x0010);
3284 ibmcam_model3_Packet1(uvd, 0x0029, 0x0054);
3285 ibmcam_model3_Packet1(uvd, 0x002a, 0x0013);
3286 ibmcam_model3_Packet1(uvd, 0x002b, 0x0007);
3287 ibmcam_model3_Packet1(uvd, 0x002d, 0x0028);
3288 ibmcam_model3_Packet1(uvd, 0x002e, 0x0000);
3289 ibmcam_model3_Packet1(uvd, 0x0031, 0x0000);
3290 ibmcam_model3_Packet1(uvd, 0x0032, 0x0000);
3291 ibmcam_model3_Packet1(uvd, 0x0033, 0x0000);
3292 ibmcam_model3_Packet1(uvd, 0x0034, 0x0000);
3293 ibmcam_model3_Packet1(uvd, 0x0035, 0x0038);
3294 ibmcam_model3_Packet1(uvd, 0x003a, 0x0001);
3295 ibmcam_model3_Packet1(uvd, 0x003c, 0x001e);
3296 ibmcam_model3_Packet1(uvd, 0x003f, 0x000a);
3297 ibmcam_model3_Packet1(uvd, 0x0041, 0x0000);
3298 ibmcam_model3_Packet1(uvd, 0x0046, 0x003f);
3299 ibmcam_model3_Packet1(uvd, 0x0047, 0x0000);
3300 ibmcam_model3_Packet1(uvd, 0x0050, 0x0005);
3301 ibmcam_model3_Packet1(uvd, 0x0052, 0x001a);
3302 ibmcam_model3_Packet1(uvd, 0x0053, 0x0003);
3303 ibmcam_model3_Packet1(uvd, 0x005a, 0x006b);
3304 ibmcam_model3_Packet1(uvd, 0x005d, 0x001e);
3305 ibmcam_model3_Packet1(uvd, 0x005e, 0x0030);
3306 ibmcam_model3_Packet1(uvd, 0x005f, 0x0041);
3307 ibmcam_model3_Packet1(uvd, 0x0064, 0x0008);
3308 ibmcam_model3_Packet1(uvd, 0x0065, 0x0015);
3309 ibmcam_model3_Packet1(uvd, 0x0068, 0x000f);
3310 ibmcam_model3_Packet1(uvd, 0x0079, 0x0000);
3311 ibmcam_model3_Packet1(uvd, 0x007a, 0x0000);
3312 ibmcam_model3_Packet1(uvd, 0x007c, 0x003f);
3313 ibmcam_model3_Packet1(uvd, 0x0082, 0x000f);
3314 ibmcam_model3_Packet1(uvd, 0x0085, 0x0000);
3315 ibmcam_model3_Packet1(uvd, 0x0099, 0x0000);
3316 ibmcam_model3_Packet1(uvd, 0x009b, 0x0023);
3317 ibmcam_model3_Packet1(uvd, 0x009c, 0x0022);
3318 ibmcam_model3_Packet1(uvd, 0x009d, 0x0096);
3319 ibmcam_model3_Packet1(uvd, 0x009e, 0x0096);
3320 ibmcam_model3_Packet1(uvd, 0x009f, 0x000a);
3321
3322 switch (uvd->videosize) {
3323 case VIDEOSIZE_160x120:
3324 ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
3325 ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
3326 ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
3327 ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
3328 ibmcam_veio(uvd, 0, 0x0024, 0x010b); /* Differs everywhere */
3329 ibmcam_veio(uvd, 0, 0x00a9, 0x0119);
3330 ibmcam_veio(uvd, 0, 0x0016, 0x011b);
3331 ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same on 176x144, 320x240 */
3332 ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
3333 ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
3334 ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
3335 ibmcam_veio(uvd, 0, 0x0018, 0x0102);
3336 ibmcam_veio(uvd, 0, 0x0004, 0x0104);
3337 ibmcam_veio(uvd, 0, 0x0004, 0x011a);
3338 ibmcam_veio(uvd, 0, 0x0028, 0x011c);
3339 ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
3340 ibmcam_veio(uvd, 0, 0x0000, 0x0118);
3341 ibmcam_veio(uvd, 0, 0x0000, 0x0132);
3342 ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
3343 ibmcam_veio(uvd, 0, compression, 0x0109);
3344 break;
3345 case VIDEOSIZE_320x240:
3346 ibmcam_veio(uvd, 0, 0x0000, 0x0101); /* Same on 176x144, 320x240 */
3347 ibmcam_veio(uvd, 0, 0x00a0, 0x0103); /* Same on 176x144, 320x240 */
3348 ibmcam_veio(uvd, 0, 0x0078, 0x0105); /* Same on 176x144, 320x240 */
3349 ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
3350 ibmcam_veio(uvd, 0, 0x0028, 0x010b); /* Differs everywhere */
3351 ibmcam_veio(uvd, 0, 0x0002, 0x011d); /* Same */
3352 ibmcam_veio(uvd, 0, 0x0000, 0x011e);
3353 ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
3354 ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
3355 /* 4 commands from 160x120 skipped */
3356 ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
3357 ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
3358 ibmcam_veio(uvd, 0, compression, 0x0109);
3359 ibmcam_veio(uvd, 0, 0x00d9, 0x0119);
3360 ibmcam_veio(uvd, 0, 0x0006, 0x011b);
3361 ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
3362 ibmcam_veio(uvd, 0, 0x0010, 0x0104);
3363 ibmcam_veio(uvd, 0, 0x0004, 0x011a);
3364 ibmcam_veio(uvd, 0, 0x003f, 0x011c);
3365 ibmcam_veio(uvd, 0, 0x001c, 0x0118);
3366 ibmcam_veio(uvd, 0, 0x0000, 0x0132);
3367 break;
3368 case VIDEOSIZE_640x480:
3369 ibmcam_veio(uvd, 0, 0x00f0, 0x0105);
3370 ibmcam_veio(uvd, 0, 0x0000, 0x010a); /* Same */
3371 ibmcam_veio(uvd, 0, 0x0038, 0x010b); /* Differs everywhere */
3372 ibmcam_veio(uvd, 0, 0x00d9, 0x0119); /* Same on 320x240, 640x480 */
3373 ibmcam_veio(uvd, 0, 0x0006, 0x011b); /* Same on 320x240, 640x480 */
3374 ibmcam_veio(uvd, 0, 0x0004, 0x011d); /* NC */
3375 ibmcam_veio(uvd, 0, 0x0003, 0x011e); /* Same on 176x144, 640x480 */
3376 ibmcam_veio(uvd, 0, 0x0000, 0x0129); /* Same */
3377 ibmcam_veio(uvd, 0, 0x00fc, 0x012b); /* Same */
3378 ibmcam_veio(uvd, 0, 0x0021, 0x0102); /* Same on 320x240, 640x480 */
3379 ibmcam_veio(uvd, 0, 0x0016, 0x0104); /* NC */
3380 ibmcam_veio(uvd, 0, 0x0004, 0x011a); /* Same on 320x240, 640x480 */
3381 ibmcam_veio(uvd, 0, 0x003f, 0x011c); /* Same on 320x240, 640x480 */
3382 ibmcam_veio(uvd, 0, 0x0022, 0x012a); /* Same */
3383 ibmcam_veio(uvd, 0, 0x001c, 0x0118); /* Same on 320x240, 640x480 */
3384 ibmcam_model3_Packet1(uvd, 0x0021, 0x0001); /* Same */
3385 ibmcam_veio(uvd, 0, compression, 0x0109);
3386 ibmcam_veio(uvd, 0, 0x0040, 0x0101);
3387 ibmcam_veio(uvd, 0, 0x0040, 0x0103);
3388 ibmcam_veio(uvd, 0, 0x0000, 0x0132); /* Same on 320x240, 640x480 */
3389 break;
3390 }
3391 ibmcam_model3_Packet1(uvd, 0x007e, 0x000e); /* Hue */
3392 ibmcam_model3_Packet1(uvd, 0x0036, 0x0011); /* Brightness */
3393 ibmcam_model3_Packet1(uvd, 0x0060, 0x0002); /* Sharpness */
3394 ibmcam_model3_Packet1(uvd, 0x0061, 0x0004); /* Sharpness */
3395 ibmcam_model3_Packet1(uvd, 0x0062, 0x0005); /* Sharpness */
3396 ibmcam_model3_Packet1(uvd, 0x0063, 0x0014); /* Sharpness */
3397 ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */
3398 ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */
3399 ibmcam_model3_Packet1(uvd, 0x0067, 0x0001); /* Contrast */
3400 ibmcam_model3_Packet1(uvd, 0x005b, 0x000c); /* Contrast */
3401 ibmcam_model3_Packet1(uvd, 0x005c, 0x0016); /* Contrast */
3402 ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
3403 ibmcam_model3_Packet1(uvd, 0x002c, 0x0003); /* Was 1, broke 640x480 */
3404 ibmcam_model3_Packet1(uvd, 0x002f, 0x002a);
3405 ibmcam_model3_Packet1(uvd, 0x0030, 0x0029);
3406 ibmcam_model3_Packet1(uvd, 0x0037, 0x0002);
3407 ibmcam_model3_Packet1(uvd, 0x0038, 0x0059);
3408 ibmcam_model3_Packet1(uvd, 0x003d, 0x002e);
3409 ibmcam_model3_Packet1(uvd, 0x003e, 0x0028);
3410 ibmcam_model3_Packet1(uvd, 0x0078, 0x0005);
3411 ibmcam_model3_Packet1(uvd, 0x007b, 0x0011);
3412 ibmcam_model3_Packet1(uvd, 0x007d, 0x004b);
3413 ibmcam_model3_Packet1(uvd, 0x007f, 0x0022);
3414 ibmcam_model3_Packet1(uvd, 0x0080, 0x000c);
3415 ibmcam_model3_Packet1(uvd, 0x0081, 0x000b);
3416 ibmcam_model3_Packet1(uvd, 0x0083, 0x00fd);
3417 ibmcam_model3_Packet1(uvd, 0x0086, 0x000b);
3418 ibmcam_model3_Packet1(uvd, 0x0087, 0x000b);
3419 ibmcam_model3_Packet1(uvd, 0x007e, 0x000e);
3420 ibmcam_model3_Packet1(uvd, 0x0096, 0x00a0); /* Red gain */
3421 ibmcam_model3_Packet1(uvd, 0x0097, 0x0096); /* Blue gain */
3422 ibmcam_model3_Packet1(uvd, 0x0098, 0x000b);
3423
3424 switch (uvd->videosize) {
3425 case VIDEOSIZE_160x120:
3426 ibmcam_veio(uvd, 0, 0x0002, 0x0106);
3427 ibmcam_veio(uvd, 0, 0x0008, 0x0107);
3428 ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */
3429 ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
3430 ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
3431 ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
3432 ibmcam_model3_Packet1(uvd, 0x0040, 0x000a);
3433 ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
3434 break;
3435 case VIDEOSIZE_320x240:
3436 ibmcam_veio(uvd, 0, 0x0003, 0x0106);
3437 ibmcam_veio(uvd, 0, 0x0062, 0x0107);
3438 ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */
3439 ibmcam_model3_Packet1(uvd, 0x001f, 0x0000); /* Same */
3440 ibmcam_model3_Packet1(uvd, 0x0039, 0x001f); /* Same */
3441 ibmcam_model3_Packet1(uvd, 0x003b, 0x003c); /* Same */
3442 ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
3443 ibmcam_model3_Packet1(uvd, 0x0051, 0x000b);
3444 break;
3445 case VIDEOSIZE_640x480:
3446 ibmcam_veio(uvd, 0, 0x0002, 0x0106); /* Adjustments */
3447 ibmcam_veio(uvd, 0, 0x00b4, 0x0107); /* Adjustments */
3448 ibmcam_veio(uvd, 0, f_rate, 0x0111); /* Frame rate */
3449 ibmcam_model3_Packet1(uvd, 0x001f, 0x0002); /* !Same */
3450 ibmcam_model3_Packet1(uvd, 0x0039, 0x003e); /* !Same */
3451 ibmcam_model3_Packet1(uvd, 0x0040, 0x0008);
3452 ibmcam_model3_Packet1(uvd, 0x0051, 0x000a);
3453 break;
3454 }
3455
3456 /* 01.01.08 - Added for RCA video in support -LO */
3457 if(init_model3_input) {
3458 if (debug > 0)
3459 info("Setting input to RCA.");
3460 for (i=0; i < ARRAY_SIZE(initData); i++) {
3461 ibmcam_veio(uvd, initData[i].req, initData[i].value, initData[i].index);
3462 }
3463 }
3464
3465 ibmcam_veio(uvd, 0, 0x0001, 0x0114);
3466 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
3467 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
3468}
3469
3470/*
3471 * ibmcam_video_stop()
3472 *
3473 * This code tells camera to stop streaming. The interface remains
3474 * configured and bandwidth - claimed.
3475 */
3476static void ibmcam_video_stop(struct uvd *uvd)
3477{
3478 switch (IBMCAM_T(uvd)->camera_model) {
3479 case IBMCAM_MODEL_1:
3480 ibmcam_veio(uvd, 0, 0x00, 0x010c);
3481 ibmcam_veio(uvd, 0, 0x00, 0x010c);
3482 ibmcam_veio(uvd, 0, 0x01, 0x0114);
3483 ibmcam_veio(uvd, 0, 0xc0, 0x010c);
3484 ibmcam_veio(uvd, 0, 0x00, 0x010c);
3485 ibmcam_send_FF_04_02(uvd);
3486 ibmcam_veio(uvd, 1, 0x00, 0x0100);
3487 ibmcam_veio(uvd, 0, 0x81, 0x0100); /* LED Off */
3488 break;
3489 case IBMCAM_MODEL_2:
3490case IBMCAM_MODEL_4:
3491 ibmcam_veio(uvd, 0, 0x0000, 0x010c); /* Stop the camera */
3492
3493 ibmcam_model2_Packet1(uvd, 0x0030, 0x0004);
3494
3495 ibmcam_veio(uvd, 0, 0x0080, 0x0100); /* LED Off */
3496 ibmcam_veio(uvd, 0, 0x0020, 0x0111);
3497 ibmcam_veio(uvd, 0, 0x00a0, 0x0111);
3498
3499 ibmcam_model2_Packet1(uvd, 0x0030, 0x0002);
3500
3501 ibmcam_veio(uvd, 0, 0x0020, 0x0111);
3502 ibmcam_veio(uvd, 0, 0x0000, 0x0112);
3503 break;
3504 case IBMCAM_MODEL_3:
3505#if 1
3506 ibmcam_veio(uvd, 0, 0x0000, 0x010c);
3507
3508 /* Here we are supposed to select video interface alt. setting 0 */
3509 ibmcam_veio(uvd, 0, 0x0006, 0x012c);
3510
3511 ibmcam_model3_Packet1(uvd, 0x0046, 0x0000);
3512
3513 ibmcam_veio(uvd, 1, 0x0000, 0x0116);
3514 ibmcam_veio(uvd, 0, 0x0064, 0x0116);
3515 ibmcam_veio(uvd, 1, 0x0000, 0x0115);
3516 ibmcam_veio(uvd, 0, 0x0003, 0x0115);
3517 ibmcam_veio(uvd, 0, 0x0008, 0x0123);
3518 ibmcam_veio(uvd, 0, 0x0000, 0x0117);
3519 ibmcam_veio(uvd, 0, 0x0000, 0x0112);
3520 ibmcam_veio(uvd, 0, 0x0080, 0x0100);
3521 IBMCAM_T(uvd)->initialized = 0;
3522#endif
3523 break;
3524 } /* switch */
3525}
3526
3527/*
3528 * ibmcam_reinit_iso()
3529 *
3530 * This procedure sends couple of commands to the camera and then
3531 * resets the video pipe. This sequence was observed to reinit the
3532 * camera or, at least, to initiate ISO data stream.
3533 *
3534 * History:
3535 * 1/2/00 Created.
3536 */
3537static void ibmcam_reinit_iso(struct uvd *uvd, int do_stop)
3538{
3539 switch (IBMCAM_T(uvd)->camera_model) {
3540 case IBMCAM_MODEL_1:
3541 if (do_stop)
3542 ibmcam_video_stop(uvd);
3543 ibmcam_veio(uvd, 0, 0x0001, 0x0114);
3544 ibmcam_veio(uvd, 0, 0x00c0, 0x010c);
3545 usb_clear_halt(uvd->dev, usb_rcvisocpipe(uvd->dev, uvd->video_endp));
3546 ibmcam_model1_setup_after_video_if(uvd);
3547 break;
3548 case IBMCAM_MODEL_2:
3549 ibmcam_model2_setup_after_video_if(uvd);
3550 break;
3551 case IBMCAM_MODEL_3:
3552 ibmcam_video_stop(uvd);
3553 ibmcam_model3_setup_after_video_if(uvd);
3554 break;
3555 case IBMCAM_MODEL_4:
3556 ibmcam_model4_setup_after_video_if(uvd);
3557 break;
3558 }
3559}
3560
3561static void ibmcam_video_start(struct uvd *uvd)
3562{
3563 ibmcam_change_lighting_conditions(uvd);
3564 ibmcam_set_sharpness(uvd);
3565 ibmcam_reinit_iso(uvd, 0);
3566}
3567
3568/*
3569 * Return negative code on failure, 0 on success.
3570 */
3571static int ibmcam_setup_on_open(struct uvd *uvd)
3572{
3573 int setup_ok = 0; /* Success by default */
3574 /* Send init sequence only once, it's large! */
3575 if (!IBMCAM_T(uvd)->initialized) { /* FIXME rename */
3576 switch (IBMCAM_T(uvd)->camera_model) {
3577 case IBMCAM_MODEL_1:
3578 setup_ok = ibmcam_model1_setup(uvd);
3579 break;
3580 case IBMCAM_MODEL_2:
3581 setup_ok = ibmcam_model2_setup(uvd);
3582 break;
3583 case IBMCAM_MODEL_3:
3584 case IBMCAM_MODEL_4:
3585 /* We do all setup when Isoc stream is requested */
3586 break;
3587 }
3588 IBMCAM_T(uvd)->initialized = (setup_ok != 0);
3589 }
3590 return setup_ok;
3591}
3592
3593static void ibmcam_configure_video(struct uvd *uvd)
3594{
3595 if (uvd == NULL)
3596 return;
3597
3598 RESTRICT_TO_RANGE(init_brightness, 0, 255);
3599 RESTRICT_TO_RANGE(init_contrast, 0, 255);
3600 RESTRICT_TO_RANGE(init_color, 0, 255);
3601 RESTRICT_TO_RANGE(init_hue, 0, 255);
3602 RESTRICT_TO_RANGE(hue_correction, 0, 255);
3603
3604 memset(&uvd->vpic, 0, sizeof(uvd->vpic));
3605 memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
3606
3607 uvd->vpic.colour = init_color << 8;
3608 uvd->vpic.hue = init_hue << 8;
3609 uvd->vpic.brightness = init_brightness << 8;
3610 uvd->vpic.contrast = init_contrast << 8;
3611 uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
3612 uvd->vpic.depth = 24;
3613 uvd->vpic.palette = VIDEO_PALETTE_RGB24;
3614
3615 memset(&uvd->vcap, 0, sizeof(uvd->vcap));
3616 strcpy(uvd->vcap.name, "IBM USB Camera");
3617 uvd->vcap.type = VID_TYPE_CAPTURE;
3618 uvd->vcap.channels = 1;
3619 uvd->vcap.audios = 0;
3620 uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
3621 uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
3622 uvd->vcap.minwidth = min_canvasWidth;
3623 uvd->vcap.minheight = min_canvasHeight;
3624
3625 memset(&uvd->vchan, 0, sizeof(uvd->vchan));
3626 uvd->vchan.flags = 0;
3627 uvd->vchan.tuners = 0;
3628 uvd->vchan.channel = 0;
3629 uvd->vchan.type = VIDEO_TYPE_CAMERA;
3630 strcpy(uvd->vchan.name, "Camera");
3631}
3632
3633/*
3634 * ibmcam_probe()
3635 *
3636 * This procedure queries device descriptor and accepts the interface
3637 * if it looks like IBM C-it camera.
3638 *
3639 * History:
3640 * 22-Jan-2000 Moved camera init code to ibmcam_open()
3641 * 27=Jan-2000 Changed to use static structures, added locking.
3642 * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
3643 * 03-Jul-2000 Fixed endianness bug.
3644 * 12-Nov-2000 Reworked to comply with new probe() signature.
3645 * 23-Jan-2001 Added compatibility with 2.2.x kernels.
3646 */
3647static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *devid)
3648{
3649 struct usb_device *dev = interface_to_usbdev(intf);
3650 struct uvd *uvd = NULL;
3651 int ix, i, nas, model=0, canvasX=0, canvasY=0;
3652 int actInterface=-1, inactInterface=-1, maxPS=0;
3653 __u8 ifnum = intf->altsetting->desc.bInterfaceNumber;
3654 unsigned char video_ep = 0;
3655
3656 if (debug >= 1)
3657 info("ibmcam_probe(%p,%u.)", intf, ifnum);
3658
3659 /* We don't handle multi-config cameras */
3660 if (dev->descriptor.bNumConfigurations != 1)
3661 return -ENODEV;
3662
3663 /* Check the version/revision */
3664 switch (le16_to_cpu(dev->descriptor.bcdDevice)) {
3665 case 0x0002:
3666 if (ifnum != 2)
3667 return -ENODEV;
3668 model = IBMCAM_MODEL_1;
3669 break;
3670 case 0x030A:
3671 if (ifnum != 0)
3672 return -ENODEV;
3673 if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) ||
3674 (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID))
3675 model = IBMCAM_MODEL_4;
3676 else
3677 model = IBMCAM_MODEL_2;
3678 break;
3679 case 0x0301:
3680 if (ifnum != 0)
3681 return -ENODEV;
3682 model = IBMCAM_MODEL_3;
3683 break;
3684 default:
3685 err("IBM camera with revision 0x%04x is not supported.",
3686 le16_to_cpu(dev->descriptor.bcdDevice));
3687 return -ENODEV;
3688 }
3689
3690 /* Print detailed info on what we found so far */
3691 do {
3692 char *brand = NULL;
3693 switch (le16_to_cpu(dev->descriptor.idProduct)) {
3694 case NETCAM_PRODUCT_ID:
3695 brand = "IBM NetCamera";
3696 break;
3697 case VEO_800C_PRODUCT_ID:
3698 brand = "Veo Stingray [800C]";
3699 break;
3700 case VEO_800D_PRODUCT_ID:
3701 brand = "Veo Stingray [800D]";
3702 break;
3703 case IBMCAM_PRODUCT_ID:
3704 default:
3705 brand = "IBM PC Camera"; /* a.k.a. Xirlink C-It */
3706 break;
3707 }
3708 info("%s USB camera found (model %d, rev. 0x%04x)",
3709 brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
3710 } while (0);
3711
3712 /* Validate found interface: must have one ISO endpoint */
3713 nas = intf->num_altsetting;
3714 if (debug > 0)
3715 info("Number of alternate settings=%d.", nas);
3716 if (nas < 2) {
3717 err("Too few alternate settings for this camera!");
3718 return -ENODEV;
3719 }
3720 /* Validate all alternate settings */
3721 for (ix=0; ix < nas; ix++) {
3722 const struct usb_host_interface *interface;
3723 const struct usb_endpoint_descriptor *endpoint;
3724
3725 interface = &intf->altsetting[ix];
3726 i = interface->desc.bAlternateSetting;
3727 if (interface->desc.bNumEndpoints != 1) {
3728 err("Interface %d. has %u. endpoints!",
3729 ifnum, (unsigned)(interface->desc.bNumEndpoints));
3730 return -ENODEV;
3731 }
3732 endpoint = &interface->endpoint[0].desc;
3733 if (video_ep == 0)
3734 video_ep = endpoint->bEndpointAddress;
3735 else if (video_ep != endpoint->bEndpointAddress) {
3736 err("Alternate settings have different endpoint addresses!");
3737 return -ENODEV;
3738 }
3739 if ((endpoint->bmAttributes & 0x03) != 0x01) {
3740 err("Interface %d. has non-ISO endpoint!", ifnum);
3741 return -ENODEV;
3742 }
3743 if ((endpoint->bEndpointAddress & 0x80) == 0) {
3744 err("Interface %d. has ISO OUT endpoint!", ifnum);
3745 return -ENODEV;
3746 }
3747 if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
3748 if (inactInterface < 0)
3749 inactInterface = i;
3750 else {
3751 err("More than one inactive alt. setting!");
3752 return -ENODEV;
3753 }
3754 } else {
3755 if (actInterface < 0) {
3756 actInterface = i;
3757 maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
3758 if (debug > 0)
3759 info("Active setting=%d. maxPS=%d.", i, maxPS);
3760 } else
3761 err("More than one active alt. setting! Ignoring #%d.", i);
3762 }
3763 }
3764 if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
3765 err("Failed to recognize the camera!");
3766 return -ENODEV;
3767 }
3768
3769 /* Validate options */
3770 switch (model) {
3771 case IBMCAM_MODEL_1:
3772 RESTRICT_TO_RANGE(lighting, 0, 2);
3773 RESTRICT_TO_RANGE(size, SIZE_128x96, SIZE_352x288);
3774 if (framerate < 0)
3775 framerate = 2;
3776 canvasX = 352;
3777 canvasY = 288;
3778 break;
3779 case IBMCAM_MODEL_2:
3780 RESTRICT_TO_RANGE(lighting, 0, 15);
3781 RESTRICT_TO_RANGE(size, SIZE_176x144, SIZE_352x240);
3782 if (framerate < 0)
3783 framerate = 2;
3784 canvasX = 352;
3785 canvasY = 240;
3786 break;
3787 case IBMCAM_MODEL_3:
3788 RESTRICT_TO_RANGE(lighting, 0, 15); /* FIXME */
3789 switch (size) {
3790 case SIZE_160x120:
3791 canvasX = 160;
3792 canvasY = 120;
3793 if (framerate < 0)
3794 framerate = 2;
3795 RESTRICT_TO_RANGE(framerate, 0, 5);
3796 break;
3797 default:
3798 info("IBM camera: using 320x240");
3799 size = SIZE_320x240;
3800 /* No break here */
3801 case SIZE_320x240:
3802 canvasX = 320;
3803 canvasY = 240;
3804 if (framerate < 0)
3805 framerate = 3;
3806 RESTRICT_TO_RANGE(framerate, 0, 5);
3807 break;
3808 case SIZE_640x480:
3809 canvasX = 640;
3810 canvasY = 480;
3811 framerate = 0; /* Slowest, and maybe even that is too fast */
3812 break;
3813 }
3814 break;
3815 case IBMCAM_MODEL_4:
3816 RESTRICT_TO_RANGE(lighting, 0, 2);
3817 switch (size) {
3818 case SIZE_128x96:
3819 canvasX = 128;
3820 canvasY = 96;
3821 break;
3822 case SIZE_160x120:
3823 canvasX = 160;
3824 canvasY = 120;
3825 break;
3826 default:
3827 info("IBM NetCamera: using 176x144");
3828 size = SIZE_176x144;
3829 /* No break here */
3830 case SIZE_176x144:
3831 canvasX = 176;
3832 canvasY = 144;
3833 break;
3834 case SIZE_320x240:
3835 canvasX = 320;
3836 canvasY = 240;
3837 break;
3838 case SIZE_352x288:
3839 canvasX = 352;
3840 canvasY = 288;
3841 break;
3842 }
3843 break;
3844 default:
3845 err("IBM camera: Model %d. not supported!", model);
3846 return -ENODEV;
3847 }
3848
3849 uvd = usbvideo_AllocateDevice(cams);
3850 if (uvd != NULL) {
3851 /* Here uvd is a fully allocated uvd object */
3852 uvd->flags = flags;
3853 uvd->debug = debug;
3854 uvd->dev = dev;
3855 uvd->iface = ifnum;
3856 uvd->ifaceAltInactive = inactInterface;
3857 uvd->ifaceAltActive = actInterface;
3858 uvd->video_endp = video_ep;
3859 uvd->iso_packet_len = maxPS;
3860 uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
3861 uvd->defaultPalette = VIDEO_PALETTE_RGB24;
3862 uvd->canvas = VIDEOSIZE(canvasX, canvasY);
3863 uvd->videosize = ibmcam_size_to_videosize(size);
3864
3865 /* Initialize ibmcam-specific data */
3866 assert(IBMCAM_T(uvd) != NULL);
3867 IBMCAM_T(uvd)->camera_model = model;
3868 IBMCAM_T(uvd)->initialized = 0;
3869
3870 ibmcam_configure_video(uvd);
3871
3872 i = usbvideo_RegisterVideoDevice(uvd);
3873 if (i != 0) {
3874 err("usbvideo_RegisterVideoDevice() failed.");
3875 uvd = NULL;
3876 }
3877 }
3878 usb_set_intfdata (intf, uvd);
3879 return 0;
3880}
3881
3882
3883static struct usb_device_id id_table[] = {
3884 { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0002, 0x0002) }, /* Model 1 */
3885 { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */
3886 { USB_DEVICE_VER(IBMCAM_VENDOR_ID, IBMCAM_PRODUCT_ID, 0x0301, 0x0301) }, /* Model 3 */
3887 { USB_DEVICE_VER(IBMCAM_VENDOR_ID, NETCAM_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */
3888 { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800C_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 2 */
3889 { USB_DEVICE_VER(IBMCAM_VENDOR_ID, VEO_800D_PRODUCT_ID, 0x030a, 0x030a) }, /* Model 4 */
3890 { } /* Terminating entry */
3891};
3892
3893/*
3894 * ibmcam_init()
3895 *
3896 * This code is run to initialize the driver.
3897 *
3898 * History:
3899 * 1/27/00 Reworked to use statically allocated ibmcam structures.
3900 * 21/10/00 Completely redesigned to use usbvideo services.
3901 */
3902static int __init ibmcam_init(void)
3903{
3904 struct usbvideo_cb cbTbl;
3905 memset(&cbTbl, 0, sizeof(cbTbl));
3906 cbTbl.probe = ibmcam_probe;
3907 cbTbl.setupOnOpen = ibmcam_setup_on_open;
3908 cbTbl.videoStart = ibmcam_video_start;
3909 cbTbl.videoStop = ibmcam_video_stop;
3910 cbTbl.processData = ibmcam_ProcessIsocData;
3911 cbTbl.postProcess = usbvideo_DeinterlaceFrame;
3912 cbTbl.adjustPicture = ibmcam_adjust_picture;
3913 cbTbl.getFPS = ibmcam_calculate_fps;
3914 return usbvideo_register(
3915 &cams,
3916 MAX_IBMCAM,
3917 sizeof(ibmcam_t),
3918 "ibmcam",
3919 &cbTbl,
3920 THIS_MODULE,
3921 id_table);
3922}
3923
3924static void __exit ibmcam_cleanup(void)
3925{
3926 usbvideo_Deregister(&cams);
3927}
3928
3929MODULE_DEVICE_TABLE(usb, id_table);
3930
3931module_init(ibmcam_init);
3932module_exit(ibmcam_cleanup);
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
new file mode 100644
index 000000000000..e2ede583518f
--- /dev/null
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -0,0 +1,978 @@
1/*
2 * konicawc.c - konica webcam driver
3 *
4 * Author: Simon Evans <spse@secret.org.uk>
5 *
6 * Copyright (C) 2002 Simon Evans
7 *
8 * Licence: GPL
9 *
10 * Driver for USB webcams based on Konica chipset. This
11 * chipset is used in Intel YC76 camera.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/module.h>
17#include <linux/init.h>
18#include <linux/input.h>
19#include <linux/usb_input.h>
20
21#include "usbvideo.h"
22
23#define MAX_BRIGHTNESS 108
24#define MAX_CONTRAST 108
25#define MAX_SATURATION 108
26#define MAX_SHARPNESS 108
27#define MAX_WHITEBAL 372
28#define MAX_SPEED 6
29
30
31#define MAX_CAMERAS 1
32
33#define DRIVER_VERSION "v1.4"
34#define DRIVER_DESC "Konica Webcam driver"
35
36enum ctrl_req {
37 SetWhitebal = 0x01,
38 SetBrightness = 0x02,
39 SetSharpness = 0x03,
40 SetContrast = 0x04,
41 SetSaturation = 0x05,
42};
43
44
45enum frame_sizes {
46 SIZE_160X120 = 0,
47 SIZE_160X136 = 1,
48 SIZE_176X144 = 2,
49 SIZE_320X240 = 3,
50
51};
52
53#define MAX_FRAME_SIZE SIZE_320X240
54
55static struct usbvideo *cams;
56
57#ifdef CONFIG_USB_DEBUG
58static int debug;
59#define DEBUG(n, format, arg...) \
60 if (n <= debug) { \
61 printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
62 }
63#else
64#define DEBUG(n, arg...)
65static const int debug = 0;
66#endif
67
68
69/* Some default values for initial camera settings,
70 can be set by modprobe */
71
72static int size;
73static int speed = 6; /* Speed (fps) 0 (slowest) to 6 (fastest) */
74static int brightness = MAX_BRIGHTNESS/2;
75static int contrast = MAX_CONTRAST/2;
76static int saturation = MAX_SATURATION/2;
77static int sharpness = MAX_SHARPNESS/2;
78static int whitebal = 3*(MAX_WHITEBAL/4);
79
80static const int spd_to_iface[] = { 1, 0, 3, 2, 4, 5, 6 };
81
82/* These FPS speeds are from the windows config box. They are
83 * indexed on size (0-2) and speed (0-6). Divide by 3 to get the
84 * real fps.
85 */
86
87static const int spd_to_fps[][7] = { { 24, 40, 48, 60, 72, 80, 100 },
88 { 24, 40, 48, 60, 72, 80, 100 },
89 { 18, 30, 36, 45, 54, 60, 75 },
90 { 6, 10, 12, 15, 18, 21, 25 } };
91
92struct cam_size {
93 u16 width;
94 u16 height;
95 u8 cmd;
96};
97
98static const struct cam_size camera_sizes[] = { { 160, 120, 0x7 },
99 { 160, 136, 0xa },
100 { 176, 144, 0x4 },
101 { 320, 240, 0x5 } };
102
103struct konicawc {
104 u8 brightness; /* camera uses 0 - 9, x11 for real value */
105 u8 contrast; /* as above */
106 u8 saturation; /* as above */
107 u8 sharpness; /* as above */
108 u8 white_bal; /* 0 - 33, x11 for real value */
109 u8 speed; /* Stored as 0 - 6, used as index in spd_to_* (above) */
110 u8 size; /* Frame Size */
111 int height;
112 int width;
113 struct urb *sts_urb[USBVIDEO_NUMSBUF];
114 u8 sts_buf[USBVIDEO_NUMSBUF][FRAMES_PER_DESC];
115 struct urb *last_data_urb;
116 int lastframe;
117 int cur_frame_size; /* number of bytes in current frame size */
118 int maxline; /* number of lines per frame */
119 int yplanesz; /* Number of bytes in the Y plane */
120 unsigned int buttonsts:1;
121#ifdef CONFIG_INPUT
122 struct input_dev *input;
123 char input_physname[64];
124#endif
125};
126
127
128#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)
129#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)
130#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)
131
132
133static int konicawc_ctrl_msg(struct uvd *uvd, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
134{
135 int retval = usb_control_msg(uvd->dev,
136 dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
137 request, 0x40 | dir, value, index, buf, len, 1000);
138 return retval < 0 ? retval : 0;
139}
140
141
142static inline void konicawc_camera_on(struct uvd *uvd)
143{
144 DEBUG(0, "camera on");
145 konicawc_set_misc(uvd, 0x2, 1, 0x0b);
146}
147
148
149static inline void konicawc_camera_off(struct uvd *uvd)
150{
151 DEBUG(0, "camera off");
152 konicawc_set_misc(uvd, 0x2, 0, 0x0b);
153}
154
155
156static void konicawc_set_camera_size(struct uvd *uvd)
157{
158 struct konicawc *cam = (struct konicawc *)uvd->user_data;
159
160 konicawc_set_misc(uvd, 0x2, camera_sizes[cam->size].cmd, 0x08);
161 cam->width = camera_sizes[cam->size].width;
162 cam->height = camera_sizes[cam->size].height;
163 cam->yplanesz = cam->height * cam->width;
164 cam->cur_frame_size = (cam->yplanesz * 3) / 2;
165 cam->maxline = cam->yplanesz / 256;
166 uvd->videosize = VIDEOSIZE(cam->width, cam->height);
167}
168
169
170static int konicawc_setup_on_open(struct uvd *uvd)
171{
172 struct konicawc *cam = (struct konicawc *)uvd->user_data;
173
174 DEBUG(1, "setting brightness to %d (%d)", cam->brightness,
175 cam->brightness * 11);
176 konicawc_set_value(uvd, cam->brightness, SetBrightness);
177 DEBUG(1, "setting white balance to %d (%d)", cam->white_bal,
178 cam->white_bal * 11);
179 konicawc_set_value(uvd, cam->white_bal, SetWhitebal);
180 DEBUG(1, "setting contrast to %d (%d)", cam->contrast,
181 cam->contrast * 11);
182 konicawc_set_value(uvd, cam->contrast, SetContrast);
183 DEBUG(1, "setting saturation to %d (%d)", cam->saturation,
184 cam->saturation * 11);
185 konicawc_set_value(uvd, cam->saturation, SetSaturation);
186 DEBUG(1, "setting sharpness to %d (%d)", cam->sharpness,
187 cam->sharpness * 11);
188 konicawc_set_value(uvd, cam->sharpness, SetSharpness);
189 konicawc_set_camera_size(uvd);
190 cam->lastframe = -2;
191 cam->buttonsts = 0;
192 return 0;
193}
194
195
196static void konicawc_adjust_picture(struct uvd *uvd)
197{
198 struct konicawc *cam = (struct konicawc *)uvd->user_data;
199
200 konicawc_camera_off(uvd);
201 DEBUG(1, "new brightness: %d", uvd->vpic.brightness);
202 uvd->vpic.brightness = (uvd->vpic.brightness > MAX_BRIGHTNESS) ? MAX_BRIGHTNESS : uvd->vpic.brightness;
203 if(cam->brightness != uvd->vpic.brightness / 11) {
204 cam->brightness = uvd->vpic.brightness / 11;
205 DEBUG(1, "setting brightness to %d (%d)", cam->brightness,
206 cam->brightness * 11);
207 konicawc_set_value(uvd, cam->brightness, SetBrightness);
208 }
209
210 DEBUG(1, "new contrast: %d", uvd->vpic.contrast);
211 uvd->vpic.contrast = (uvd->vpic.contrast > MAX_CONTRAST) ? MAX_CONTRAST : uvd->vpic.contrast;
212 if(cam->contrast != uvd->vpic.contrast / 11) {
213 cam->contrast = uvd->vpic.contrast / 11;
214 DEBUG(1, "setting contrast to %d (%d)", cam->contrast,
215 cam->contrast * 11);
216 konicawc_set_value(uvd, cam->contrast, SetContrast);
217 }
218 konicawc_camera_on(uvd);
219}
220
221#ifdef CONFIG_INPUT
222
223static void konicawc_register_input(struct konicawc *cam, struct usb_device *dev)
224{
225 struct input_dev *input_dev;
226
227 usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
228 strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
229
230 cam->input = input_dev = input_allocate_device();
231 if (!input_dev) {
232 warn("Not enough memory for camera's input device\n");
233 return;
234 }
235
236 input_dev->name = "Konicawc snapshot button";
237 input_dev->phys = cam->input_physname;
238 usb_to_input_id(dev, &input_dev->id);
239 input_dev->cdev.dev = &dev->dev;
240
241 input_dev->evbit[0] = BIT(EV_KEY);
242 input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
243
244 input_dev->private = cam;
245
246 input_register_device(cam->input);
247}
248
249static void konicawc_unregister_input(struct konicawc *cam)
250{
251 if (cam->input) {
252 input_unregister_device(cam->input);
253 cam->input = NULL;
254 }
255}
256
257static void konicawc_report_buttonstat(struct konicawc *cam)
258{
259 if (cam->input) {
260 input_report_key(cam->input, BTN_0, cam->buttonsts);
261 input_sync(cam->input);
262 }
263}
264
265#else
266
267static inline void konicawc_register_input(struct konicawc *cam, struct usb_device *dev) { }
268static inline void konicawc_unregister_input(struct konicawc *cam) { }
269static inline void konicawc_report_buttonstat(struct konicawc *cam) { }
270
271#endif /* CONFIG_INPUT */
272
273static int konicawc_compress_iso(struct uvd *uvd, struct urb *dataurb, struct urb *stsurb)
274{
275 char *cdata;
276 int i, totlen = 0;
277 unsigned char *status = stsurb->transfer_buffer;
278 int keep = 0, discard = 0, bad = 0;
279 struct konicawc *cam = (struct konicawc *)uvd->user_data;
280
281 for (i = 0; i < dataurb->number_of_packets; i++) {
282 int button = cam->buttonsts;
283 unsigned char sts;
284 int n = dataurb->iso_frame_desc[i].actual_length;
285 int st = dataurb->iso_frame_desc[i].status;
286 cdata = dataurb->transfer_buffer +
287 dataurb->iso_frame_desc[i].offset;
288
289 /* Detect and ignore errored packets */
290 if (st < 0) {
291 DEBUG(1, "Data error: packet=%d. len=%d. status=%d.",
292 i, n, st);
293 uvd->stats.iso_err_count++;
294 continue;
295 }
296
297 /* Detect and ignore empty packets */
298 if (n <= 0) {
299 uvd->stats.iso_skip_count++;
300 continue;
301 }
302
303 /* See what the status data said about the packet */
304 sts = *(status+stsurb->iso_frame_desc[i].offset);
305
306 /* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
307 * otherwise:
308 * bit 0 0: keep packet
309 * 1: drop packet (padding data)
310 *
311 * bit 4 0 button not clicked
312 * 1 button clicked
313 * button is used to `take a picture' (in software)
314 */
315
316 if(sts < 0x80) {
317 button = !!(sts & 0x40);
318 sts &= ~0x40;
319 }
320
321 /* work out the button status, but don't do
322 anything with it for now */
323
324 if(button != cam->buttonsts) {
325 DEBUG(2, "button: %sclicked", button ? "" : "un");
326 cam->buttonsts = button;
327 konicawc_report_buttonstat(cam);
328 }
329
330 if(sts == 0x01) { /* drop frame */
331 discard++;
332 continue;
333 }
334
335 if((sts > 0x01) && (sts < 0x80)) {
336 info("unknown status %2.2x", sts);
337 bad++;
338 continue;
339 }
340 if(!sts && cam->lastframe == -2) {
341 DEBUG(2, "dropping frame looking for image start");
342 continue;
343 }
344
345 keep++;
346 if(sts & 0x80) { /* frame start */
347 unsigned char marker[] = { 0, 0xff, 0, 0x00 };
348
349 if(cam->lastframe == -2) {
350 DEBUG(2, "found initial image");
351 cam->lastframe = -1;
352 }
353
354 marker[3] = sts & 0x7F;
355 RingQueue_Enqueue(&uvd->dp, marker, 4);
356 totlen += 4;
357 }
358
359 totlen += n; /* Little local accounting */
360 RingQueue_Enqueue(&uvd->dp, cdata, n);
361 }
362 DEBUG(8, "finished: keep = %d discard = %d bad = %d added %d bytes",
363 keep, discard, bad, totlen);
364 return totlen;
365}
366
367
368static void resubmit_urb(struct uvd *uvd, struct urb *urb)
369{
370 int i, ret;
371 for (i = 0; i < FRAMES_PER_DESC; i++) {
372 urb->iso_frame_desc[i].status = 0;
373 }
374 urb->dev = uvd->dev;
375 urb->status = 0;
376 ret = usb_submit_urb(urb, GFP_ATOMIC);
377 DEBUG(3, "submitting urb of length %d", urb->transfer_buffer_length);
378 if(ret)
379 err("usb_submit_urb error (%d)", ret);
380
381}
382
383
384static void konicawc_isoc_irq(struct urb *urb, struct pt_regs *regs)
385{
386 struct uvd *uvd = urb->context;
387 struct konicawc *cam = (struct konicawc *)uvd->user_data;
388
389 /* We don't want to do anything if we are about to be removed! */
390 if (!CAMERA_IS_OPERATIONAL(uvd))
391 return;
392
393 if (!uvd->streaming) {
394 DEBUG(1, "Not streaming, but interrupt!");
395 return;
396 }
397
398 DEBUG(3, "got frame %d len = %d buflen =%d", urb->start_frame, urb->actual_length, urb->transfer_buffer_length);
399
400 uvd->stats.urb_count++;
401
402 if (urb->transfer_buffer_length > 32) {
403 cam->last_data_urb = urb;
404 return;
405 }
406 /* Copy the data received into ring queue */
407 if(cam->last_data_urb) {
408 int len = 0;
409 if(urb->start_frame != cam->last_data_urb->start_frame)
410 err("Lost sync on frames");
411 else if (!urb->status && !cam->last_data_urb->status)
412 len = konicawc_compress_iso(uvd, cam->last_data_urb, urb);
413
414 resubmit_urb(uvd, cam->last_data_urb);
415 resubmit_urb(uvd, urb);
416 cam->last_data_urb = NULL;
417 uvd->stats.urb_length = len;
418 uvd->stats.data_count += len;
419 if(len)
420 RingQueue_WakeUpInterruptible(&uvd->dp);
421 return;
422 }
423 return;
424}
425
426
427static int konicawc_start_data(struct uvd *uvd)
428{
429 struct usb_device *dev = uvd->dev;
430 int i, errFlag;
431 struct konicawc *cam = (struct konicawc *)uvd->user_data;
432 int pktsz;
433 struct usb_interface *intf;
434 struct usb_host_interface *interface = NULL;
435
436 intf = usb_ifnum_to_if(dev, uvd->iface);
437 if (intf)
438 interface = usb_altnum_to_altsetting(intf,
439 spd_to_iface[cam->speed]);
440 if (!interface)
441 return -ENXIO;
442 pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize);
443 DEBUG(1, "pktsz = %d", pktsz);
444 if (!CAMERA_IS_OPERATIONAL(uvd)) {
445 err("Camera is not operational");
446 return -EFAULT;
447 }
448 uvd->curframe = -1;
449 konicawc_camera_on(uvd);
450 /* Alternate interface 1 is is the biggest frame size */
451 i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
452 if (i < 0) {
453 err("usb_set_interface error");
454 uvd->last_error = i;
455 return -EBUSY;
456 }
457
458 /* We double buffer the Iso lists */
459 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
460 int j, k;
461 struct urb *urb = uvd->sbuf[i].urb;
462 urb->dev = dev;
463 urb->context = uvd;
464 urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
465 urb->interval = 1;
466 urb->transfer_flags = URB_ISO_ASAP;
467 urb->transfer_buffer = uvd->sbuf[i].data;
468 urb->complete = konicawc_isoc_irq;
469 urb->number_of_packets = FRAMES_PER_DESC;
470 urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
471 for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
472 urb->iso_frame_desc[j].offset = k;
473 urb->iso_frame_desc[j].length = pktsz;
474 }
475
476 urb = cam->sts_urb[i];
477 urb->dev = dev;
478 urb->context = uvd;
479 urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp-1);
480 urb->interval = 1;
481 urb->transfer_flags = URB_ISO_ASAP;
482 urb->transfer_buffer = cam->sts_buf[i];
483 urb->complete = konicawc_isoc_irq;
484 urb->number_of_packets = FRAMES_PER_DESC;
485 urb->transfer_buffer_length = FRAMES_PER_DESC;
486 for (j=0; j < FRAMES_PER_DESC; j++) {
487 urb->iso_frame_desc[j].offset = j;
488 urb->iso_frame_desc[j].length = 1;
489 }
490 }
491
492 cam->last_data_urb = NULL;
493
494 /* Submit all URBs */
495 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
496 errFlag = usb_submit_urb(cam->sts_urb[i], GFP_KERNEL);
497 if (errFlag)
498 err("usb_submit_isoc(%d) ret %d", i, errFlag);
499
500 errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
501 if (errFlag)
502 err ("usb_submit_isoc(%d) ret %d", i, errFlag);
503 }
504
505 uvd->streaming = 1;
506 DEBUG(1, "streaming=1 video_endp=$%02x", uvd->video_endp);
507 return 0;
508}
509
510
511static void konicawc_stop_data(struct uvd *uvd)
512{
513 int i, j;
514 struct konicawc *cam;
515
516 if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
517 return;
518
519 konicawc_camera_off(uvd);
520 uvd->streaming = 0;
521 cam = (struct konicawc *)uvd->user_data;
522 cam->last_data_urb = NULL;
523
524 /* Unschedule all of the iso td's */
525 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
526 usb_kill_urb(uvd->sbuf[i].urb);
527 usb_kill_urb(cam->sts_urb[i]);
528 }
529
530 if (!uvd->remove_pending) {
531 /* Set packet size to 0 */
532 j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
533 if (j < 0) {
534 err("usb_set_interface() error %d.", j);
535 uvd->last_error = j;
536 }
537 }
538}
539
540
541static void konicawc_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
542{
543 struct konicawc *cam = (struct konicawc *)uvd->user_data;
544 int maxline = cam->maxline;
545 int yplanesz = cam->yplanesz;
546
547 assert(frame != NULL);
548
549 DEBUG(5, "maxline = %d yplanesz = %d", maxline, yplanesz);
550 DEBUG(3, "Frame state = %d", frame->scanstate);
551
552 if(frame->scanstate == ScanState_Scanning) {
553 int drop = 0;
554 int curframe;
555 int fdrops = 0;
556 DEBUG(3, "Searching for marker, queue len = %d", RingQueue_GetLength(&uvd->dp));
557 while(RingQueue_GetLength(&uvd->dp) >= 4) {
558 if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
559 (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
560 (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
561 (RING_QUEUE_PEEK(&uvd->dp, 3) < 0x80)) {
562 curframe = RING_QUEUE_PEEK(&uvd->dp, 3);
563 if(cam->lastframe >= 0) {
564 fdrops = (0x80 + curframe - cam->lastframe) & 0x7F;
565 fdrops--;
566 if(fdrops) {
567 info("Dropped %d frames (%d -> %d)", fdrops,
568 cam->lastframe, curframe);
569 }
570 }
571 cam->lastframe = curframe;
572 frame->curline = 0;
573 frame->scanstate = ScanState_Lines;
574 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
575 break;
576 }
577 RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
578 drop++;
579 }
580 if(drop)
581 DEBUG(2, "dropped %d bytes looking for new frame", drop);
582 }
583
584 if(frame->scanstate == ScanState_Scanning)
585 return;
586
587 /* Try to move data from queue into frame buffer
588 * We get data in blocks of 384 bytes made up of:
589 * 256 Y, 64 U, 64 V.
590 * This needs to be written out as a Y plane, a U plane and a V plane.
591 */
592
593 while ( frame->curline < maxline && (RingQueue_GetLength(&uvd->dp) >= 384)) {
594 /* Y */
595 RingQueue_Dequeue(&uvd->dp, frame->data + (frame->curline * 256), 256);
596 /* U */
597 RingQueue_Dequeue(&uvd->dp, frame->data + yplanesz + (frame->curline * 64), 64);
598 /* V */
599 RingQueue_Dequeue(&uvd->dp, frame->data + (5 * yplanesz)/4 + (frame->curline * 64), 64);
600 frame->seqRead_Length += 384;
601 frame->curline++;
602 }
603 /* See if we filled the frame */
604 if (frame->curline == maxline) {
605 DEBUG(5, "got whole frame");
606
607 frame->frameState = FrameState_Done_Hold;
608 frame->curline = 0;
609 uvd->curframe = -1;
610 uvd->stats.frame_num++;
611 }
612}
613
614
615static int konicawc_find_fps(int size, int fps)
616{
617 int i;
618
619 fps *= 3;
620 DEBUG(1, "konica_find_fps: size = %d fps = %d", size, fps);
621 if(fps <= spd_to_fps[size][0])
622 return 0;
623
624 if(fps >= spd_to_fps[size][MAX_SPEED])
625 return MAX_SPEED;
626
627 for(i = 0; i < MAX_SPEED; i++) {
628 if((fps >= spd_to_fps[size][i]) && (fps <= spd_to_fps[size][i+1])) {
629 DEBUG(2, "fps %d between %d and %d", fps, i, i+1);
630 if( (fps - spd_to_fps[size][i]) < (spd_to_fps[size][i+1] - fps))
631 return i;
632 else
633 return i+1;
634 }
635 }
636 return MAX_SPEED+1;
637}
638
639
640static int konicawc_set_video_mode(struct uvd *uvd, struct video_window *vw)
641{
642 struct konicawc *cam = (struct konicawc *)uvd->user_data;
643 int newspeed = cam->speed;
644 int newsize;
645 int x = vw->width;
646 int y = vw->height;
647 int fps = vw->flags;
648
649 if(x > 0 && y > 0) {
650 DEBUG(2, "trying to find size %d,%d", x, y);
651 for(newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
652 if((camera_sizes[newsize].width == x) && (camera_sizes[newsize].height == y))
653 break;
654 }
655 } else {
656 newsize = cam->size;
657 }
658
659 if(newsize > MAX_FRAME_SIZE) {
660 DEBUG(1, "couldn't find size %d,%d", x, y);
661 return -EINVAL;
662 }
663
664 if(fps > 0) {
665 DEBUG(1, "trying to set fps to %d", fps);
666 newspeed = konicawc_find_fps(newsize, fps);
667 DEBUG(1, "find_fps returned %d (%d)", newspeed, spd_to_fps[newsize][newspeed]);
668 }
669
670 if(newspeed > MAX_SPEED)
671 return -EINVAL;
672
673 DEBUG(1, "setting size to %d speed to %d", newsize, newspeed);
674 if((newsize == cam->size) && (newspeed == cam->speed)) {
675 DEBUG(1, "Nothing to do");
676 return 0;
677 }
678 DEBUG(0, "setting to %dx%d @ %d fps", camera_sizes[newsize].width,
679 camera_sizes[newsize].height, spd_to_fps[newsize][newspeed]/3);
680
681 konicawc_stop_data(uvd);
682 uvd->ifaceAltActive = spd_to_iface[newspeed];
683 DEBUG(1, "new interface = %d", uvd->ifaceAltActive);
684 cam->speed = newspeed;
685
686 if(cam->size != newsize) {
687 cam->size = newsize;
688 konicawc_set_camera_size(uvd);
689 }
690
691 /* Flush the input queue and clear any current frame in progress */
692
693 RingQueue_Flush(&uvd->dp);
694 cam->lastframe = -2;
695 if(uvd->curframe != -1) {
696 uvd->frame[uvd->curframe].curline = 0;
697 uvd->frame[uvd->curframe].seqRead_Length = 0;
698 uvd->frame[uvd->curframe].seqRead_Index = 0;
699 }
700
701 konicawc_start_data(uvd);
702 return 0;
703}
704
705
706static int konicawc_calculate_fps(struct uvd *uvd)
707{
708 struct konicawc *cam = uvd->user_data;
709 return spd_to_fps[cam->size][cam->speed]/3;
710}
711
712
713static void konicawc_configure_video(struct uvd *uvd)
714{
715 struct konicawc *cam = (struct konicawc *)uvd->user_data;
716 u8 buf[2];
717
718 memset(&uvd->vpic, 0, sizeof(uvd->vpic));
719 memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
720
721 RESTRICT_TO_RANGE(brightness, 0, MAX_BRIGHTNESS);
722 RESTRICT_TO_RANGE(contrast, 0, MAX_CONTRAST);
723 RESTRICT_TO_RANGE(saturation, 0, MAX_SATURATION);
724 RESTRICT_TO_RANGE(sharpness, 0, MAX_SHARPNESS);
725 RESTRICT_TO_RANGE(whitebal, 0, MAX_WHITEBAL);
726
727 cam->brightness = brightness / 11;
728 cam->contrast = contrast / 11;
729 cam->saturation = saturation / 11;
730 cam->sharpness = sharpness / 11;
731 cam->white_bal = whitebal / 11;
732
733 uvd->vpic.colour = 108;
734 uvd->vpic.hue = 108;
735 uvd->vpic.brightness = brightness;
736 uvd->vpic.contrast = contrast;
737 uvd->vpic.whiteness = whitebal;
738 uvd->vpic.depth = 6;
739 uvd->vpic.palette = VIDEO_PALETTE_YUV420P;
740
741 memset(&uvd->vcap, 0, sizeof(uvd->vcap));
742 strcpy(uvd->vcap.name, "Konica Webcam");
743 uvd->vcap.type = VID_TYPE_CAPTURE;
744 uvd->vcap.channels = 1;
745 uvd->vcap.audios = 0;
746 uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
747 uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
748 uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
749 uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
750
751 memset(&uvd->vchan, 0, sizeof(uvd->vchan));
752 uvd->vchan.flags = 0 ;
753 uvd->vchan.tuners = 0;
754 uvd->vchan.channel = 0;
755 uvd->vchan.type = VIDEO_TYPE_CAMERA;
756 strcpy(uvd->vchan.name, "Camera");
757
758 /* Talk to device */
759 DEBUG(1, "device init");
760 if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
761 DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]);
762 if(!konicawc_get_misc(uvd, 0x3, 0, 0x10, buf, 2))
763 DEBUG(2, "3,10 -> %2.2x %2.2x", buf[0], buf[1]);
764 if(konicawc_set_misc(uvd, 0x2, 0, 0xd))
765 DEBUG(2, "2,0,d failed");
766 DEBUG(1, "setting initial values");
767}
768
769static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id *devid)
770{
771 struct usb_device *dev = interface_to_usbdev(intf);
772 struct uvd *uvd = NULL;
773 int ix, i, nas;
774 int actInterface=-1, inactInterface=-1, maxPS=0;
775 unsigned char video_ep = 0;
776
777 DEBUG(1, "konicawc_probe(%p)", intf);
778
779 /* We don't handle multi-config cameras */
780 if (dev->descriptor.bNumConfigurations != 1)
781 return -ENODEV;
782
783 info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice));
784 RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
785
786 /* Validate found interface: must have one ISO endpoint */
787 nas = intf->num_altsetting;
788 if (nas != 8) {
789 err("Incorrect number of alternate settings (%d) for this camera!", nas);
790 return -ENODEV;
791 }
792 /* Validate all alternate settings */
793 for (ix=0; ix < nas; ix++) {
794 const struct usb_host_interface *interface;
795 const struct usb_endpoint_descriptor *endpoint;
796
797 interface = &intf->altsetting[ix];
798 i = interface->desc.bAlternateSetting;
799 if (interface->desc.bNumEndpoints != 2) {
800 err("Interface %d. has %u. endpoints!",
801 interface->desc.bInterfaceNumber,
802 (unsigned)(interface->desc.bNumEndpoints));
803 return -ENODEV;
804 }
805 endpoint = &interface->endpoint[1].desc;
806 DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x",
807 endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize));
808 if (video_ep == 0)
809 video_ep = endpoint->bEndpointAddress;
810 else if (video_ep != endpoint->bEndpointAddress) {
811 err("Alternate settings have different endpoint addresses!");
812 return -ENODEV;
813 }
814 if ((endpoint->bmAttributes & 0x03) != 0x01) {
815 err("Interface %d. has non-ISO endpoint!",
816 interface->desc.bInterfaceNumber);
817 return -ENODEV;
818 }
819 if ((endpoint->bEndpointAddress & 0x80) == 0) {
820 err("Interface %d. has ISO OUT endpoint!",
821 interface->desc.bInterfaceNumber);
822 return -ENODEV;
823 }
824 if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
825 if (inactInterface < 0)
826 inactInterface = i;
827 else {
828 err("More than one inactive alt. setting!");
829 return -ENODEV;
830 }
831 } else {
832 if (i == spd_to_iface[speed]) {
833 /* This one is the requested one */
834 actInterface = i;
835 }
836 }
837 if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS)
838 maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
839 }
840 if(actInterface == -1) {
841 err("Cant find required endpoint");
842 return -ENODEV;
843 }
844
845 DEBUG(1, "Selecting requested active setting=%d. maxPS=%d.", actInterface, maxPS);
846
847 uvd = usbvideo_AllocateDevice(cams);
848 if (uvd != NULL) {
849 struct konicawc *cam = (struct konicawc *)(uvd->user_data);
850 /* Here uvd is a fully allocated uvd object */
851 for(i = 0; i < USBVIDEO_NUMSBUF; i++) {
852 cam->sts_urb[i] = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
853 if(cam->sts_urb[i] == NULL) {
854 while(i--) {
855 usb_free_urb(cam->sts_urb[i]);
856 }
857 err("can't allocate urbs");
858 return -ENOMEM;
859 }
860 }
861 cam->speed = speed;
862 RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
863 cam->width = camera_sizes[size].width;
864 cam->height = camera_sizes[size].height;
865 cam->size = size;
866
867 uvd->flags = 0;
868 uvd->debug = debug;
869 uvd->dev = dev;
870 uvd->iface = intf->altsetting->desc.bInterfaceNumber;
871 uvd->ifaceAltInactive = inactInterface;
872 uvd->ifaceAltActive = actInterface;
873 uvd->video_endp = video_ep;
874 uvd->iso_packet_len = maxPS;
875 uvd->paletteBits = 1L << VIDEO_PALETTE_YUV420P;
876 uvd->defaultPalette = VIDEO_PALETTE_YUV420P;
877 uvd->canvas = VIDEOSIZE(320, 240);
878 uvd->videosize = VIDEOSIZE(cam->width, cam->height);
879
880 /* Initialize konicawc specific data */
881 konicawc_configure_video(uvd);
882
883 i = usbvideo_RegisterVideoDevice(uvd);
884 uvd->max_frame_size = (320 * 240 * 3)/2;
885 if (i != 0) {
886 err("usbvideo_RegisterVideoDevice() failed.");
887 uvd = NULL;
888 }
889
890 konicawc_register_input(cam, dev);
891 }
892
893 if (uvd) {
894 usb_set_intfdata (intf, uvd);
895 return 0;
896 }
897 return -EIO;
898}
899
900
901static void konicawc_free_uvd(struct uvd *uvd)
902{
903 int i;
904 struct konicawc *cam = (struct konicawc *)uvd->user_data;
905
906 konicawc_unregister_input(cam);
907
908 for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
909 usb_free_urb(cam->sts_urb[i]);
910 cam->sts_urb[i] = NULL;
911 }
912}
913
914
915static struct usb_device_id id_table[] = {
916 { USB_DEVICE(0x04c8, 0x0720) }, /* Intel YC 76 */
917 { } /* Terminating entry */
918};
919
920
921static int __init konicawc_init(void)
922{
923 struct usbvideo_cb cbTbl;
924 info(DRIVER_DESC " " DRIVER_VERSION);
925 memset(&cbTbl, 0, sizeof(cbTbl));
926 cbTbl.probe = konicawc_probe;
927 cbTbl.setupOnOpen = konicawc_setup_on_open;
928 cbTbl.processData = konicawc_process_isoc;
929 cbTbl.getFPS = konicawc_calculate_fps;
930 cbTbl.setVideoMode = konicawc_set_video_mode;
931 cbTbl.startDataPump = konicawc_start_data;
932 cbTbl.stopDataPump = konicawc_stop_data;
933 cbTbl.adjustPicture = konicawc_adjust_picture;
934 cbTbl.userFree = konicawc_free_uvd;
935 return usbvideo_register(
936 &cams,
937 MAX_CAMERAS,
938 sizeof(struct konicawc),
939 "konicawc",
940 &cbTbl,
941 THIS_MODULE,
942 id_table);
943}
944
945
946static void __exit konicawc_cleanup(void)
947{
948 usbvideo_Deregister(&cams);
949}
950
951
952MODULE_DEVICE_TABLE(usb, id_table);
953
954MODULE_LICENSE("GPL");
955MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>");
956MODULE_DESCRIPTION(DRIVER_DESC);
957module_param(speed, int, 0);
958MODULE_PARM_DESC(speed, "Initial speed: 0 (slowest) - 6 (fastest)");
959module_param(size, int, 0);
960MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 160x136 2: 176x144 3: 320x240");
961module_param(brightness, int, 0);
962MODULE_PARM_DESC(brightness, "Initial brightness 0 - 108");
963module_param(contrast, int, 0);
964MODULE_PARM_DESC(contrast, "Initial contrast 0 - 108");
965module_param(saturation, int, 0);
966MODULE_PARM_DESC(saturation, "Initial saturation 0 - 108");
967module_param(sharpness, int, 0);
968MODULE_PARM_DESC(sharpness, "Initial brightness 0 - 108");
969module_param(whitebal, int, 0);
970MODULE_PARM_DESC(whitebal, "Initial white balance 0 - 363");
971
972#ifdef CONFIG_USB_DEBUG
973module_param(debug, int, S_IRUGO | S_IWUSR);
974MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
975#endif
976
977module_init(konicawc_init);
978module_exit(konicawc_cleanup);
diff --git a/drivers/media/video/usbvideo/ultracam.c b/drivers/media/video/usbvideo/ultracam.c
new file mode 100644
index 000000000000..75ff755224df
--- /dev/null
+++ b/drivers/media/video/usbvideo/ultracam.c
@@ -0,0 +1,679 @@
1/*
2 * USB NB Camera driver
3 *
4 * HISTORY:
5 * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods.
6 */
7
8#include <linux/kernel.h>
9#include <linux/sched.h>
10#include <linux/module.h>
11#include <linux/init.h>
12
13#include "usbvideo.h"
14
15#define ULTRACAM_VENDOR_ID 0x0461
16#define ULTRACAM_PRODUCT_ID 0x0813
17
18#define MAX_CAMERAS 4 /* How many devices we allow to connect */
19
20/*
21 * This structure lives in uvd_t->user field.
22 */
23typedef struct {
24 int initialized; /* Had we already sent init sequence? */
25 int camera_model; /* What type of IBM camera we got? */
26 int has_hdr;
27} ultracam_t;
28#define ULTRACAM_T(uvd) ((ultracam_t *)((uvd)->user_data))
29
30static struct usbvideo *cams = NULL;
31
32static int debug = 0;
33
34static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
35
36static const int min_canvasWidth = 8;
37static const int min_canvasHeight = 4;
38
39#define FRAMERATE_MIN 0
40#define FRAMERATE_MAX 6
41static int framerate = -1;
42
43/*
44 * Here we define several initialization variables. They may
45 * be used to automatically set color, hue, brightness and
46 * contrast to desired values. This is particularly useful in
47 * case of webcams (which have no controls and no on-screen
48 * output) and also when a client V4L software is used that
49 * does not have some of those controls. In any case it's
50 * good to have startup values as options.
51 *
52 * These values are all in [0..255] range. This simplifies
53 * operation. Note that actual values of V4L variables may
54 * be scaled up (as much as << 8). User can see that only
55 * on overlay output, however, or through a V4L client.
56 */
57static int init_brightness = 128;
58static int init_contrast = 192;
59static int init_color = 128;
60static int init_hue = 128;
61static int hue_correction = 128;
62
63module_param(debug, int, S_IRUGO | S_IWUSR);
64MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
65module_param(flags, int, 0);
66MODULE_PARM_DESC(flags,
67 "Bitfield: 0=VIDIOCSYNC, "
68 "1=B/W, "
69 "2=show hints, "
70 "3=show stats, "
71 "4=test pattern, "
72 "5=separate frames, "
73 "6=clean frames");
74module_param(framerate, int, 0);
75MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
76
77module_param(init_brightness, int, 0);
78MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
79module_param(init_contrast, int, 0);
80MODULE_PARM_DESC(init_contrast, "Contrast preconfiguration: 0-255 (default=192)");
81module_param(init_color, int, 0);
82MODULE_PARM_DESC(init_color, "Color preconfiguration: 0-255 (default=128)");
83module_param(init_hue, int, 0);
84MODULE_PARM_DESC(init_hue, "Hue preconfiguration: 0-255 (default=128)");
85module_param(hue_correction, int, 0);
86MODULE_PARM_DESC(hue_correction, "YUV colorspace regulation: 0-255 (default=128)");
87
88/*
89 * ultracam_ProcessIsocData()
90 *
91 * Generic routine to parse the ring queue data. It employs either
92 * ultracam_find_header() or ultracam_parse_lines() to do most
93 * of work.
94 *
95 * 02-Nov-2000 First (mostly dummy) version.
96 * 06-Nov-2000 Rewrote to dump all data into frame.
97 */
98static void ultracam_ProcessIsocData(struct uvd *uvd, struct usbvideo_frame *frame)
99{
100 int n;
101
102 assert(uvd != NULL);
103 assert(frame != NULL);
104
105 /* Try to move data from queue into frame buffer */
106 n = RingQueue_GetLength(&uvd->dp);
107 if (n > 0) {
108 int m;
109 /* See how much spare we have left */
110 m = uvd->max_frame_size - frame->seqRead_Length;
111 if (n > m)
112 n = m;
113 /* Now move that much data into frame buffer */
114 RingQueue_Dequeue(
115 &uvd->dp,
116 frame->data + frame->seqRead_Length,
117 m);
118 frame->seqRead_Length += m;
119 }
120 /* See if we filled the frame */
121 if (frame->seqRead_Length >= uvd->max_frame_size) {
122 frame->frameState = FrameState_Done;
123 uvd->curframe = -1;
124 uvd->stats.frame_num++;
125 }
126}
127
128/*
129 * ultracam_veio()
130 *
131 * History:
132 * 1/27/00 Added check for dev == NULL; this happens if camera is unplugged.
133 */
134static int ultracam_veio(
135 struct uvd *uvd,
136 unsigned char req,
137 unsigned short value,
138 unsigned short index,
139 int is_out)
140{
141 static const char proc[] = "ultracam_veio";
142 unsigned char cp[8] /* = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef } */;
143 int i;
144
145 if (!CAMERA_IS_OPERATIONAL(uvd))
146 return 0;
147
148 if (!is_out) {
149 i = usb_control_msg(
150 uvd->dev,
151 usb_rcvctrlpipe(uvd->dev, 0),
152 req,
153 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
154 value,
155 index,
156 cp,
157 sizeof(cp),
158 1000);
159#if 1
160 info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
161 "(req=$%02x val=$%04x ind=$%04x)",
162 cp[0],cp[1],cp[2],cp[3],cp[4],cp[5],cp[6],cp[7],
163 req, value, index);
164#endif
165 } else {
166 i = usb_control_msg(
167 uvd->dev,
168 usb_sndctrlpipe(uvd->dev, 0),
169 req,
170 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
171 value,
172 index,
173 NULL,
174 0,
175 1000);
176 }
177 if (i < 0) {
178 err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
179 proc, i);
180 uvd->last_error = i;
181 }
182 return i;
183}
184
185/*
186 * ultracam_calculate_fps()
187 */
188static int ultracam_calculate_fps(struct uvd *uvd)
189{
190 return 3 + framerate*4 + framerate/2;
191}
192
193/*
194 * ultracam_adjust_contrast()
195 */
196static void ultracam_adjust_contrast(struct uvd *uvd)
197{
198}
199
200/*
201 * ultracam_set_brightness()
202 *
203 * This procedure changes brightness of the picture.
204 */
205static void ultracam_set_brightness(struct uvd *uvd)
206{
207}
208
209static void ultracam_set_hue(struct uvd *uvd)
210{
211}
212
213/*
214 * ultracam_adjust_picture()
215 *
216 * This procedure gets called from V4L interface to update picture settings.
217 * Here we change brightness and contrast.
218 */
219static void ultracam_adjust_picture(struct uvd *uvd)
220{
221 ultracam_adjust_contrast(uvd);
222 ultracam_set_brightness(uvd);
223 ultracam_set_hue(uvd);
224}
225
226/*
227 * ultracam_video_stop()
228 *
229 * This code tells camera to stop streaming. The interface remains
230 * configured and bandwidth - claimed.
231 */
232static void ultracam_video_stop(struct uvd *uvd)
233{
234}
235
236/*
237 * ultracam_reinit_iso()
238 *
239 * This procedure sends couple of commands to the camera and then
240 * resets the video pipe. This sequence was observed to reinit the
241 * camera or, at least, to initiate ISO data stream.
242 */
243static void ultracam_reinit_iso(struct uvd *uvd, int do_stop)
244{
245}
246
247static void ultracam_video_start(struct uvd *uvd)
248{
249 ultracam_reinit_iso(uvd, 0);
250}
251
252static int ultracam_resetPipe(struct uvd *uvd)
253{
254 usb_clear_halt(uvd->dev, uvd->video_endp);
255 return 0;
256}
257
258static int ultracam_alternateSetting(struct uvd *uvd, int setting)
259{
260 static const char proc[] = "ultracam_alternateSetting";
261 int i;
262 i = usb_set_interface(uvd->dev, uvd->iface, setting);
263 if (i < 0) {
264 err("%s: usb_set_interface error", proc);
265 uvd->last_error = i;
266 return -EBUSY;
267 }
268 return 0;
269}
270
271/*
272 * Return negative code on failure, 0 on success.
273 */
274static int ultracam_setup_on_open(struct uvd *uvd)
275{
276 int setup_ok = 0; /* Success by default */
277 /* Send init sequence only once, it's large! */
278 if (!ULTRACAM_T(uvd)->initialized) {
279 ultracam_alternateSetting(uvd, 0x04);
280 ultracam_alternateSetting(uvd, 0x00);
281 ultracam_veio(uvd, 0x02, 0x0004, 0x000b, 1);
282 ultracam_veio(uvd, 0x02, 0x0001, 0x0005, 1);
283 ultracam_veio(uvd, 0x02, 0x8000, 0x0000, 1);
284 ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
285 ultracam_veio(uvd, 0x00, 0x00b0, 0x0001, 1);
286 ultracam_veio(uvd, 0x00, 0x0000, 0x0002, 1);
287 ultracam_veio(uvd, 0x00, 0x000c, 0x0003, 1);
288 ultracam_veio(uvd, 0x00, 0x000b, 0x0004, 1);
289 ultracam_veio(uvd, 0x00, 0x0000, 0x0005, 1);
290 ultracam_veio(uvd, 0x00, 0x0000, 0x0006, 1);
291 ultracam_veio(uvd, 0x00, 0x0079, 0x0007, 1);
292 ultracam_veio(uvd, 0x00, 0x003b, 0x0008, 1);
293 ultracam_veio(uvd, 0x00, 0x0002, 0x000f, 1);
294 ultracam_veio(uvd, 0x00, 0x0001, 0x0010, 1);
295 ultracam_veio(uvd, 0x00, 0x0000, 0x0011, 1);
296 ultracam_veio(uvd, 0x00, 0x0000, 0x00bf, 1);
297 ultracam_veio(uvd, 0x00, 0x0001, 0x00c0, 1);
298 ultracam_veio(uvd, 0x00, 0x0010, 0x00cb, 1);
299 ultracam_veio(uvd, 0x01, 0x00a4, 0x0001, 1);
300 ultracam_veio(uvd, 0x01, 0x0010, 0x0002, 1);
301 ultracam_veio(uvd, 0x01, 0x0066, 0x0007, 1);
302 ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
303 ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
304 ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
305 ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
306 ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
307 ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
308 ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
309 ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
310 ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
311 ultracam_veio(uvd, 0x01, 0x000b, 0x0011, 1);
312 ultracam_veio(uvd, 0x01, 0x0001, 0x0012, 1);
313 ultracam_veio(uvd, 0x01, 0x0000, 0x0013, 1);
314 ultracam_veio(uvd, 0x01, 0x0000, 0x0014, 1);
315 ultracam_veio(uvd, 0x01, 0x0087, 0x0051, 1);
316 ultracam_veio(uvd, 0x01, 0x0040, 0x0052, 1);
317 ultracam_veio(uvd, 0x01, 0x0058, 0x0053, 1);
318 ultracam_veio(uvd, 0x01, 0x0040, 0x0054, 1);
319 ultracam_veio(uvd, 0x01, 0x0000, 0x0040, 1);
320 ultracam_veio(uvd, 0x01, 0x0010, 0x0041, 1);
321 ultracam_veio(uvd, 0x01, 0x0020, 0x0042, 1);
322 ultracam_veio(uvd, 0x01, 0x0030, 0x0043, 1);
323 ultracam_veio(uvd, 0x01, 0x0040, 0x0044, 1);
324 ultracam_veio(uvd, 0x01, 0x0050, 0x0045, 1);
325 ultracam_veio(uvd, 0x01, 0x0060, 0x0046, 1);
326 ultracam_veio(uvd, 0x01, 0x0070, 0x0047, 1);
327 ultracam_veio(uvd, 0x01, 0x0080, 0x0048, 1);
328 ultracam_veio(uvd, 0x01, 0x0090, 0x0049, 1);
329 ultracam_veio(uvd, 0x01, 0x00a0, 0x004a, 1);
330 ultracam_veio(uvd, 0x01, 0x00b0, 0x004b, 1);
331 ultracam_veio(uvd, 0x01, 0x00c0, 0x004c, 1);
332 ultracam_veio(uvd, 0x01, 0x00d0, 0x004d, 1);
333 ultracam_veio(uvd, 0x01, 0x00e0, 0x004e, 1);
334 ultracam_veio(uvd, 0x01, 0x00f0, 0x004f, 1);
335 ultracam_veio(uvd, 0x01, 0x00ff, 0x0050, 1);
336 ultracam_veio(uvd, 0x01, 0x0000, 0x0056, 1);
337 ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
338 ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
339 ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
340 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
341 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
342 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
343 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
344 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
345 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
346 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
347 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
348 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
349 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
350 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
351 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
352 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
353 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
354 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
355 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
356 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
357 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
358 ultracam_veio(uvd, 0x00, 0x0080, 0x00c1, 1);
359 ultracam_veio(uvd, 0x00, 0x0004, 0x00c2, 1);
360 ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
361 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
362 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
363 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
364 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
365 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
366 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
367 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
368 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
369 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
370 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
371 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
372 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
373 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
374 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
375 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
376 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
377 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
378 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
379 ultracam_veio(uvd, 0x00, 0x0002, 0x00c1, 1);
380 ultracam_veio(uvd, 0x00, 0x0020, 0x00c2, 1);
381 ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
382 ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
383 ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
384 ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
385 ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
386 ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
387 ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
388 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
389 ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
390 ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
391 ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
392 ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
393 ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
394 ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
395 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
396 ultracam_veio(uvd, 0x00, 0x0040, 0x00c1, 1);
397 ultracam_veio(uvd, 0x00, 0x0017, 0x00c2, 1);
398 ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
399 ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
400 ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
401 ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
402 ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
403 ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
404 ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
405 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
406 ultracam_veio(uvd, 0x00, 0x0000, 0x00c3, 1);
407 ultracam_veio(uvd, 0x00, 0x0000, 0x00c4, 1);
408 ultracam_veio(uvd, 0x00, 0x0000, 0x00c5, 1);
409 ultracam_veio(uvd, 0x00, 0x0000, 0x00c6, 1);
410 ultracam_veio(uvd, 0x00, 0x0000, 0x00c7, 1);
411 ultracam_veio(uvd, 0x00, 0x0000, 0x00c8, 1);
412 ultracam_veio(uvd, 0x00, 0x0000, 0x00c9, 1);
413 ultracam_veio(uvd, 0x00, 0x00c0, 0x00c1, 1);
414 ultracam_veio(uvd, 0x00, 0x0000, 0x00c2, 1);
415 ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
416 ultracam_veio(uvd, 0x02, 0xc040, 0x0001, 1);
417 ultracam_veio(uvd, 0x01, 0x0000, 0x0008, 0);
418 ultracam_veio(uvd, 0x01, 0x0000, 0x0009, 0);
419 ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 0);
420 ultracam_veio(uvd, 0x01, 0x0000, 0x000b, 0);
421 ultracam_veio(uvd, 0x01, 0x0000, 0x000c, 0);
422 ultracam_veio(uvd, 0x01, 0x0000, 0x000d, 0);
423 ultracam_veio(uvd, 0x01, 0x0000, 0x000e, 0);
424 ultracam_veio(uvd, 0x01, 0x0000, 0x000f, 0);
425 ultracam_veio(uvd, 0x01, 0x0000, 0x0010, 0);
426 ultracam_veio(uvd, 0x01, 0x000b, 0x0008, 1);
427 ultracam_veio(uvd, 0x01, 0x0034, 0x0009, 1);
428 ultracam_veio(uvd, 0x01, 0x0000, 0x000a, 1);
429 ultracam_veio(uvd, 0x01, 0x002e, 0x000b, 1);
430 ultracam_veio(uvd, 0x01, 0x00d6, 0x000c, 1);
431 ultracam_veio(uvd, 0x01, 0x00fc, 0x000d, 1);
432 ultracam_veio(uvd, 0x01, 0x00f1, 0x000e, 1);
433 ultracam_veio(uvd, 0x01, 0x00da, 0x000f, 1);
434 ultracam_veio(uvd, 0x01, 0x0036, 0x0010, 1);
435 ultracam_veio(uvd, 0x01, 0x0000, 0x0001, 0);
436 ultracam_veio(uvd, 0x01, 0x0064, 0x0001, 1);
437 ultracam_veio(uvd, 0x01, 0x0059, 0x0051, 1);
438 ultracam_veio(uvd, 0x01, 0x003f, 0x0052, 1);
439 ultracam_veio(uvd, 0x01, 0x0094, 0x0053, 1);
440 ultracam_veio(uvd, 0x01, 0x00ff, 0x0011, 1);
441 ultracam_veio(uvd, 0x01, 0x0003, 0x0012, 1);
442 ultracam_veio(uvd, 0x01, 0x00f7, 0x0013, 1);
443 ultracam_veio(uvd, 0x00, 0x0009, 0x0011, 1);
444 ultracam_veio(uvd, 0x00, 0x0000, 0x0001, 1);
445 ultracam_veio(uvd, 0x00, 0x0000, 0x0000, 1);
446 ultracam_veio(uvd, 0x00, 0x0020, 0x00c1, 1);
447 ultracam_veio(uvd, 0x00, 0x0010, 0x00c2, 1);
448 ultracam_veio(uvd, 0x00, 0x0000, 0x00ca, 1);
449 ultracam_alternateSetting(uvd, 0x04);
450 ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
451 ultracam_veio(uvd, 0x02, 0x0000, 0x0001, 1);
452 ultracam_veio(uvd, 0x02, 0x0000, 0x0006, 1);
453 ultracam_veio(uvd, 0x02, 0x9000, 0x0007, 1);
454 ultracam_veio(uvd, 0x02, 0x0042, 0x0001, 1);
455 ultracam_veio(uvd, 0x02, 0x0000, 0x000b, 0);
456 ultracam_resetPipe(uvd);
457 ULTRACAM_T(uvd)->initialized = (setup_ok != 0);
458 }
459 return setup_ok;
460}
461
462static void ultracam_configure_video(struct uvd *uvd)
463{
464 if (uvd == NULL)
465 return;
466
467 RESTRICT_TO_RANGE(init_brightness, 0, 255);
468 RESTRICT_TO_RANGE(init_contrast, 0, 255);
469 RESTRICT_TO_RANGE(init_color, 0, 255);
470 RESTRICT_TO_RANGE(init_hue, 0, 255);
471 RESTRICT_TO_RANGE(hue_correction, 0, 255);
472
473 memset(&uvd->vpic, 0, sizeof(uvd->vpic));
474 memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
475
476 uvd->vpic.colour = init_color << 8;
477 uvd->vpic.hue = init_hue << 8;
478 uvd->vpic.brightness = init_brightness << 8;
479 uvd->vpic.contrast = init_contrast << 8;
480 uvd->vpic.whiteness = 105 << 8; /* This one isn't used */
481 uvd->vpic.depth = 24;
482 uvd->vpic.palette = VIDEO_PALETTE_RGB24;
483
484 memset(&uvd->vcap, 0, sizeof(uvd->vcap));
485 strcpy(uvd->vcap.name, "IBM Ultra Camera");
486 uvd->vcap.type = VID_TYPE_CAPTURE;
487 uvd->vcap.channels = 1;
488 uvd->vcap.audios = 0;
489 uvd->vcap.maxwidth = VIDEOSIZE_X(uvd->canvas);
490 uvd->vcap.maxheight = VIDEOSIZE_Y(uvd->canvas);
491 uvd->vcap.minwidth = min_canvasWidth;
492 uvd->vcap.minheight = min_canvasHeight;
493
494 memset(&uvd->vchan, 0, sizeof(uvd->vchan));
495 uvd->vchan.flags = 0;
496 uvd->vchan.tuners = 0;
497 uvd->vchan.channel = 0;
498 uvd->vchan.type = VIDEO_TYPE_CAMERA;
499 strcpy(uvd->vchan.name, "Camera");
500}
501
502/*
503 * ultracam_probe()
504 *
505 * This procedure queries device descriptor and accepts the interface
506 * if it looks like our camera.
507 *
508 * History:
509 * 12-Nov-2000 Reworked to comply with new probe() signature.
510 * 23-Jan-2001 Added compatibility with 2.2.x kernels.
511 */
512static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id *devid)
513{
514 struct usb_device *dev = interface_to_usbdev(intf);
515 struct uvd *uvd = NULL;
516 int ix, i, nas;
517 int actInterface=-1, inactInterface=-1, maxPS=0;
518 unsigned char video_ep = 0;
519
520 if (debug >= 1)
521 info("ultracam_probe(%p)", intf);
522
523 /* We don't handle multi-config cameras */
524 if (dev->descriptor.bNumConfigurations != 1)
525 return -ENODEV;
526
527 info("IBM Ultra camera found (rev. 0x%04x)",
528 le16_to_cpu(dev->descriptor.bcdDevice));
529
530 /* Validate found interface: must have one ISO endpoint */
531 nas = intf->num_altsetting;
532 if (debug > 0)
533 info("Number of alternate settings=%d.", nas);
534 if (nas < 8) {
535 err("Too few alternate settings for this camera!");
536 return -ENODEV;
537 }
538 /* Validate all alternate settings */
539 for (ix=0; ix < nas; ix++) {
540 const struct usb_host_interface *interface;
541 const struct usb_endpoint_descriptor *endpoint;
542
543 interface = &intf->altsetting[ix];
544 i = interface->desc.bAlternateSetting;
545 if (interface->desc.bNumEndpoints != 1) {
546 err("Interface %d. has %u. endpoints!",
547 interface->desc.bInterfaceNumber,
548 (unsigned)(interface->desc.bNumEndpoints));
549 return -ENODEV;
550 }
551 endpoint = &interface->endpoint[0].desc;
552 if (video_ep == 0)
553 video_ep = endpoint->bEndpointAddress;
554 else if (video_ep != endpoint->bEndpointAddress) {
555 err("Alternate settings have different endpoint addresses!");
556 return -ENODEV;
557 }
558 if ((endpoint->bmAttributes & 0x03) != 0x01) {
559 err("Interface %d. has non-ISO endpoint!",
560 interface->desc.bInterfaceNumber);
561 return -ENODEV;
562 }
563 if ((endpoint->bEndpointAddress & 0x80) == 0) {
564 err("Interface %d. has ISO OUT endpoint!",
565 interface->desc.bInterfaceNumber);
566 return -ENODEV;
567 }
568 if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
569 if (inactInterface < 0)
570 inactInterface = i;
571 else {
572 err("More than one inactive alt. setting!");
573 return -ENODEV;
574 }
575 } else {
576 if (actInterface < 0) {
577 actInterface = i;
578 maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
579 if (debug > 0)
580 info("Active setting=%d. maxPS=%d.", i, maxPS);
581 } else {
582 /* Got another active alt. setting */
583 if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) {
584 /* This one is better! */
585 actInterface = i;
586 maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
587 if (debug > 0) {
588 info("Even better ctive setting=%d. maxPS=%d.",
589 i, maxPS);
590 }
591 }
592 }
593 }
594 }
595 if ((maxPS <= 0) || (actInterface < 0) || (inactInterface < 0)) {
596 err("Failed to recognize the camera!");
597 return -ENODEV;
598 }
599
600 uvd = usbvideo_AllocateDevice(cams);
601 if (uvd != NULL) {
602 /* Here uvd is a fully allocated uvd object */
603 uvd->flags = flags;
604 uvd->debug = debug;
605 uvd->dev = dev;
606 uvd->iface = intf->altsetting->desc.bInterfaceNumber;
607 uvd->ifaceAltInactive = inactInterface;
608 uvd->ifaceAltActive = actInterface;
609 uvd->video_endp = video_ep;
610 uvd->iso_packet_len = maxPS;
611 uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
612 uvd->defaultPalette = VIDEO_PALETTE_RGB24;
613 uvd->canvas = VIDEOSIZE(640, 480); /* FIXME */
614 uvd->videosize = uvd->canvas; /* ultracam_size_to_videosize(size);*/
615
616 /* Initialize ibmcam-specific data */
617 assert(ULTRACAM_T(uvd) != NULL);
618 ULTRACAM_T(uvd)->camera_model = 0; /* Not used yet */
619 ULTRACAM_T(uvd)->initialized = 0;
620
621 ultracam_configure_video(uvd);
622
623 i = usbvideo_RegisterVideoDevice(uvd);
624 if (i != 0) {
625 err("usbvideo_RegisterVideoDevice() failed.");
626 uvd = NULL;
627 }
628 }
629
630 if (uvd) {
631 usb_set_intfdata (intf, uvd);
632 return 0;
633 }
634 return -EIO;
635}
636
637
638static struct usb_device_id id_table[] = {
639 { USB_DEVICE(ULTRACAM_VENDOR_ID, ULTRACAM_PRODUCT_ID) },
640 { } /* Terminating entry */
641};
642
643/*
644 * ultracam_init()
645 *
646 * This code is run to initialize the driver.
647 */
648static int __init ultracam_init(void)
649{
650 struct usbvideo_cb cbTbl;
651 memset(&cbTbl, 0, sizeof(cbTbl));
652 cbTbl.probe = ultracam_probe;
653 cbTbl.setupOnOpen = ultracam_setup_on_open;
654 cbTbl.videoStart = ultracam_video_start;
655 cbTbl.videoStop = ultracam_video_stop;
656 cbTbl.processData = ultracam_ProcessIsocData;
657 cbTbl.postProcess = usbvideo_DeinterlaceFrame;
658 cbTbl.adjustPicture = ultracam_adjust_picture;
659 cbTbl.getFPS = ultracam_calculate_fps;
660 return usbvideo_register(
661 &cams,
662 MAX_CAMERAS,
663 sizeof(ultracam_t),
664 "ultracam",
665 &cbTbl,
666 THIS_MODULE,
667 id_table);
668}
669
670static void __exit ultracam_cleanup(void)
671{
672 usbvideo_Deregister(&cams);
673}
674
675MODULE_DEVICE_TABLE(usb, id_table);
676MODULE_LICENSE("GPL");
677
678module_init(ultracam_init);
679module_exit(ultracam_cleanup);
diff --git a/drivers/media/video/usbvideo/usbvideo.c b/drivers/media/video/usbvideo/usbvideo.c
new file mode 100644
index 000000000000..0b51fae720a9
--- /dev/null
+++ b/drivers/media/video/usbvideo/usbvideo.c
@@ -0,0 +1,2190 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2, or (at your option)
5 * any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/list.h>
20#include <linux/slab.h>
21#include <linux/module.h>
22#include <linux/mm.h>
23#include <linux/smp_lock.h>
24#include <linux/vmalloc.h>
25#include <linux/init.h>
26#include <linux/spinlock.h>
27
28#include <asm/io.h>
29
30#include "usbvideo.h"
31
32#if defined(MAP_NR)
33#define virt_to_page(v) MAP_NR(v) /* Kernels 2.2.x */
34#endif
35
36static int video_nr = -1;
37module_param(video_nr, int, 0);
38
39/*
40 * Local prototypes.
41 */
42static void usbvideo_Disconnect(struct usb_interface *intf);
43static void usbvideo_CameraRelease(struct uvd *uvd);
44
45static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
46 unsigned int cmd, unsigned long arg);
47static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma);
48static int usbvideo_v4l_open(struct inode *inode, struct file *file);
49static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
50 size_t count, loff_t *ppos);
51static int usbvideo_v4l_close(struct inode *inode, struct file *file);
52
53static int usbvideo_StartDataPump(struct uvd *uvd);
54static void usbvideo_StopDataPump(struct uvd *uvd);
55static int usbvideo_GetFrame(struct uvd *uvd, int frameNum);
56static int usbvideo_NewFrame(struct uvd *uvd, int framenum);
57static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
58 struct usbvideo_frame *frame);
59
60/*******************************/
61/* Memory management functions */
62/*******************************/
63static void *usbvideo_rvmalloc(unsigned long size)
64{
65 void *mem;
66 unsigned long adr;
67
68 size = PAGE_ALIGN(size);
69 mem = vmalloc_32(size);
70 if (!mem)
71 return NULL;
72
73 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
74 adr = (unsigned long) mem;
75 while (size > 0) {
76 SetPageReserved(vmalloc_to_page((void *)adr));
77 adr += PAGE_SIZE;
78 size -= PAGE_SIZE;
79 }
80
81 return mem;
82}
83
84static void usbvideo_rvfree(void *mem, unsigned long size)
85{
86 unsigned long adr;
87
88 if (!mem)
89 return;
90
91 adr = (unsigned long) mem;
92 while ((long) size > 0) {
93 ClearPageReserved(vmalloc_to_page((void *)adr));
94 adr += PAGE_SIZE;
95 size -= PAGE_SIZE;
96 }
97 vfree(mem);
98}
99
100static void RingQueue_Initialize(struct RingQueue *rq)
101{
102 assert(rq != NULL);
103 init_waitqueue_head(&rq->wqh);
104}
105
106static void RingQueue_Allocate(struct RingQueue *rq, int rqLen)
107{
108 /* Make sure the requested size is a power of 2 and
109 round up if necessary. This allows index wrapping
110 using masks rather than modulo */
111
112 int i = 1;
113 assert(rq != NULL);
114 assert(rqLen > 0);
115
116 while(rqLen >> i)
117 i++;
118 if(rqLen != 1 << (i-1))
119 rqLen = 1 << i;
120
121 rq->length = rqLen;
122 rq->ri = rq->wi = 0;
123 rq->queue = usbvideo_rvmalloc(rq->length);
124 assert(rq->queue != NULL);
125}
126
127static int RingQueue_IsAllocated(const struct RingQueue *rq)
128{
129 if (rq == NULL)
130 return 0;
131 return (rq->queue != NULL) && (rq->length > 0);
132}
133
134static void RingQueue_Free(struct RingQueue *rq)
135{
136 assert(rq != NULL);
137 if (RingQueue_IsAllocated(rq)) {
138 usbvideo_rvfree(rq->queue, rq->length);
139 rq->queue = NULL;
140 rq->length = 0;
141 }
142}
143
144int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len)
145{
146 int rql, toread;
147
148 assert(rq != NULL);
149 assert(dst != NULL);
150
151 rql = RingQueue_GetLength(rq);
152 if(!rql)
153 return 0;
154
155 /* Clip requested length to available data */
156 if(len > rql)
157 len = rql;
158
159 toread = len;
160 if(rq->ri > rq->wi) {
161 /* Read data from tail */
162 int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri;
163 memcpy(dst, rq->queue + rq->ri, read);
164 toread -= read;
165 dst += read;
166 rq->ri = (rq->ri + read) & (rq->length-1);
167 }
168 if(toread) {
169 /* Read data from head */
170 memcpy(dst, rq->queue + rq->ri, toread);
171 rq->ri = (rq->ri + toread) & (rq->length-1);
172 }
173 return len;
174}
175
176EXPORT_SYMBOL(RingQueue_Dequeue);
177
178int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n)
179{
180 int enqueued = 0;
181
182 assert(rq != NULL);
183 assert(cdata != NULL);
184 assert(rq->length > 0);
185 while (n > 0) {
186 int m, q_avail;
187
188 /* Calculate the largest chunk that fits the tail of the ring */
189 q_avail = rq->length - rq->wi;
190 if (q_avail <= 0) {
191 rq->wi = 0;
192 q_avail = rq->length;
193 }
194 m = n;
195 assert(q_avail > 0);
196 if (m > q_avail)
197 m = q_avail;
198
199 memcpy(rq->queue + rq->wi, cdata, m);
200 RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
201 cdata += m;
202 enqueued += m;
203 n -= m;
204 }
205 return enqueued;
206}
207
208EXPORT_SYMBOL(RingQueue_Enqueue);
209
210static void RingQueue_InterruptibleSleepOn(struct RingQueue *rq)
211{
212 assert(rq != NULL);
213 interruptible_sleep_on(&rq->wqh);
214}
215
216void RingQueue_WakeUpInterruptible(struct RingQueue *rq)
217{
218 assert(rq != NULL);
219 if (waitqueue_active(&rq->wqh))
220 wake_up_interruptible(&rq->wqh);
221}
222
223EXPORT_SYMBOL(RingQueue_WakeUpInterruptible);
224
225void RingQueue_Flush(struct RingQueue *rq)
226{
227 assert(rq != NULL);
228 rq->ri = 0;
229 rq->wi = 0;
230}
231
232EXPORT_SYMBOL(RingQueue_Flush);
233
234
235/*
236 * usbvideo_VideosizeToString()
237 *
238 * This procedure converts given videosize value to readable string.
239 *
240 * History:
241 * 07-Aug-2000 Created.
242 * 19-Oct-2000 Reworked for usbvideo module.
243 */
244static void usbvideo_VideosizeToString(char *buf, int bufLen, videosize_t vs)
245{
246 char tmp[40];
247 int n;
248
249 n = 1 + sprintf(tmp, "%ldx%ld", VIDEOSIZE_X(vs), VIDEOSIZE_Y(vs));
250 assert(n < sizeof(tmp));
251 if ((buf == NULL) || (bufLen < n))
252 err("usbvideo_VideosizeToString: buffer is too small.");
253 else
254 memmove(buf, tmp, n);
255}
256
257/*
258 * usbvideo_OverlayChar()
259 *
260 * History:
261 * 01-Feb-2000 Created.
262 */
263static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame,
264 int x, int y, int ch)
265{
266 static const unsigned short digits[16] = {
267 0xF6DE, /* 0 */
268 0x2492, /* 1 */
269 0xE7CE, /* 2 */
270 0xE79E, /* 3 */
271 0xB792, /* 4 */
272 0xF39E, /* 5 */
273 0xF3DE, /* 6 */
274 0xF492, /* 7 */
275 0xF7DE, /* 8 */
276 0xF79E, /* 9 */
277 0x77DA, /* a */
278 0xD75C, /* b */
279 0xF24E, /* c */
280 0xD6DC, /* d */
281 0xF34E, /* e */
282 0xF348 /* f */
283 };
284 unsigned short digit;
285 int ix, iy;
286
287 if ((uvd == NULL) || (frame == NULL))
288 return;
289
290 if (ch >= '0' && ch <= '9')
291 ch -= '0';
292 else if (ch >= 'A' && ch <= 'F')
293 ch = 10 + (ch - 'A');
294 else if (ch >= 'a' && ch <= 'f')
295 ch = 10 + (ch - 'a');
296 else
297 return;
298 digit = digits[ch];
299
300 for (iy=0; iy < 5; iy++) {
301 for (ix=0; ix < 3; ix++) {
302 if (digit & 0x8000) {
303 if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {
304/* TODO */ RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);
305 }
306 }
307 digit = digit << 1;
308 }
309 }
310}
311
312/*
313 * usbvideo_OverlayString()
314 *
315 * History:
316 * 01-Feb-2000 Created.
317 */
318static void usbvideo_OverlayString(struct uvd *uvd, struct usbvideo_frame *frame,
319 int x, int y, const char *str)
320{
321 while (*str) {
322 usbvideo_OverlayChar(uvd, frame, x, y, *str);
323 str++;
324 x += 4; /* 3 pixels character + 1 space */
325 }
326}
327
328/*
329 * usbvideo_OverlayStats()
330 *
331 * Overlays important debugging information.
332 *
333 * History:
334 * 01-Feb-2000 Created.
335 */
336static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame)
337{
338 const int y_diff = 8;
339 char tmp[16];
340 int x = 10, y=10;
341 long i, j, barLength;
342 const int qi_x1 = 60, qi_y1 = 10;
343 const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;
344
345 /* Call the user callback, see if we may proceed after that */
346 if (VALID_CALLBACK(uvd, overlayHook)) {
347 if (GET_CALLBACK(uvd, overlayHook)(uvd, frame) < 0)
348 return;
349 }
350
351 /*
352 * We draw a (mostly) hollow rectangle with qi_xxx coordinates.
353 * Left edge symbolizes the queue index 0; right edge symbolizes
354 * the full capacity of the queue.
355 */
356 barLength = qi_x2 - qi_x1 - 2;
357 if ((barLength > 10) && (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))) {
358/* TODO */ long u_lo, u_hi, q_used;
359 long m_ri, m_wi, m_lo, m_hi;
360
361 /*
362 * Determine fill zones (used areas of the queue):
363 * 0 xxxxxxx u_lo ...... uvd->dp.ri xxxxxxxx u_hi ..... uvd->dp.length
364 *
365 * if u_lo < 0 then there is no first filler.
366 */
367
368 q_used = RingQueue_GetLength(&uvd->dp);
369 if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
370 u_hi = uvd->dp.length;
371 u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1);
372 } else {
373 u_hi = (q_used + uvd->dp.ri);
374 u_lo = -1;
375 }
376
377 /* Convert byte indices into screen units */
378 m_ri = qi_x1 + ((barLength * uvd->dp.ri) / uvd->dp.length);
379 m_wi = qi_x1 + ((barLength * uvd->dp.wi) / uvd->dp.length);
380 m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;
381 m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);
382
383 for (j=qi_y1; j < (qi_y1 + qi_h); j++) {
384 for (i=qi_x1; i < qi_x2; i++) {
385 /* Draw border lines */
386 if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||
387 (i == qi_x1) || (i == (qi_x2 - 1))) {
388 RGB24_PUTPIXEL(frame, i, j, 0xFF, 0xFF, 0xFF);
389 continue;
390 }
391 /* For all other points the Y coordinate does not matter */
392 if ((i >= m_ri) && (i <= (m_ri + 3))) {
393 RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);
394 } else if ((i >= m_wi) && (i <= (m_wi + 3))) {
395 RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);
396 } else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
397 RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);
398 }
399 }
400 }
401
402 sprintf(tmp, "%8lx", uvd->stats.frame_num);
403 usbvideo_OverlayString(uvd, frame, x, y, tmp);
404 y += y_diff;
405
406 sprintf(tmp, "%8lx", uvd->stats.urb_count);
407 usbvideo_OverlayString(uvd, frame, x, y, tmp);
408 y += y_diff;
409
410 sprintf(tmp, "%8lx", uvd->stats.urb_length);
411 usbvideo_OverlayString(uvd, frame, x, y, tmp);
412 y += y_diff;
413
414 sprintf(tmp, "%8lx", uvd->stats.data_count);
415 usbvideo_OverlayString(uvd, frame, x, y, tmp);
416 y += y_diff;
417
418 sprintf(tmp, "%8lx", uvd->stats.header_count);
419 usbvideo_OverlayString(uvd, frame, x, y, tmp);
420 y += y_diff;
421
422 sprintf(tmp, "%8lx", uvd->stats.iso_skip_count);
423 usbvideo_OverlayString(uvd, frame, x, y, tmp);
424 y += y_diff;
425
426 sprintf(tmp, "%8lx", uvd->stats.iso_err_count);
427 usbvideo_OverlayString(uvd, frame, x, y, tmp);
428 y += y_diff;
429
430 sprintf(tmp, "%8x", uvd->vpic.colour);
431 usbvideo_OverlayString(uvd, frame, x, y, tmp);
432 y += y_diff;
433
434 sprintf(tmp, "%8x", uvd->vpic.hue);
435 usbvideo_OverlayString(uvd, frame, x, y, tmp);
436 y += y_diff;
437
438 sprintf(tmp, "%8x", uvd->vpic.brightness >> 8);
439 usbvideo_OverlayString(uvd, frame, x, y, tmp);
440 y += y_diff;
441
442 sprintf(tmp, "%8x", uvd->vpic.contrast >> 12);
443 usbvideo_OverlayString(uvd, frame, x, y, tmp);
444 y += y_diff;
445
446 sprintf(tmp, "%8d", uvd->vpic.whiteness >> 8);
447 usbvideo_OverlayString(uvd, frame, x, y, tmp);
448 y += y_diff;
449}
450
451/*
452 * usbvideo_ReportStatistics()
453 *
454 * This procedure prints packet and transfer statistics.
455 *
456 * History:
457 * 14-Jan-2000 Corrected default multiplier.
458 */
459static void usbvideo_ReportStatistics(const struct uvd *uvd)
460{
461 if ((uvd != NULL) && (uvd->stats.urb_count > 0)) {
462 unsigned long allPackets, badPackets, goodPackets, percent;
463 allPackets = uvd->stats.urb_count * CAMERA_URB_FRAMES;
464 badPackets = uvd->stats.iso_skip_count + uvd->stats.iso_err_count;
465 goodPackets = allPackets - badPackets;
466 /* Calculate percentage wisely, remember integer limits */
467 assert(allPackets != 0);
468 if (goodPackets < (((unsigned long)-1)/100))
469 percent = (100 * goodPackets) / allPackets;
470 else
471 percent = goodPackets / (allPackets / 100);
472 info("Packet Statistics: Total=%lu. Empty=%lu. Usage=%lu%%",
473 allPackets, badPackets, percent);
474 if (uvd->iso_packet_len > 0) {
475 unsigned long allBytes, xferBytes;
476 char multiplier = ' ';
477 allBytes = allPackets * uvd->iso_packet_len;
478 xferBytes = uvd->stats.data_count;
479 assert(allBytes != 0);
480 if (xferBytes < (((unsigned long)-1)/100))
481 percent = (100 * xferBytes) / allBytes;
482 else
483 percent = xferBytes / (allBytes / 100);
484 /* Scale xferBytes for easy reading */
485 if (xferBytes > 10*1024) {
486 xferBytes /= 1024;
487 multiplier = 'K';
488 if (xferBytes > 10*1024) {
489 xferBytes /= 1024;
490 multiplier = 'M';
491 if (xferBytes > 10*1024) {
492 xferBytes /= 1024;
493 multiplier = 'G';
494 if (xferBytes > 10*1024) {
495 xferBytes /= 1024;
496 multiplier = 'T';
497 }
498 }
499 }
500 }
501 info("Transfer Statistics: Transferred=%lu%cB Usage=%lu%%",
502 xferBytes, multiplier, percent);
503 }
504 }
505}
506
507/*
508 * usbvideo_TestPattern()
509 *
510 * Procedure forms a test pattern (yellow grid on blue background).
511 *
512 * Parameters:
513 * fullframe: if TRUE then entire frame is filled, otherwise the procedure
514 * continues from the current scanline.
515 * pmode 0: fill the frame with solid blue color (like on VCR or TV)
516 * 1: Draw a colored grid
517 *
518 * History:
519 * 01-Feb-2000 Created.
520 */
521void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
522{
523 struct usbvideo_frame *frame;
524 int num_cell = 0;
525 int scan_length = 0;
526 static int num_pass = 0;
527
528 if (uvd == NULL) {
529 err("%s: uvd == NULL", __FUNCTION__);
530 return;
531 }
532 if ((uvd->curframe < 0) || (uvd->curframe >= USBVIDEO_NUMFRAMES)) {
533 err("%s: uvd->curframe=%d.", __FUNCTION__, uvd->curframe);
534 return;
535 }
536
537 /* Grab the current frame */
538 frame = &uvd->frame[uvd->curframe];
539
540 /* Optionally start at the beginning */
541 if (fullframe) {
542 frame->curline = 0;
543 frame->seqRead_Length = 0;
544 }
545#if 0
546 { /* For debugging purposes only */
547 char tmp[20];
548 usbvideo_VideosizeToString(tmp, sizeof(tmp), frame->request);
549 info("testpattern: frame=%s", tmp);
550 }
551#endif
552 /* Form every scan line */
553 for (; frame->curline < VIDEOSIZE_Y(frame->request); frame->curline++) {
554 int i;
555 unsigned char *f = frame->data +
556 (VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);
557 for (i=0; i < VIDEOSIZE_X(frame->request); i++) {
558 unsigned char cb=0x80;
559 unsigned char cg = 0;
560 unsigned char cr = 0;
561
562 if (pmode == 1) {
563 if (frame->curline % 32 == 0)
564 cb = 0, cg = cr = 0xFF;
565 else if (i % 32 == 0) {
566 if (frame->curline % 32 == 1)
567 num_cell++;
568 cb = 0, cg = cr = 0xFF;
569 } else {
570 cb = ((num_cell*7) + num_pass) & 0xFF;
571 cg = ((num_cell*5) + num_pass*2) & 0xFF;
572 cr = ((num_cell*3) + num_pass*3) & 0xFF;
573 }
574 } else {
575 /* Just the blue screen */
576 }
577
578 *f++ = cb;
579 *f++ = cg;
580 *f++ = cr;
581 scan_length += 3;
582 }
583 }
584
585 frame->frameState = FrameState_Done;
586 frame->seqRead_Length += scan_length;
587 ++num_pass;
588
589 /* We do this unconditionally, regardless of FLAGS_OVERLAY_STATS */
590 usbvideo_OverlayStats(uvd, frame);
591}
592
593EXPORT_SYMBOL(usbvideo_TestPattern);
594
595
596#ifdef DEBUG
597/*
598 * usbvideo_HexDump()
599 *
600 * A debugging tool. Prints hex dumps.
601 *
602 * History:
603 * 29-Jul-2000 Added printing of offsets.
604 */
605void usbvideo_HexDump(const unsigned char *data, int len)
606{
607 const int bytes_per_line = 32;
608 char tmp[128]; /* 32*3 + 5 */
609 int i, k;
610
611 for (i=k=0; len > 0; i++, len--) {
612 if (i > 0 && ((i % bytes_per_line) == 0)) {
613 printk("%s\n", tmp);
614 k=0;
615 }
616 if ((i % bytes_per_line) == 0)
617 k += sprintf(&tmp[k], "%04x: ", i);
618 k += sprintf(&tmp[k], "%02x ", data[i]);
619 }
620 if (k > 0)
621 printk("%s\n", tmp);
622}
623
624EXPORT_SYMBOL(usbvideo_HexDump);
625
626#endif
627
628/* ******************************************************************** */
629
630/* XXX: this piece of crap really wants some error handling.. */
631static void usbvideo_ClientIncModCount(struct uvd *uvd)
632{
633 if (uvd == NULL) {
634 err("%s: uvd == NULL", __FUNCTION__);
635 return;
636 }
637 if (uvd->handle == NULL) {
638 err("%s: uvd->handle == NULL", __FUNCTION__);
639 return;
640 }
641 if (uvd->handle->md_module == NULL) {
642 err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
643 return;
644 }
645 if (!try_module_get(uvd->handle->md_module)) {
646 err("%s: try_module_get() == 0", __FUNCTION__);
647 return;
648 }
649}
650
651static void usbvideo_ClientDecModCount(struct uvd *uvd)
652{
653 if (uvd == NULL) {
654 err("%s: uvd == NULL", __FUNCTION__);
655 return;
656 }
657 if (uvd->handle == NULL) {
658 err("%s: uvd->handle == NULL", __FUNCTION__);
659 return;
660 }
661 if (uvd->handle->md_module == NULL) {
662 err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
663 return;
664 }
665 module_put(uvd->handle->md_module);
666}
667
668int usbvideo_register(
669 struct usbvideo **pCams,
670 const int num_cams,
671 const int num_extra,
672 const char *driverName,
673 const struct usbvideo_cb *cbTbl,
674 struct module *md,
675 const struct usb_device_id *id_table)
676{
677 struct usbvideo *cams;
678 int i, base_size, result;
679
680 /* Check parameters for sanity */
681 if ((num_cams <= 0) || (pCams == NULL) || (cbTbl == NULL)) {
682 err("%s: Illegal call", __FUNCTION__);
683 return -EINVAL;
684 }
685
686 /* Check registration callback - must be set! */
687 if (cbTbl->probe == NULL) {
688 err("%s: probe() is required!", __FUNCTION__);
689 return -EINVAL;
690 }
691
692 base_size = num_cams * sizeof(struct uvd) + sizeof(struct usbvideo);
693 cams = (struct usbvideo *) kzalloc(base_size, GFP_KERNEL);
694 if (cams == NULL) {
695 err("Failed to allocate %d. bytes for usbvideo struct", base_size);
696 return -ENOMEM;
697 }
698 dbg("%s: Allocated $%p (%d. bytes) for %d. cameras",
699 __FUNCTION__, cams, base_size, num_cams);
700
701 /* Copy callbacks, apply defaults for those that are not set */
702 memmove(&cams->cb, cbTbl, sizeof(cams->cb));
703 if (cams->cb.getFrame == NULL)
704 cams->cb.getFrame = usbvideo_GetFrame;
705 if (cams->cb.disconnect == NULL)
706 cams->cb.disconnect = usbvideo_Disconnect;
707 if (cams->cb.startDataPump == NULL)
708 cams->cb.startDataPump = usbvideo_StartDataPump;
709 if (cams->cb.stopDataPump == NULL)
710 cams->cb.stopDataPump = usbvideo_StopDataPump;
711
712 cams->num_cameras = num_cams;
713 cams->cam = (struct uvd *) &cams[1];
714 cams->md_module = md;
715 if (cams->md_module == NULL)
716 warn("%s: module == NULL!", __FUNCTION__);
717 mutex_init(&cams->lock); /* to 1 == available */
718
719 for (i = 0; i < num_cams; i++) {
720 struct uvd *up = &cams->cam[i];
721
722 up->handle = cams;
723
724 /* Allocate user_data separately because of kmalloc's limits */
725 if (num_extra > 0) {
726 up->user_size = num_cams * num_extra;
727 up->user_data = kmalloc(up->user_size, GFP_KERNEL);
728 if (up->user_data == NULL) {
729 err("%s: Failed to allocate user_data (%d. bytes)",
730 __FUNCTION__, up->user_size);
731 while (i) {
732 up = &cams->cam[--i];
733 kfree(up->user_data);
734 }
735 kfree(cams);
736 return -ENOMEM;
737 }
738 dbg("%s: Allocated cams[%d].user_data=$%p (%d. bytes)",
739 __FUNCTION__, i, up->user_data, up->user_size);
740 }
741 }
742
743 /*
744 * Register ourselves with USB stack.
745 */
746 strcpy(cams->drvName, (driverName != NULL) ? driverName : "Unknown");
747 cams->usbdrv.name = cams->drvName;
748 cams->usbdrv.probe = cams->cb.probe;
749 cams->usbdrv.disconnect = cams->cb.disconnect;
750 cams->usbdrv.id_table = id_table;
751
752 /*
753 * Update global handle to usbvideo. This is very important
754 * because probe() can be called before usb_register() returns.
755 * If the handle is not yet updated then the probe() will fail.
756 */
757 *pCams = cams;
758 result = usb_register(&cams->usbdrv);
759 if (result) {
760 for (i = 0; i < num_cams; i++) {
761 struct uvd *up = &cams->cam[i];
762 kfree(up->user_data);
763 }
764 kfree(cams);
765 }
766
767 return result;
768}
769
770EXPORT_SYMBOL(usbvideo_register);
771
772/*
773 * usbvideo_Deregister()
774 *
775 * Procedure frees all usbvideo and user data structures. Be warned that
776 * if you had some dynamically allocated components in ->user field then
777 * you should free them before calling here.
778 */
779void usbvideo_Deregister(struct usbvideo **pCams)
780{
781 struct usbvideo *cams;
782 int i;
783
784 if (pCams == NULL) {
785 err("%s: pCams == NULL", __FUNCTION__);
786 return;
787 }
788 cams = *pCams;
789 if (cams == NULL) {
790 err("%s: cams == NULL", __FUNCTION__);
791 return;
792 }
793
794 dbg("%s: Deregistering %s driver.", __FUNCTION__, cams->drvName);
795 usb_deregister(&cams->usbdrv);
796
797 dbg("%s: Deallocating cams=$%p (%d. cameras)", __FUNCTION__, cams, cams->num_cameras);
798 for (i=0; i < cams->num_cameras; i++) {
799 struct uvd *up = &cams->cam[i];
800 int warning = 0;
801
802 if (up->user_data != NULL) {
803 if (up->user_size <= 0)
804 ++warning;
805 } else {
806 if (up->user_size > 0)
807 ++warning;
808 }
809 if (warning) {
810 err("%s: Warning: user_data=$%p user_size=%d.",
811 __FUNCTION__, up->user_data, up->user_size);
812 } else {
813 dbg("%s: Freeing %d. $%p->user_data=$%p",
814 __FUNCTION__, i, up, up->user_data);
815 kfree(up->user_data);
816 }
817 }
818 /* Whole array was allocated in one chunk */
819 dbg("%s: Freed %d uvd structures",
820 __FUNCTION__, cams->num_cameras);
821 kfree(cams);
822 *pCams = NULL;
823}
824
825EXPORT_SYMBOL(usbvideo_Deregister);
826
827/*
828 * usbvideo_Disconnect()
829 *
830 * This procedure stops all driver activity. Deallocation of
831 * the interface-private structure (pointed by 'ptr') is done now
832 * (if we don't have any open files) or later, when those files
833 * are closed. After that driver should be removable.
834 *
835 * This code handles surprise removal. The uvd->user is a counter which
836 * increments on open() and decrements on close(). If we see here that
837 * this counter is not 0 then we have a client who still has us opened.
838 * We set uvd->remove_pending flag as early as possible, and after that
839 * all access to the camera will gracefully fail. These failures should
840 * prompt client to (eventually) close the video device, and then - in
841 * usbvideo_v4l_close() - we decrement uvd->uvd_used and usage counter.
842 *
843 * History:
844 * 22-Jan-2000 Added polling of MOD_IN_USE to delay removal until all users gone.
845 * 27-Jan-2000 Reworked to allow pending disconnects; see xxx_close()
846 * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
847 * 19-Oct-2000 Moved to usbvideo module.
848 */
849static void usbvideo_Disconnect(struct usb_interface *intf)
850{
851 struct uvd *uvd = usb_get_intfdata (intf);
852 int i;
853
854 if (uvd == NULL) {
855 err("%s($%p): Illegal call.", __FUNCTION__, intf);
856 return;
857 }
858
859 usb_set_intfdata (intf, NULL);
860
861 usbvideo_ClientIncModCount(uvd);
862 if (uvd->debug > 0)
863 info("%s(%p.)", __FUNCTION__, intf);
864
865 mutex_lock(&uvd->lock);
866 uvd->remove_pending = 1; /* Now all ISO data will be ignored */
867
868 /* At this time we ask to cancel outstanding URBs */
869 GET_CALLBACK(uvd, stopDataPump)(uvd);
870
871 for (i=0; i < USBVIDEO_NUMSBUF; i++)
872 usb_free_urb(uvd->sbuf[i].urb);
873
874 usb_put_dev(uvd->dev);
875 uvd->dev = NULL; /* USB device is no more */
876
877 video_unregister_device(&uvd->vdev);
878 if (uvd->debug > 0)
879 info("%s: Video unregistered.", __FUNCTION__);
880
881 if (uvd->user)
882 info("%s: In use, disconnect pending.", __FUNCTION__);
883 else
884 usbvideo_CameraRelease(uvd);
885 mutex_unlock(&uvd->lock);
886 info("USB camera disconnected.");
887
888 usbvideo_ClientDecModCount(uvd);
889}
890
891/*
892 * usbvideo_CameraRelease()
893 *
894 * This code does final release of uvd. This happens
895 * after the device is disconnected -and- all clients
896 * closed their files.
897 *
898 * History:
899 * 27-Jan-2000 Created.
900 */
901static void usbvideo_CameraRelease(struct uvd *uvd)
902{
903 if (uvd == NULL) {
904 err("%s: Illegal call", __FUNCTION__);
905 return;
906 }
907
908 RingQueue_Free(&uvd->dp);
909 if (VALID_CALLBACK(uvd, userFree))
910 GET_CALLBACK(uvd, userFree)(uvd);
911 uvd->uvd_used = 0; /* This is atomic, no need to take mutex */
912}
913
914/*
915 * usbvideo_find_struct()
916 *
917 * This code searches the array of preallocated (static) structures
918 * and returns index of the first one that isn't in use. Returns -1
919 * if there are no free structures.
920 *
921 * History:
922 * 27-Jan-2000 Created.
923 */
924static int usbvideo_find_struct(struct usbvideo *cams)
925{
926 int u, rv = -1;
927
928 if (cams == NULL) {
929 err("No usbvideo handle?");
930 return -1;
931 }
932 mutex_lock(&cams->lock);
933 for (u = 0; u < cams->num_cameras; u++) {
934 struct uvd *uvd = &cams->cam[u];
935 if (!uvd->uvd_used) /* This one is free */
936 {
937 uvd->uvd_used = 1; /* In use now */
938 mutex_init(&uvd->lock); /* to 1 == available */
939 uvd->dev = NULL;
940 rv = u;
941 break;
942 }
943 }
944 mutex_unlock(&cams->lock);
945 return rv;
946}
947
948static struct file_operations usbvideo_fops = {
949 .owner = THIS_MODULE,
950 .open = usbvideo_v4l_open,
951 .release =usbvideo_v4l_close,
952 .read = usbvideo_v4l_read,
953 .mmap = usbvideo_v4l_mmap,
954 .ioctl = usbvideo_v4l_ioctl,
955 .compat_ioctl = v4l_compat_ioctl32,
956 .llseek = no_llseek,
957};
958static const struct video_device usbvideo_template = {
959 .owner = THIS_MODULE,
960 .type = VID_TYPE_CAPTURE,
961 .hardware = VID_HARDWARE_CPIA,
962 .fops = &usbvideo_fops,
963};
964
965struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams)
966{
967 int i, devnum;
968 struct uvd *uvd = NULL;
969
970 if (cams == NULL) {
971 err("No usbvideo handle?");
972 return NULL;
973 }
974
975 devnum = usbvideo_find_struct(cams);
976 if (devnum == -1) {
977 err("IBM USB camera driver: Too many devices!");
978 return NULL;
979 }
980 uvd = &cams->cam[devnum];
981 dbg("Device entry #%d. at $%p", devnum, uvd);
982
983 /* Not relying upon caller we increase module counter ourselves */
984 usbvideo_ClientIncModCount(uvd);
985
986 mutex_lock(&uvd->lock);
987 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
988 uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
989 if (uvd->sbuf[i].urb == NULL) {
990 err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);
991 uvd->uvd_used = 0;
992 uvd = NULL;
993 goto allocate_done;
994 }
995 }
996 uvd->user=0;
997 uvd->remove_pending = 0;
998 uvd->last_error = 0;
999 RingQueue_Initialize(&uvd->dp);
1000
1001 /* Initialize video device structure */
1002 uvd->vdev = usbvideo_template;
1003 sprintf(uvd->vdev.name, "%.20s USB Camera", cams->drvName);
1004 /*
1005 * The client is free to overwrite those because we
1006 * return control to the client's probe function right now.
1007 */
1008allocate_done:
1009 mutex_unlock(&uvd->lock);
1010 usbvideo_ClientDecModCount(uvd);
1011 return uvd;
1012}
1013
1014EXPORT_SYMBOL(usbvideo_AllocateDevice);
1015
1016int usbvideo_RegisterVideoDevice(struct uvd *uvd)
1017{
1018 char tmp1[20], tmp2[20]; /* Buffers for printing */
1019
1020 if (uvd == NULL) {
1021 err("%s: Illegal call.", __FUNCTION__);
1022 return -EINVAL;
1023 }
1024 if (uvd->video_endp == 0) {
1025 info("%s: No video endpoint specified; data pump disabled.", __FUNCTION__);
1026 }
1027 if (uvd->paletteBits == 0) {
1028 err("%s: No palettes specified!", __FUNCTION__);
1029 return -EINVAL;
1030 }
1031 if (uvd->defaultPalette == 0) {
1032 info("%s: No default palette!", __FUNCTION__);
1033 }
1034
1035 uvd->max_frame_size = VIDEOSIZE_X(uvd->canvas) *
1036 VIDEOSIZE_Y(uvd->canvas) * V4L_BYTES_PER_PIXEL;
1037 usbvideo_VideosizeToString(tmp1, sizeof(tmp1), uvd->videosize);
1038 usbvideo_VideosizeToString(tmp2, sizeof(tmp2), uvd->canvas);
1039
1040 if (uvd->debug > 0) {
1041 info("%s: iface=%d. endpoint=$%02x paletteBits=$%08lx",
1042 __FUNCTION__, uvd->iface, uvd->video_endp, uvd->paletteBits);
1043 }
1044 if (video_register_device(&uvd->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
1045 err("%s: video_register_device failed", __FUNCTION__);
1046 return -EPIPE;
1047 }
1048 if (uvd->debug > 1) {
1049 info("%s: video_register_device() successful", __FUNCTION__);
1050 }
1051 if (uvd->dev == NULL) {
1052 err("%s: uvd->dev == NULL", __FUNCTION__);
1053 return -EINVAL;
1054 }
1055
1056 info("%s on /dev/video%d: canvas=%s videosize=%s",
1057 (uvd->handle != NULL) ? uvd->handle->drvName : "???",
1058 uvd->vdev.minor, tmp2, tmp1);
1059
1060 usb_get_dev(uvd->dev);
1061 return 0;
1062}
1063
1064EXPORT_SYMBOL(usbvideo_RegisterVideoDevice);
1065
1066/* ******************************************************************** */
1067
1068static int usbvideo_v4l_mmap(struct file *file, struct vm_area_struct *vma)
1069{
1070 struct uvd *uvd = file->private_data;
1071 unsigned long start = vma->vm_start;
1072 unsigned long size = vma->vm_end-vma->vm_start;
1073 unsigned long page, pos;
1074
1075 if (!CAMERA_IS_OPERATIONAL(uvd))
1076 return -EFAULT;
1077
1078 if (size > (((USBVIDEO_NUMFRAMES * uvd->max_frame_size) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
1079 return -EINVAL;
1080
1081 pos = (unsigned long) uvd->fbuf;
1082 while (size > 0) {
1083 page = vmalloc_to_pfn((void *)pos);
1084 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1085 return -EAGAIN;
1086
1087 start += PAGE_SIZE;
1088 pos += PAGE_SIZE;
1089 if (size > PAGE_SIZE)
1090 size -= PAGE_SIZE;
1091 else
1092 size = 0;
1093 }
1094
1095 return 0;
1096}
1097
1098/*
1099 * usbvideo_v4l_open()
1100 *
1101 * This is part of Video 4 Linux API. The driver can be opened by one
1102 * client only (checks internal counter 'uvdser'). The procedure
1103 * then allocates buffers needed for video processing.
1104 *
1105 * History:
1106 * 22-Jan-2000 Rewrote, moved scratch buffer allocation here. Now the
1107 * camera is also initialized here (once per connect), at
1108 * expense of V4L client (it waits on open() call).
1109 * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
1110 * 24-May-2000 Corrected to prevent race condition (MOD_xxx_USE_COUNT).
1111 */
1112static int usbvideo_v4l_open(struct inode *inode, struct file *file)
1113{
1114 struct video_device *dev = video_devdata(file);
1115 struct uvd *uvd = (struct uvd *) dev;
1116 const int sb_size = FRAMES_PER_DESC * uvd->iso_packet_len;
1117 int i, errCode = 0;
1118
1119 if (uvd->debug > 1)
1120 info("%s($%p)", __FUNCTION__, dev);
1121
1122 usbvideo_ClientIncModCount(uvd);
1123 mutex_lock(&uvd->lock);
1124
1125 if (uvd->user) {
1126 err("%s: Someone tried to open an already opened device!", __FUNCTION__);
1127 errCode = -EBUSY;
1128 } else {
1129 /* Clear statistics */
1130 memset(&uvd->stats, 0, sizeof(uvd->stats));
1131
1132 /* Clean pointers so we know if we allocated something */
1133 for (i=0; i < USBVIDEO_NUMSBUF; i++)
1134 uvd->sbuf[i].data = NULL;
1135
1136 /* Allocate memory for the frame buffers */
1137 uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
1138 uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
1139 RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
1140 if ((uvd->fbuf == NULL) ||
1141 (!RingQueue_IsAllocated(&uvd->dp))) {
1142 err("%s: Failed to allocate fbuf or dp", __FUNCTION__);
1143 errCode = -ENOMEM;
1144 } else {
1145 /* Allocate all buffers */
1146 for (i=0; i < USBVIDEO_NUMFRAMES; i++) {
1147 uvd->frame[i].frameState = FrameState_Unused;
1148 uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);
1149 /*
1150 * Set default sizes in case IOCTL (VIDIOCMCAPTURE)
1151 * is not used (using read() instead).
1152 */
1153 uvd->frame[i].canvas = uvd->canvas;
1154 uvd->frame[i].seqRead_Index = 0;
1155 }
1156 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
1157 uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
1158 if (uvd->sbuf[i].data == NULL) {
1159 errCode = -ENOMEM;
1160 break;
1161 }
1162 }
1163 }
1164 if (errCode != 0) {
1165 /* Have to free all that memory */
1166 if (uvd->fbuf != NULL) {
1167 usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
1168 uvd->fbuf = NULL;
1169 }
1170 RingQueue_Free(&uvd->dp);
1171 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
1172 kfree(uvd->sbuf[i].data);
1173 uvd->sbuf[i].data = NULL;
1174 }
1175 }
1176 }
1177
1178 /* If so far no errors then we shall start the camera */
1179 if (errCode == 0) {
1180 /* Start data pump if we have valid endpoint */
1181 if (uvd->video_endp != 0)
1182 errCode = GET_CALLBACK(uvd, startDataPump)(uvd);
1183 if (errCode == 0) {
1184 if (VALID_CALLBACK(uvd, setupOnOpen)) {
1185 if (uvd->debug > 1)
1186 info("%s: setupOnOpen callback", __FUNCTION__);
1187 errCode = GET_CALLBACK(uvd, setupOnOpen)(uvd);
1188 if (errCode < 0) {
1189 err("%s: setupOnOpen callback failed (%d.).",
1190 __FUNCTION__, errCode);
1191 } else if (uvd->debug > 1) {
1192 info("%s: setupOnOpen callback successful", __FUNCTION__);
1193 }
1194 }
1195 if (errCode == 0) {
1196 uvd->settingsAdjusted = 0;
1197 if (uvd->debug > 1)
1198 info("%s: Open succeeded.", __FUNCTION__);
1199 uvd->user++;
1200 file->private_data = uvd;
1201 }
1202 }
1203 }
1204 mutex_unlock(&uvd->lock);
1205 if (errCode != 0)
1206 usbvideo_ClientDecModCount(uvd);
1207 if (uvd->debug > 0)
1208 info("%s: Returning %d.", __FUNCTION__, errCode);
1209 return errCode;
1210}
1211
1212/*
1213 * usbvideo_v4l_close()
1214 *
1215 * This is part of Video 4 Linux API. The procedure
1216 * stops streaming and deallocates all buffers that were earlier
1217 * allocated in usbvideo_v4l_open().
1218 *
1219 * History:
1220 * 22-Jan-2000 Moved scratch buffer deallocation here.
1221 * 27-Jan-2000 Used USBVIDEO_NUMSBUF as number of URB buffers.
1222 * 24-May-2000 Moved MOD_DEC_USE_COUNT outside of code that can sleep.
1223 */
1224static int usbvideo_v4l_close(struct inode *inode, struct file *file)
1225{
1226 struct video_device *dev = file->private_data;
1227 struct uvd *uvd = (struct uvd *) dev;
1228 int i;
1229
1230 if (uvd->debug > 1)
1231 info("%s($%p)", __FUNCTION__, dev);
1232
1233 mutex_lock(&uvd->lock);
1234 GET_CALLBACK(uvd, stopDataPump)(uvd);
1235 usbvideo_rvfree(uvd->fbuf, uvd->fbuf_size);
1236 uvd->fbuf = NULL;
1237 RingQueue_Free(&uvd->dp);
1238
1239 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
1240 kfree(uvd->sbuf[i].data);
1241 uvd->sbuf[i].data = NULL;
1242 }
1243
1244#if USBVIDEO_REPORT_STATS
1245 usbvideo_ReportStatistics(uvd);
1246#endif
1247
1248 uvd->user--;
1249 if (uvd->remove_pending) {
1250 if (uvd->debug > 0)
1251 info("usbvideo_v4l_close: Final disconnect.");
1252 usbvideo_CameraRelease(uvd);
1253 }
1254 mutex_unlock(&uvd->lock);
1255 usbvideo_ClientDecModCount(uvd);
1256
1257 if (uvd->debug > 1)
1258 info("%s: Completed.", __FUNCTION__);
1259 file->private_data = NULL;
1260 return 0;
1261}
1262
1263/*
1264 * usbvideo_v4l_ioctl()
1265 *
1266 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
1267 *
1268 * History:
1269 * 22-Jan-2000 Corrected VIDIOCSPICT to reject unsupported settings.
1270 */
1271static int usbvideo_v4l_do_ioctl(struct inode *inode, struct file *file,
1272 unsigned int cmd, void *arg)
1273{
1274 struct uvd *uvd = file->private_data;
1275
1276 if (!CAMERA_IS_OPERATIONAL(uvd))
1277 return -EIO;
1278
1279 switch (cmd) {
1280 case VIDIOCGCAP:
1281 {
1282 struct video_capability *b = arg;
1283 *b = uvd->vcap;
1284 return 0;
1285 }
1286 case VIDIOCGCHAN:
1287 {
1288 struct video_channel *v = arg;
1289 *v = uvd->vchan;
1290 return 0;
1291 }
1292 case VIDIOCSCHAN:
1293 {
1294 struct video_channel *v = arg;
1295 if (v->channel != 0)
1296 return -EINVAL;
1297 return 0;
1298 }
1299 case VIDIOCGPICT:
1300 {
1301 struct video_picture *pic = arg;
1302 *pic = uvd->vpic;
1303 return 0;
1304 }
1305 case VIDIOCSPICT:
1306 {
1307 struct video_picture *pic = arg;
1308 /*
1309 * Use temporary 'video_picture' structure to preserve our
1310 * own settings (such as color depth, palette) that we
1311 * aren't allowing everyone (V4L client) to change.
1312 */
1313 uvd->vpic.brightness = pic->brightness;
1314 uvd->vpic.hue = pic->hue;
1315 uvd->vpic.colour = pic->colour;
1316 uvd->vpic.contrast = pic->contrast;
1317 uvd->settingsAdjusted = 0; /* Will force new settings */
1318 return 0;
1319 }
1320 case VIDIOCSWIN:
1321 {
1322 struct video_window *vw = arg;
1323
1324 if(VALID_CALLBACK(uvd, setVideoMode)) {
1325 return GET_CALLBACK(uvd, setVideoMode)(uvd, vw);
1326 }
1327
1328 if (vw->flags)
1329 return -EINVAL;
1330 if (vw->clipcount)
1331 return -EINVAL;
1332 if (vw->width != VIDEOSIZE_X(uvd->canvas))
1333 return -EINVAL;
1334 if (vw->height != VIDEOSIZE_Y(uvd->canvas))
1335 return -EINVAL;
1336
1337 return 0;
1338 }
1339 case VIDIOCGWIN:
1340 {
1341 struct video_window *vw = arg;
1342
1343 vw->x = 0;
1344 vw->y = 0;
1345 vw->width = VIDEOSIZE_X(uvd->videosize);
1346 vw->height = VIDEOSIZE_Y(uvd->videosize);
1347 vw->chromakey = 0;
1348 if (VALID_CALLBACK(uvd, getFPS))
1349 vw->flags = GET_CALLBACK(uvd, getFPS)(uvd);
1350 else
1351 vw->flags = 10; /* FIXME: do better! */
1352 return 0;
1353 }
1354 case VIDIOCGMBUF:
1355 {
1356 struct video_mbuf *vm = arg;
1357 int i;
1358
1359 memset(vm, 0, sizeof(*vm));
1360 vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES;
1361 vm->frames = USBVIDEO_NUMFRAMES;
1362 for(i = 0; i < USBVIDEO_NUMFRAMES; i++)
1363 vm->offsets[i] = i * uvd->max_frame_size;
1364
1365 return 0;
1366 }
1367 case VIDIOCMCAPTURE:
1368 {
1369 struct video_mmap *vm = arg;
1370
1371 if (uvd->debug >= 1) {
1372 info("VIDIOCMCAPTURE: frame=%d. size=%dx%d, format=%d.",
1373 vm->frame, vm->width, vm->height, vm->format);
1374 }
1375 /*
1376 * Check if the requested size is supported. If the requestor
1377 * requests too big a frame then we may be tricked into accessing
1378 * outside of own preallocated frame buffer (in uvd->frame).
1379 * This will cause oops or a security hole. Theoretically, we
1380 * could only clamp the size down to acceptable bounds, but then
1381 * we'd need to figure out how to insert our smaller buffer into
1382 * larger caller's buffer... this is not an easy question. So we
1383 * here just flatly reject too large requests, assuming that the
1384 * caller will resubmit with smaller size. Callers should know
1385 * what size we support (returned by VIDIOCGCAP). However vidcat,
1386 * for one, does not care and allows to ask for any size.
1387 */
1388 if ((vm->width > VIDEOSIZE_X(uvd->canvas)) ||
1389 (vm->height > VIDEOSIZE_Y(uvd->canvas))) {
1390 if (uvd->debug > 0) {
1391 info("VIDIOCMCAPTURE: Size=%dx%d too large; "
1392 "allowed only up to %ldx%ld", vm->width, vm->height,
1393 VIDEOSIZE_X(uvd->canvas), VIDEOSIZE_Y(uvd->canvas));
1394 }
1395 return -EINVAL;
1396 }
1397 /* Check if the palette is supported */
1398 if (((1L << vm->format) & uvd->paletteBits) == 0) {
1399 if (uvd->debug > 0) {
1400 info("VIDIOCMCAPTURE: format=%d. not supported"
1401 " (paletteBits=$%08lx)",
1402 vm->format, uvd->paletteBits);
1403 }
1404 return -EINVAL;
1405 }
1406 if ((vm->frame < 0) || (vm->frame >= USBVIDEO_NUMFRAMES)) {
1407 err("VIDIOCMCAPTURE: vm.frame=%d. !E [0-%d]", vm->frame, USBVIDEO_NUMFRAMES-1);
1408 return -EINVAL;
1409 }
1410 if (uvd->frame[vm->frame].frameState == FrameState_Grabbing) {
1411 /* Not an error - can happen */
1412 }
1413 uvd->frame[vm->frame].request = VIDEOSIZE(vm->width, vm->height);
1414 uvd->frame[vm->frame].palette = vm->format;
1415
1416 /* Mark it as ready */
1417 uvd->frame[vm->frame].frameState = FrameState_Ready;
1418
1419 return usbvideo_NewFrame(uvd, vm->frame);
1420 }
1421 case VIDIOCSYNC:
1422 {
1423 int *frameNum = arg;
1424 int ret;
1425
1426 if (*frameNum < 0 || *frameNum >= USBVIDEO_NUMFRAMES)
1427 return -EINVAL;
1428
1429 if (uvd->debug >= 1)
1430 info("VIDIOCSYNC: syncing to frame %d.", *frameNum);
1431 if (uvd->flags & FLAGS_NO_DECODING)
1432 ret = usbvideo_GetFrame(uvd, *frameNum);
1433 else if (VALID_CALLBACK(uvd, getFrame)) {
1434 ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum);
1435 if ((ret < 0) && (uvd->debug >= 1)) {
1436 err("VIDIOCSYNC: getFrame() returned %d.", ret);
1437 }
1438 } else {
1439 err("VIDIOCSYNC: getFrame is not set");
1440 ret = -EFAULT;
1441 }
1442
1443 /*
1444 * The frame is in FrameState_Done_Hold state. Release it
1445 * right now because its data is already mapped into
1446 * the user space and it's up to the application to
1447 * make use of it until it asks for another frame.
1448 */
1449 uvd->frame[*frameNum].frameState = FrameState_Unused;
1450 return ret;
1451 }
1452 case VIDIOCGFBUF:
1453 {
1454 struct video_buffer *vb = arg;
1455
1456 memset(vb, 0, sizeof(*vb));
1457 return 0;
1458 }
1459 case VIDIOCKEY:
1460 return 0;
1461
1462 case VIDIOCCAPTURE:
1463 return -EINVAL;
1464
1465 case VIDIOCSFBUF:
1466
1467 case VIDIOCGTUNER:
1468 case VIDIOCSTUNER:
1469
1470 case VIDIOCGFREQ:
1471 case VIDIOCSFREQ:
1472
1473 case VIDIOCGAUDIO:
1474 case VIDIOCSAUDIO:
1475 return -EINVAL;
1476
1477 default:
1478 return -ENOIOCTLCMD;
1479 }
1480 return 0;
1481}
1482
1483static int usbvideo_v4l_ioctl(struct inode *inode, struct file *file,
1484 unsigned int cmd, unsigned long arg)
1485{
1486 return video_usercopy(inode, file, cmd, arg, usbvideo_v4l_do_ioctl);
1487}
1488
1489/*
1490 * usbvideo_v4l_read()
1491 *
1492 * This is mostly boring stuff. We simply ask for a frame and when it
1493 * arrives copy all the video data from it into user space. There is
1494 * no obvious need to override this method.
1495 *
1496 * History:
1497 * 20-Oct-2000 Created.
1498 * 01-Nov-2000 Added mutex (uvd->lock).
1499 */
1500static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
1501 size_t count, loff_t *ppos)
1502{
1503 struct uvd *uvd = file->private_data;
1504 int noblock = file->f_flags & O_NONBLOCK;
1505 int frmx = -1, i;
1506 struct usbvideo_frame *frame;
1507
1508 if (!CAMERA_IS_OPERATIONAL(uvd) || (buf == NULL))
1509 return -EFAULT;
1510
1511 if (uvd->debug >= 1)
1512 info("%s: %Zd. bytes, noblock=%d.", __FUNCTION__, count, noblock);
1513
1514 mutex_lock(&uvd->lock);
1515
1516 /* See if a frame is completed, then use it. */
1517 for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
1518 if ((uvd->frame[i].frameState == FrameState_Done) ||
1519 (uvd->frame[i].frameState == FrameState_Done_Hold) ||
1520 (uvd->frame[i].frameState == FrameState_Error)) {
1521 frmx = i;
1522 break;
1523 }
1524 }
1525
1526 /* FIXME: If we don't start a frame here then who ever does? */
1527 if (noblock && (frmx == -1)) {
1528 count = -EAGAIN;
1529 goto read_done;
1530 }
1531
1532 /*
1533 * If no FrameState_Done, look for a FrameState_Grabbing state.
1534 * See if a frame is in process (grabbing), then use it.
1535 * We will need to wait until it becomes cooked, of course.
1536 */
1537 if (frmx == -1) {
1538 for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
1539 if (uvd->frame[i].frameState == FrameState_Grabbing) {
1540 frmx = i;
1541 break;
1542 }
1543 }
1544 }
1545
1546 /*
1547 * If no frame is active, start one. We don't care which one
1548 * it will be, so #0 is as good as any.
1549 * In read access mode we don't have convenience of VIDIOCMCAPTURE
1550 * to specify the requested palette (video format) on per-frame
1551 * basis. This means that we have to return data in -some- format
1552 * and just hope that the client knows what to do with it.
1553 * The default format is configured in uvd->defaultPalette field
1554 * as one of VIDEO_PALETTE_xxx values. We stuff it into the new
1555 * frame and initiate the frame filling process.
1556 */
1557 if (frmx == -1) {
1558 if (uvd->defaultPalette == 0) {
1559 err("%s: No default palette; don't know what to do!", __FUNCTION__);
1560 count = -EFAULT;
1561 goto read_done;
1562 }
1563 frmx = 0;
1564 /*
1565 * We have no per-frame control over video size.
1566 * Therefore we only can use whatever size was
1567 * specified as default.
1568 */
1569 uvd->frame[frmx].request = uvd->videosize;
1570 uvd->frame[frmx].palette = uvd->defaultPalette;
1571 uvd->frame[frmx].frameState = FrameState_Ready;
1572 usbvideo_NewFrame(uvd, frmx);
1573 /* Now frame 0 is supposed to start filling... */
1574 }
1575
1576 /*
1577 * Get a pointer to the active frame. It is either previously
1578 * completed frame or frame in progress but not completed yet.
1579 */
1580 frame = &uvd->frame[frmx];
1581
1582 /*
1583 * Sit back & wait until the frame gets filled and postprocessed.
1584 * If we fail to get the picture [in time] then return the error.
1585 * In this call we specify that we want the frame to be waited for,
1586 * postprocessed and switched into FrameState_Done_Hold state. This
1587 * state is used to hold the frame as "fully completed" between
1588 * subsequent partial reads of the same frame.
1589 */
1590 if (frame->frameState != FrameState_Done_Hold) {
1591 long rv = -EFAULT;
1592 if (uvd->flags & FLAGS_NO_DECODING)
1593 rv = usbvideo_GetFrame(uvd, frmx);
1594 else if (VALID_CALLBACK(uvd, getFrame))
1595 rv = GET_CALLBACK(uvd, getFrame)(uvd, frmx);
1596 else
1597 err("getFrame is not set");
1598 if ((rv != 0) || (frame->frameState != FrameState_Done_Hold)) {
1599 count = rv;
1600 goto read_done;
1601 }
1602 }
1603
1604 /*
1605 * Copy bytes to user space. We allow for partial reads, which
1606 * means that the user application can request read less than
1607 * the full frame size. It is up to the application to issue
1608 * subsequent calls until entire frame is read.
1609 *
1610 * First things first, make sure we don't copy more than we
1611 * have - even if the application wants more. That would be
1612 * a big security embarassment!
1613 */
1614 if ((count + frame->seqRead_Index) > frame->seqRead_Length)
1615 count = frame->seqRead_Length - frame->seqRead_Index;
1616
1617 /*
1618 * Copy requested amount of data to user space. We start
1619 * copying from the position where we last left it, which
1620 * will be zero for a new frame (not read before).
1621 */
1622 if (copy_to_user(buf, frame->data + frame->seqRead_Index, count)) {
1623 count = -EFAULT;
1624 goto read_done;
1625 }
1626
1627 /* Update last read position */
1628 frame->seqRead_Index += count;
1629 if (uvd->debug >= 1) {
1630 err("%s: {copy} count used=%Zd, new seqRead_Index=%ld",
1631 __FUNCTION__, count, frame->seqRead_Index);
1632 }
1633
1634 /* Finally check if the frame is done with and "release" it */
1635 if (frame->seqRead_Index >= frame->seqRead_Length) {
1636 /* All data has been read */
1637 frame->seqRead_Index = 0;
1638
1639 /* Mark it as available to be used again. */
1640 uvd->frame[frmx].frameState = FrameState_Unused;
1641 if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
1642 err("%s: usbvideo_NewFrame failed.", __FUNCTION__);
1643 }
1644 }
1645read_done:
1646 mutex_unlock(&uvd->lock);
1647 return count;
1648}
1649
1650/*
1651 * Make all of the blocks of data contiguous
1652 */
1653static int usbvideo_CompressIsochronous(struct uvd *uvd, struct urb *urb)
1654{
1655 char *cdata;
1656 int i, totlen = 0;
1657
1658 for (i = 0; i < urb->number_of_packets; i++) {
1659 int n = urb->iso_frame_desc[i].actual_length;
1660 int st = urb->iso_frame_desc[i].status;
1661
1662 cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
1663
1664 /* Detect and ignore errored packets */
1665 if (st < 0) {
1666 if (uvd->debug >= 1)
1667 err("Data error: packet=%d. len=%d. status=%d.", i, n, st);
1668 uvd->stats.iso_err_count++;
1669 continue;
1670 }
1671
1672 /* Detect and ignore empty packets */
1673 if (n <= 0) {
1674 uvd->stats.iso_skip_count++;
1675 continue;
1676 }
1677 totlen += n; /* Little local accounting */
1678 RingQueue_Enqueue(&uvd->dp, cdata, n);
1679 }
1680 return totlen;
1681}
1682
1683static void usbvideo_IsocIrq(struct urb *urb, struct pt_regs *regs)
1684{
1685 int i, ret, len;
1686 struct uvd *uvd = urb->context;
1687
1688 /* We don't want to do anything if we are about to be removed! */
1689 if (!CAMERA_IS_OPERATIONAL(uvd))
1690 return;
1691#if 0
1692 if (urb->actual_length > 0) {
1693 info("urb=$%p status=%d. errcount=%d. length=%d.",
1694 urb, urb->status, urb->error_count, urb->actual_length);
1695 } else {
1696 static int c = 0;
1697 if (c++ % 100 == 0)
1698 info("No Isoc data");
1699 }
1700#endif
1701
1702 if (!uvd->streaming) {
1703 if (uvd->debug >= 1)
1704 info("Not streaming, but interrupt!");
1705 return;
1706 }
1707
1708 uvd->stats.urb_count++;
1709 if (urb->actual_length <= 0)
1710 goto urb_done_with;
1711
1712 /* Copy the data received into ring queue */
1713 len = usbvideo_CompressIsochronous(uvd, urb);
1714 uvd->stats.urb_length = len;
1715 if (len <= 0)
1716 goto urb_done_with;
1717
1718 /* Here we got some data */
1719 uvd->stats.data_count += len;
1720 RingQueue_WakeUpInterruptible(&uvd->dp);
1721
1722urb_done_with:
1723 for (i = 0; i < FRAMES_PER_DESC; i++) {
1724 urb->iso_frame_desc[i].status = 0;
1725 urb->iso_frame_desc[i].actual_length = 0;
1726 }
1727 urb->status = 0;
1728 urb->dev = uvd->dev;
1729 ret = usb_submit_urb (urb, GFP_KERNEL);
1730 if(ret)
1731 err("usb_submit_urb error (%d)", ret);
1732 return;
1733}
1734
1735/*
1736 * usbvideo_StartDataPump()
1737 *
1738 * History:
1739 * 27-Jan-2000 Used ibmcam->iface, ibmcam->ifaceAltActive instead
1740 * of hardcoded values. Simplified by using for loop,
1741 * allowed any number of URBs.
1742 */
1743static int usbvideo_StartDataPump(struct uvd *uvd)
1744{
1745 struct usb_device *dev = uvd->dev;
1746 int i, errFlag;
1747
1748 if (uvd->debug > 1)
1749 info("%s($%p)", __FUNCTION__, uvd);
1750
1751 if (!CAMERA_IS_OPERATIONAL(uvd)) {
1752 err("%s: Camera is not operational", __FUNCTION__);
1753 return -EFAULT;
1754 }
1755 uvd->curframe = -1;
1756
1757 /* Alternate interface 1 is is the biggest frame size */
1758 i = usb_set_interface(dev, uvd->iface, uvd->ifaceAltActive);
1759 if (i < 0) {
1760 err("%s: usb_set_interface error", __FUNCTION__);
1761 uvd->last_error = i;
1762 return -EBUSY;
1763 }
1764 if (VALID_CALLBACK(uvd, videoStart))
1765 GET_CALLBACK(uvd, videoStart)(uvd);
1766 else
1767 err("%s: videoStart not set", __FUNCTION__);
1768
1769 /* We double buffer the Iso lists */
1770 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
1771 int j, k;
1772 struct urb *urb = uvd->sbuf[i].urb;
1773 urb->dev = dev;
1774 urb->context = uvd;
1775 urb->pipe = usb_rcvisocpipe(dev, uvd->video_endp);
1776 urb->interval = 1;
1777 urb->transfer_flags = URB_ISO_ASAP;
1778 urb->transfer_buffer = uvd->sbuf[i].data;
1779 urb->complete = usbvideo_IsocIrq;
1780 urb->number_of_packets = FRAMES_PER_DESC;
1781 urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
1782 for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
1783 urb->iso_frame_desc[j].offset = k;
1784 urb->iso_frame_desc[j].length = uvd->iso_packet_len;
1785 }
1786 }
1787
1788 /* Submit all URBs */
1789 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
1790 errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
1791 if (errFlag)
1792 err("%s: usb_submit_isoc(%d) ret %d", __FUNCTION__, i, errFlag);
1793 }
1794
1795 uvd->streaming = 1;
1796 if (uvd->debug > 1)
1797 info("%s: streaming=1 video_endp=$%02x", __FUNCTION__, uvd->video_endp);
1798 return 0;
1799}
1800
1801/*
1802 * usbvideo_StopDataPump()
1803 *
1804 * This procedure stops streaming and deallocates URBs. Then it
1805 * activates zero-bandwidth alt. setting of the video interface.
1806 *
1807 * History:
1808 * 22-Jan-2000 Corrected order of actions to work after surprise removal.
1809 * 27-Jan-2000 Used uvd->iface, uvd->ifaceAltInactive instead of hardcoded values.
1810 */
1811static void usbvideo_StopDataPump(struct uvd *uvd)
1812{
1813 int i, j;
1814
1815 if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
1816 return;
1817
1818 if (uvd->debug > 1)
1819 info("%s($%p)", __FUNCTION__, uvd);
1820
1821 /* Unschedule all of the iso td's */
1822 for (i=0; i < USBVIDEO_NUMSBUF; i++) {
1823 usb_kill_urb(uvd->sbuf[i].urb);
1824 }
1825 if (uvd->debug > 1)
1826 info("%s: streaming=0", __FUNCTION__);
1827 uvd->streaming = 0;
1828
1829 if (!uvd->remove_pending) {
1830 /* Invoke minidriver's magic to stop the camera */
1831 if (VALID_CALLBACK(uvd, videoStop))
1832 GET_CALLBACK(uvd, videoStop)(uvd);
1833 else
1834 err("%s: videoStop not set", __FUNCTION__);
1835
1836 /* Set packet size to 0 */
1837 j = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltInactive);
1838 if (j < 0) {
1839 err("%s: usb_set_interface() error %d.", __FUNCTION__, j);
1840 uvd->last_error = j;
1841 }
1842 }
1843}
1844
1845/*
1846 * usbvideo_NewFrame()
1847 *
1848 * History:
1849 * 29-Mar-00 Added copying of previous frame into the current one.
1850 * 6-Aug-00 Added model 3 video sizes, removed redundant width, height.
1851 */
1852static int usbvideo_NewFrame(struct uvd *uvd, int framenum)
1853{
1854 struct usbvideo_frame *frame;
1855 int n;
1856
1857 if (uvd->debug > 1)
1858 info("usbvideo_NewFrame($%p,%d.)", uvd, framenum);
1859
1860 /* If we're not grabbing a frame right now and the other frame is */
1861 /* ready to be grabbed into, then use it instead */
1862 if (uvd->curframe != -1)
1863 return 0;
1864
1865 /* If necessary we adjust picture settings between frames */
1866 if (!uvd->settingsAdjusted) {
1867 if (VALID_CALLBACK(uvd, adjustPicture))
1868 GET_CALLBACK(uvd, adjustPicture)(uvd);
1869 uvd->settingsAdjusted = 1;
1870 }
1871
1872 n = (framenum + 1) % USBVIDEO_NUMFRAMES;
1873 if (uvd->frame[n].frameState == FrameState_Ready)
1874 framenum = n;
1875
1876 frame = &uvd->frame[framenum];
1877
1878 frame->frameState = FrameState_Grabbing;
1879 frame->scanstate = ScanState_Scanning;
1880 frame->seqRead_Length = 0; /* Accumulated in xxx_parse_data() */
1881 frame->deinterlace = Deinterlace_None;
1882 frame->flags = 0; /* No flags yet, up to minidriver (or us) to set them */
1883 uvd->curframe = framenum;
1884
1885 /*
1886 * Normally we would want to copy previous frame into the current one
1887 * before we even start filling it with data; this allows us to stop
1888 * filling at any moment; top portion of the frame will be new and
1889 * bottom portion will stay as it was in previous frame. If we don't
1890 * do that then missing chunks of video stream will result in flickering
1891 * portions of old data whatever it was before.
1892 *
1893 * If we choose not to copy previous frame (to, for example, save few
1894 * bus cycles - the frame can be pretty large!) then we have an option
1895 * to clear the frame before using. If we experience losses in this
1896 * mode then missing picture will be black (no flickering).
1897 *
1898 * Finally, if user chooses not to clean the current frame before
1899 * filling it with data then the old data will be visible if we fail
1900 * to refill entire frame with new data.
1901 */
1902 if (!(uvd->flags & FLAGS_SEPARATE_FRAMES)) {
1903 /* This copies previous frame into this one to mask losses */
1904 int prev = (framenum - 1 + USBVIDEO_NUMFRAMES) % USBVIDEO_NUMFRAMES;
1905 memmove(frame->data, uvd->frame[prev].data, uvd->max_frame_size);
1906 } else {
1907 if (uvd->flags & FLAGS_CLEAN_FRAMES) {
1908 /* This provides a "clean" frame but slows things down */
1909 memset(frame->data, 0, uvd->max_frame_size);
1910 }
1911 }
1912 return 0;
1913}
1914
1915/*
1916 * usbvideo_CollectRawData()
1917 *
1918 * This procedure can be used instead of 'processData' callback if you
1919 * only want to dump the raw data from the camera into the output
1920 * device (frame buffer). You can look at it with V4L client, but the
1921 * image will be unwatchable. The main purpose of this code and of the
1922 * mode FLAGS_NO_DECODING is debugging and capturing of datastreams from
1923 * new, unknown cameras. This procedure will be automatically invoked
1924 * instead of the specified callback handler when uvd->flags has bit
1925 * FLAGS_NO_DECODING set. Therefore, any regular build of any driver
1926 * based on usbvideo can use this feature at any time.
1927 */
1928static void usbvideo_CollectRawData(struct uvd *uvd, struct usbvideo_frame *frame)
1929{
1930 int n;
1931
1932 assert(uvd != NULL);
1933 assert(frame != NULL);
1934
1935 /* Try to move data from queue into frame buffer */
1936 n = RingQueue_GetLength(&uvd->dp);
1937 if (n > 0) {
1938 int m;
1939 /* See how much space we have left */
1940 m = uvd->max_frame_size - frame->seqRead_Length;
1941 if (n > m)
1942 n = m;
1943 /* Now move that much data into frame buffer */
1944 RingQueue_Dequeue(
1945 &uvd->dp,
1946 frame->data + frame->seqRead_Length,
1947 m);
1948 frame->seqRead_Length += m;
1949 }
1950 /* See if we filled the frame */
1951 if (frame->seqRead_Length >= uvd->max_frame_size) {
1952 frame->frameState = FrameState_Done;
1953 uvd->curframe = -1;
1954 uvd->stats.frame_num++;
1955 }
1956}
1957
1958static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
1959{
1960 struct usbvideo_frame *frame = &uvd->frame[frameNum];
1961
1962 if (uvd->debug >= 2)
1963 info("%s($%p,%d.)", __FUNCTION__, uvd, frameNum);
1964
1965 switch (frame->frameState) {
1966 case FrameState_Unused:
1967 if (uvd->debug >= 2)
1968 info("%s: FrameState_Unused", __FUNCTION__);
1969 return -EINVAL;
1970 case FrameState_Ready:
1971 case FrameState_Grabbing:
1972 case FrameState_Error:
1973 {
1974 int ntries, signalPending;
1975 redo:
1976 if (!CAMERA_IS_OPERATIONAL(uvd)) {
1977 if (uvd->debug >= 2)
1978 info("%s: Camera is not operational (1)", __FUNCTION__);
1979 return -EIO;
1980 }
1981 ntries = 0;
1982 do {
1983 RingQueue_InterruptibleSleepOn(&uvd->dp);
1984 signalPending = signal_pending(current);
1985 if (!CAMERA_IS_OPERATIONAL(uvd)) {
1986 if (uvd->debug >= 2)
1987 info("%s: Camera is not operational (2)", __FUNCTION__);
1988 return -EIO;
1989 }
1990 assert(uvd->fbuf != NULL);
1991 if (signalPending) {
1992 if (uvd->debug >= 2)
1993 info("%s: Signal=$%08x", __FUNCTION__, signalPending);
1994 if (uvd->flags & FLAGS_RETRY_VIDIOCSYNC) {
1995 usbvideo_TestPattern(uvd, 1, 0);
1996 uvd->curframe = -1;
1997 uvd->stats.frame_num++;
1998 if (uvd->debug >= 2)
1999 info("%s: Forced test pattern screen", __FUNCTION__);
2000 return 0;
2001 } else {
2002 /* Standard answer: Interrupted! */
2003 if (uvd->debug >= 2)
2004 info("%s: Interrupted!", __FUNCTION__);
2005 return -EINTR;
2006 }
2007 } else {
2008 /* No signals - we just got new data in dp queue */
2009 if (uvd->flags & FLAGS_NO_DECODING)
2010 usbvideo_CollectRawData(uvd, frame);
2011 else if (VALID_CALLBACK(uvd, processData))
2012 GET_CALLBACK(uvd, processData)(uvd, frame);
2013 else
2014 err("%s: processData not set", __FUNCTION__);
2015 }
2016 } while (frame->frameState == FrameState_Grabbing);
2017 if (uvd->debug >= 2) {
2018 info("%s: Grabbing done; state=%d. (%lu. bytes)",
2019 __FUNCTION__, frame->frameState, frame->seqRead_Length);
2020 }
2021 if (frame->frameState == FrameState_Error) {
2022 int ret = usbvideo_NewFrame(uvd, frameNum);
2023 if (ret < 0) {
2024 err("%s: usbvideo_NewFrame() failed (%d.)", __FUNCTION__, ret);
2025 return ret;
2026 }
2027 goto redo;
2028 }
2029 /* Note that we fall through to meet our destiny below */
2030 }
2031 case FrameState_Done:
2032 /*
2033 * Do all necessary postprocessing of data prepared in
2034 * "interrupt" code and the collecting code above. The
2035 * frame gets marked as FrameState_Done by queue parsing code.
2036 * This status means that we collected enough data and
2037 * most likely processed it as we went through. However
2038 * the data may need postprocessing, such as deinterlacing
2039 * or picture adjustments implemented in software (horror!)
2040 *
2041 * As soon as the frame becomes "final" it gets promoted to
2042 * FrameState_Done_Hold status where it will remain until the
2043 * caller consumed all the video data from the frame. Then
2044 * the empty shell of ex-frame is thrown out for dogs to eat.
2045 * But we, worried about pets, will recycle the frame!
2046 */
2047 uvd->stats.frame_num++;
2048 if ((uvd->flags & FLAGS_NO_DECODING) == 0) {
2049 if (VALID_CALLBACK(uvd, postProcess))
2050 GET_CALLBACK(uvd, postProcess)(uvd, frame);
2051 if (frame->flags & USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST)
2052 usbvideo_SoftwareContrastAdjustment(uvd, frame);
2053 }
2054 frame->frameState = FrameState_Done_Hold;
2055 if (uvd->debug >= 2)
2056 info("%s: Entered FrameState_Done_Hold state.", __FUNCTION__);
2057 return 0;
2058
2059 case FrameState_Done_Hold:
2060 /*
2061 * We stay in this state indefinitely until someone external,
2062 * like ioctl() or read() call finishes digesting the frame
2063 * data. Then it will mark the frame as FrameState_Unused and
2064 * it will be released back into the wild to roam freely.
2065 */
2066 if (uvd->debug >= 2)
2067 info("%s: FrameState_Done_Hold state.", __FUNCTION__);
2068 return 0;
2069 }
2070
2071 /* Catch-all for other cases. We shall not be here. */
2072 err("%s: Invalid state %d.", __FUNCTION__, frame->frameState);
2073 frame->frameState = FrameState_Unused;
2074 return 0;
2075}
2076
2077/*
2078 * usbvideo_DeinterlaceFrame()
2079 *
2080 * This procedure deinterlaces the given frame. Some cameras produce
2081 * only half of scanlines - sometimes only even lines, sometimes only
2082 * odd lines. The deinterlacing method is stored in frame->deinterlace
2083 * variable.
2084 *
2085 * Here we scan the frame vertically and replace missing scanlines with
2086 * average between surrounding ones - before and after. If we have no
2087 * line above then we just copy next line. Similarly, if we need to
2088 * create a last line then preceding line is used.
2089 */
2090void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame)
2091{
2092 if ((uvd == NULL) || (frame == NULL))
2093 return;
2094
2095 if ((frame->deinterlace == Deinterlace_FillEvenLines) ||
2096 (frame->deinterlace == Deinterlace_FillOddLines))
2097 {
2098 const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
2099 int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1;
2100
2101 for (; i < VIDEOSIZE_Y(frame->request); i += 2) {
2102 const unsigned char *fs1, *fs2;
2103 unsigned char *fd;
2104 int ip, in, j; /* Previous and next lines */
2105
2106 /*
2107 * Need to average lines before and after 'i'.
2108 * If we go out of bounds seeking those lines then
2109 * we point back to existing line.
2110 */
2111 ip = i - 1; /* First, get rough numbers */
2112 in = i + 1;
2113
2114 /* Now validate */
2115 if (ip < 0)
2116 ip = in;
2117 if (in >= VIDEOSIZE_Y(frame->request))
2118 in = ip;
2119
2120 /* Sanity check */
2121 if ((ip < 0) || (in < 0) ||
2122 (ip >= VIDEOSIZE_Y(frame->request)) ||
2123 (in >= VIDEOSIZE_Y(frame->request)))
2124 {
2125 err("Error: ip=%d. in=%d. req.height=%ld.",
2126 ip, in, VIDEOSIZE_Y(frame->request));
2127 break;
2128 }
2129
2130 /* Now we need to average lines 'ip' and 'in' to produce line 'i' */
2131 fs1 = frame->data + (v4l_linesize * ip);
2132 fs2 = frame->data + (v4l_linesize * in);
2133 fd = frame->data + (v4l_linesize * i);
2134
2135 /* Average lines around destination */
2136 for (j=0; j < v4l_linesize; j++) {
2137 fd[j] = (unsigned char)((((unsigned) fs1[j]) +
2138 ((unsigned)fs2[j])) >> 1);
2139 }
2140 }
2141 }
2142
2143 /* Optionally display statistics on the screen */
2144 if (uvd->flags & FLAGS_OVERLAY_STATS)
2145 usbvideo_OverlayStats(uvd, frame);
2146}
2147
2148EXPORT_SYMBOL(usbvideo_DeinterlaceFrame);
2149
2150/*
2151 * usbvideo_SoftwareContrastAdjustment()
2152 *
2153 * This code adjusts the contrast of the frame, assuming RGB24 format.
2154 * As most software image processing, this job is CPU-intensive.
2155 * Get a camera that supports hardware adjustment!
2156 *
2157 * History:
2158 * 09-Feb-2001 Created.
2159 */
2160static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
2161 struct usbvideo_frame *frame)
2162{
2163 int i, j, v4l_linesize;
2164 signed long adj;
2165 const int ccm = 128; /* Color correction median - see below */
2166
2167 if ((uvd == NULL) || (frame == NULL)) {
2168 err("%s: Illegal call.", __FUNCTION__);
2169 return;
2170 }
2171 adj = (uvd->vpic.contrast - 0x8000) >> 8; /* -128..+127 = -ccm..+(ccm-1)*/
2172 RESTRICT_TO_RANGE(adj, -ccm, ccm+1);
2173 if (adj == 0) {
2174 /* In rare case of no adjustment */
2175 return;
2176 }
2177 v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
2178 for (i=0; i < VIDEOSIZE_Y(frame->request); i++) {
2179 unsigned char *fd = frame->data + (v4l_linesize * i);
2180 for (j=0; j < v4l_linesize; j++) {
2181 signed long v = (signed long) fd[j];
2182 /* Magnify up to 2 times, reduce down to zero */
2183 v = 128 + ((ccm + adj) * (v - 128)) / ccm;
2184 RESTRICT_TO_RANGE(v, 0, 0xFF); /* Must flatten tails */
2185 fd[j] = (unsigned char) v;
2186 }
2187 }
2188}
2189
2190MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h
new file mode 100644
index 000000000000..135433c2680a
--- /dev/null
+++ b/drivers/media/video/usbvideo/usbvideo.h
@@ -0,0 +1,394 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2, or (at your option)
5 * any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16#ifndef usbvideo_h
17#define usbvideo_h
18
19#include <linux/config.h>
20#include <linux/videodev.h>
21#include <linux/usb.h>
22#include <linux/mutex.h>
23
24/* Most helpful debugging aid */
25#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__))))
26
27#define USBVIDEO_REPORT_STATS 1 /* Set to 0 to block statistics on close */
28
29/* Bit flags (options) */
30#define FLAGS_RETRY_VIDIOCSYNC (1 << 0)
31#define FLAGS_MONOCHROME (1 << 1)
32#define FLAGS_DISPLAY_HINTS (1 << 2)
33#define FLAGS_OVERLAY_STATS (1 << 3)
34#define FLAGS_FORCE_TESTPATTERN (1 << 4)
35#define FLAGS_SEPARATE_FRAMES (1 << 5)
36#define FLAGS_CLEAN_FRAMES (1 << 6)
37#define FLAGS_NO_DECODING (1 << 7)
38
39/* Bit flags for frames (apply to the frame where they are specified) */
40#define USBVIDEO_FRAME_FLAG_SOFTWARE_CONTRAST (1 << 0)
41
42/* Camera capabilities (maximum) */
43#define CAMERA_URB_FRAMES 32
44#define CAMERA_MAX_ISO_PACKET 1023 /* 1022 actually sent by camera */
45#define FRAMES_PER_DESC (CAMERA_URB_FRAMES)
46#define FRAME_SIZE_PER_DESC (CAMERA_MAX_ISO_PACKET)
47
48/* This macro restricts an int variable to an inclusive range */
49#define RESTRICT_TO_RANGE(v,mi,ma) { if ((v) < (mi)) (v) = (mi); else if ((v) > (ma)) (v) = (ma); }
50
51#define V4L_BYTES_PER_PIXEL 3 /* Because we produce RGB24 */
52
53/*
54 * Use this macro to construct constants for different video sizes.
55 * We have to deal with different video sizes that have to be
56 * configured in the device or compared against when we receive
57 * a data. Normally one would define a bunch of VIDEOSIZE_x_by_y
58 * #defines and that's the end of story. However this solution
59 * does not allow to convert between real pixel sizes and the
60 * constant (integer) value that may be used to tag a frame or
61 * whatever. The set of macros below constructs videosize constants
62 * from the pixel size and allows to reconstruct the pixel size
63 * from the combined value later.
64 */
65#define VIDEOSIZE(x,y) (((x) & 0xFFFFL) | (((y) & 0xFFFFL) << 16))
66#define VIDEOSIZE_X(vs) ((vs) & 0xFFFFL)
67#define VIDEOSIZE_Y(vs) (((vs) >> 16) & 0xFFFFL)
68typedef unsigned long videosize_t;
69
70/*
71 * This macro checks if the camera is still operational. The 'uvd'
72 * pointer must be valid, uvd->dev must be valid, we are not
73 * removing the device and the device has not erred on us.
74 */
75#define CAMERA_IS_OPERATIONAL(uvd) (\
76 (uvd != NULL) && \
77 ((uvd)->dev != NULL) && \
78 ((uvd)->last_error == 0) && \
79 (!(uvd)->remove_pending))
80
81/*
82 * We use macros to do YUV -> RGB conversion because this is
83 * very important for speed and totally unimportant for size.
84 *
85 * YUV -> RGB Conversion
86 * ---------------------
87 *
88 * B = 1.164*(Y-16) + 2.018*(V-128)
89 * G = 1.164*(Y-16) - 0.813*(U-128) - 0.391*(V-128)
90 * R = 1.164*(Y-16) + 1.596*(U-128)
91 *
92 * If you fancy integer arithmetics (as you should), hear this:
93 *
94 * 65536*B = 76284*(Y-16) + 132252*(V-128)
95 * 65536*G = 76284*(Y-16) - 53281*(U-128) - 25625*(V-128)
96 * 65536*R = 76284*(Y-16) + 104595*(U-128)
97 *
98 * Make sure the output values are within [0..255] range.
99 */
100#define LIMIT_RGB(x) (((x) < 0) ? 0 : (((x) > 255) ? 255 : (x)))
101#define YUV_TO_RGB_BY_THE_BOOK(my,mu,mv,mr,mg,mb) { \
102 int mm_y, mm_yc, mm_u, mm_v, mm_r, mm_g, mm_b; \
103 mm_y = (my) - 16; \
104 mm_u = (mu) - 128; \
105 mm_v = (mv) - 128; \
106 mm_yc= mm_y * 76284; \
107 mm_b = (mm_yc + 132252*mm_v ) >> 16; \
108 mm_g = (mm_yc - 53281*mm_u - 25625*mm_v ) >> 16; \
109 mm_r = (mm_yc + 104595*mm_u ) >> 16; \
110 mb = LIMIT_RGB(mm_b); \
111 mg = LIMIT_RGB(mm_g); \
112 mr = LIMIT_RGB(mm_r); \
113}
114
115#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */
116#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1)
117#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
118#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)])
119
120struct RingQueue {
121 unsigned char *queue; /* Data from the Isoc data pump */
122 int length; /* How many bytes allocated for the queue */
123 int wi; /* That's where we write */
124 int ri; /* Read from here until you hit write index */
125 wait_queue_head_t wqh; /* Processes waiting */
126};
127
128enum ScanState {
129 ScanState_Scanning, /* Scanning for header */
130 ScanState_Lines /* Parsing lines */
131};
132
133/* Completion states of the data parser */
134enum ParseState {
135 scan_Continue, /* Just parse next item */
136 scan_NextFrame, /* Frame done, send it to V4L */
137 scan_Out, /* Not enough data for frame */
138 scan_EndParse /* End parsing */
139};
140
141enum FrameState {
142 FrameState_Unused, /* Unused (no MCAPTURE) */
143 FrameState_Ready, /* Ready to start grabbing */
144 FrameState_Grabbing, /* In the process of being grabbed into */
145 FrameState_Done, /* Finished grabbing, but not been synced yet */
146 FrameState_Done_Hold, /* Are syncing or reading */
147 FrameState_Error, /* Something bad happened while processing */
148};
149
150/*
151 * Some frames may contain only even or odd lines. This type
152 * specifies what type of deinterlacing is required.
153 */
154enum Deinterlace {
155 Deinterlace_None=0,
156 Deinterlace_FillOddLines,
157 Deinterlace_FillEvenLines
158};
159
160#define USBVIDEO_NUMFRAMES 2 /* How many frames we work with */
161#define USBVIDEO_NUMSBUF 2 /* How many URBs linked in a ring */
162
163/* This structure represents one Isoc request - URB and buffer */
164struct usbvideo_sbuf {
165 char *data;
166 struct urb *urb;
167};
168
169struct usbvideo_frame {
170 char *data; /* Frame buffer */
171 unsigned long header; /* Significant bits from the header */
172
173 videosize_t canvas; /* The canvas (max. image) allocated */
174 videosize_t request; /* That's what the application asked for */
175 unsigned short palette; /* The desired format */
176
177 enum FrameState frameState;/* State of grabbing */
178 enum ScanState scanstate; /* State of scanning */
179 enum Deinterlace deinterlace;
180 int flags; /* USBVIDEO_FRAME_FLAG_xxx bit flags */
181
182 int curline; /* Line of frame we're working on */
183
184 long seqRead_Length; /* Raw data length of frame */
185 long seqRead_Index; /* Amount of data that has been already read */
186
187 void *user; /* Additional data that user may need */
188};
189
190/* Statistics that can be overlaid on screen */
191struct usbvideo_statistics {
192 unsigned long frame_num; /* Sequential number of the frame */
193 unsigned long urb_count; /* How many URBs we received so far */
194 unsigned long urb_length; /* Length of last URB */
195 unsigned long data_count; /* How many bytes we received */
196 unsigned long header_count; /* How many frame headers we found */
197 unsigned long iso_skip_count; /* How many empty ISO packets received */
198 unsigned long iso_err_count; /* How many bad ISO packets received */
199};
200
201struct usbvideo;
202
203struct uvd {
204 struct video_device vdev; /* Must be the first field! */
205 struct usb_device *dev;
206 struct usbvideo *handle; /* Points back to the struct usbvideo */
207 void *user_data; /* Camera-dependent data */
208 int user_size; /* Size of that camera-dependent data */
209 int debug; /* Debug level for usbvideo */
210 unsigned char iface; /* Video interface number */
211 unsigned char video_endp;
212 unsigned char ifaceAltActive;
213 unsigned char ifaceAltInactive; /* Alt settings */
214 unsigned long flags; /* FLAGS_USBVIDEO_xxx */
215 unsigned long paletteBits; /* Which palettes we accept? */
216 unsigned short defaultPalette; /* What palette to use for read() */
217 struct mutex lock;
218 int user; /* user count for exclusive use */
219
220 videosize_t videosize; /* Current setting */
221 videosize_t canvas; /* This is the width,height of the V4L canvas */
222 int max_frame_size; /* Bytes in one video frame */
223
224 int uvd_used; /* Is this structure in use? */
225 int streaming; /* Are we streaming Isochronous? */
226 int grabbing; /* Are we grabbing? */
227 int settingsAdjusted; /* Have we adjusted contrast etc.? */
228 int last_error; /* What calamity struck us? */
229
230 char *fbuf; /* Videodev buffer area */
231 int fbuf_size; /* Videodev buffer size */
232
233 int curframe;
234 int iso_packet_len; /* Videomode-dependent, saves bus bandwidth */
235
236 struct RingQueue dp; /* Isoc data pump */
237 struct usbvideo_frame frame[USBVIDEO_NUMFRAMES];
238 struct usbvideo_sbuf sbuf[USBVIDEO_NUMSBUF];
239
240 volatile int remove_pending; /* If set then about to exit */
241
242 struct video_picture vpic, vpic_old; /* Picture settings */
243 struct video_capability vcap; /* Video capabilities */
244 struct video_channel vchan; /* May be used for tuner support */
245 struct usbvideo_statistics stats;
246 char videoName[32]; /* Holds name like "video7" */
247};
248
249/*
250 * usbvideo callbacks (virtual methods). They are set when usbvideo
251 * services are registered. All of these default to NULL, except those
252 * that default to usbvideo-provided methods.
253 */
254struct usbvideo_cb {
255 int (*probe)(struct usb_interface *, const struct usb_device_id *);
256 void (*userFree)(struct uvd *);
257 void (*disconnect)(struct usb_interface *);
258 int (*setupOnOpen)(struct uvd *);
259 void (*videoStart)(struct uvd *);
260 void (*videoStop)(struct uvd *);
261 void (*processData)(struct uvd *, struct usbvideo_frame *);
262 void (*postProcess)(struct uvd *, struct usbvideo_frame *);
263 void (*adjustPicture)(struct uvd *);
264 int (*getFPS)(struct uvd *);
265 int (*overlayHook)(struct uvd *, struct usbvideo_frame *);
266 int (*getFrame)(struct uvd *, int);
267 int (*startDataPump)(struct uvd *uvd);
268 void (*stopDataPump)(struct uvd *uvd);
269 int (*setVideoMode)(struct uvd *uvd, struct video_window *vw);
270};
271
272struct usbvideo {
273 int num_cameras; /* As allocated */
274 struct usb_driver usbdrv; /* Interface to the USB stack */
275 char drvName[80]; /* Driver name */
276 struct mutex lock; /* Mutex protecting camera structures */
277 struct usbvideo_cb cb; /* Table of callbacks (virtual methods) */
278 struct video_device vdt; /* Video device template */
279 struct uvd *cam; /* Array of camera structures */
280 struct module *md_module; /* Minidriver module */
281};
282
283
284/*
285 * This macro retrieves callback address from the struct uvd object.
286 * No validity checks are done here, so be sure to check the
287 * callback beforehand with VALID_CALLBACK.
288 */
289#define GET_CALLBACK(uvd,cbName) ((uvd)->handle->cb.cbName)
290
291/*
292 * This macro returns either callback pointer or NULL. This is safe
293 * macro, meaning that most of components of data structures involved
294 * may be NULL - this only results in NULL being returned. You may
295 * wish to use this macro to make sure that the callback is callable.
296 * However keep in mind that those checks take time.
297 */
298#define VALID_CALLBACK(uvd,cbName) ((((uvd) != NULL) && \
299 ((uvd)->handle != NULL)) ? GET_CALLBACK(uvd,cbName) : NULL)
300
301int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len);
302int RingQueue_Enqueue(struct RingQueue *rq, const unsigned char *cdata, int n);
303void RingQueue_WakeUpInterruptible(struct RingQueue *rq);
304void RingQueue_Flush(struct RingQueue *rq);
305
306static inline int RingQueue_GetLength(const struct RingQueue *rq)
307{
308 return (rq->wi - rq->ri + rq->length) & (rq->length-1);
309}
310
311static inline int RingQueue_GetFreeSpace(const struct RingQueue *rq)
312{
313 return rq->length - RingQueue_GetLength(rq);
314}
315
316void usbvideo_DrawLine(
317 struct usbvideo_frame *frame,
318 int x1, int y1,
319 int x2, int y2,
320 unsigned char cr, unsigned char cg, unsigned char cb);
321void usbvideo_HexDump(const unsigned char *data, int len);
322void usbvideo_SayAndWait(const char *what);
323void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode);
324
325/* Memory allocation routines */
326unsigned long usbvideo_kvirt_to_pa(unsigned long adr);
327
328int usbvideo_register(
329 struct usbvideo **pCams,
330 const int num_cams,
331 const int num_extra,
332 const char *driverName,
333 const struct usbvideo_cb *cbTable,
334 struct module *md,
335 const struct usb_device_id *id_table);
336struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams);
337int usbvideo_RegisterVideoDevice(struct uvd *uvd);
338void usbvideo_Deregister(struct usbvideo **uvt);
339
340int usbvideo_v4l_initialize(struct video_device *dev);
341
342void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame);
343
344/*
345 * This code performs bounds checking - use it when working with
346 * new formats, or else you may get oopses all over the place.
347 * If pixel falls out of bounds then it gets shoved back (as close
348 * to place of offence as possible) and is painted bright red.
349 *
350 * There are two important concepts: frame width, height and
351 * V4L canvas width, height. The former is the area requested by
352 * the application -for this very frame-. The latter is the largest
353 * possible frame that we can serve (we advertise that via V4L ioctl).
354 * The frame data is expected to be formatted as lines of length
355 * VIDEOSIZE_X(fr->request), total VIDEOSIZE_Y(frame->request) lines.
356 */
357static inline void RGB24_PUTPIXEL(
358 struct usbvideo_frame *fr,
359 int ix, int iy,
360 unsigned char vr,
361 unsigned char vg,
362 unsigned char vb)
363{
364 register unsigned char *pf;
365 int limiter = 0, mx, my;
366 mx = ix;
367 my = iy;
368 if (mx < 0) {
369 mx=0;
370 limiter++;
371 } else if (mx >= VIDEOSIZE_X((fr)->request)) {
372 mx= VIDEOSIZE_X((fr)->request) - 1;
373 limiter++;
374 }
375 if (my < 0) {
376 my = 0;
377 limiter++;
378 } else if (my >= VIDEOSIZE_Y((fr)->request)) {
379 my = VIDEOSIZE_Y((fr)->request) - 1;
380 limiter++;
381 }
382 pf = (fr)->data + V4L_BYTES_PER_PIXEL*((iy)*VIDEOSIZE_X((fr)->request) + (ix));
383 if (limiter) {
384 *pf++ = 0;
385 *pf++ = 0;
386 *pf++ = 0xFF;
387 } else {
388 *pf++ = (vb);
389 *pf++ = (vg);
390 *pf++ = (vr);
391 }
392}
393
394#endif /* usbvideo_h */
diff --git a/drivers/media/video/usbvideo/vicam.c b/drivers/media/video/usbvideo/vicam.c
new file mode 100644
index 000000000000..1d06e53ec7c5
--- /dev/null
+++ b/drivers/media/video/usbvideo/vicam.c
@@ -0,0 +1,1411 @@
1/*
2 * USB ViCam WebCam driver
3 * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
4 * Christopher L Cheney (ccheney@cheney.cx),
5 * Pavel Machek (pavel@suse.cz),
6 * John Tyner (jtyner@cs.ucr.edu),
7 * Monroe Williams (monroe@pobox.com)
8 *
9 * Supports 3COM HomeConnect PC Digital WebCam
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * This source code is based heavily on the CPiA webcam driver which was
26 * written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
27 *
28 * Portions of this code were also copied from usbvideo.c
29 *
30 * Special thanks to the the whole team at Sourceforge for help making
31 * this driver become a reality. Notably:
32 * Andy Armstrong who reverse engineered the color encoding and
33 * Pavel Machek and Chris Cheney who worked on reverse engineering the
34 * camera controls and wrote the first generation driver.
35 */
36
37#include <linux/kernel.h>
38#include <linux/module.h>
39#include <linux/init.h>
40#include <linux/videodev.h>
41#include <linux/usb.h>
42#include <linux/vmalloc.h>
43#include <linux/slab.h>
44#include <linux/proc_fs.h>
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
64#define VICAM_BYTES_PER_PIXEL 3
65#define VICAM_MAX_READ_SIZE (512*242+128)
66#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
67#define VICAM_FRAMES 2
68
69#define VICAM_HEADER_SIZE 64
70
71#define clamp( x, l, h ) max_t( __typeof__( x ), \
72 ( l ), \
73 min_t( __typeof__( x ), \
74 ( h ), \
75 ( x ) ) )
76
77/* Not sure what all the bytes in these char
78 * arrays do, but they're necessary to make
79 * the camera work.
80 */
81
82static unsigned char setup1[] = {
83 0xB6, 0xC3, 0x1F, 0x00, 0x02, 0x64, 0xE7, 0x67,
84 0xFD, 0xFF, 0x0E, 0xC0, 0xE7, 0x09, 0xDE, 0x00,
85 0x8E, 0x00, 0xC0, 0x09, 0x40, 0x03, 0xC0, 0x17,
86 0x44, 0x03, 0x4B, 0xAF, 0xC0, 0x07, 0x00, 0x00,
87 0x4B, 0xAF, 0x97, 0xCF, 0x00, 0x00
88};
89
90static unsigned char setup2[] = {
91 0xB6, 0xC3, 0x03, 0x00, 0x03, 0x64, 0x18, 0x00,
92 0x00, 0x00
93};
94
95static unsigned char setup3[] = {
96 0xB6, 0xC3, 0x01, 0x00, 0x06, 0x64, 0x00, 0x00
97};
98
99static unsigned char setup4[] = {
100 0xB6, 0xC3, 0x8F, 0x06, 0x02, 0x64, 0xE7, 0x07,
101 0x00, 0x00, 0x08, 0xC0, 0xE7, 0x07, 0x00, 0x00,
102 0x3E, 0xC0, 0xE7, 0x07, 0x54, 0x01, 0xAA, 0x00,
103 0xE7, 0x07, 0xC8, 0x05, 0xB6, 0x00, 0xE7, 0x07,
104 0x42, 0x01, 0xD2, 0x00, 0xE7, 0x07, 0x7C, 0x00,
105 0x16, 0x00, 0xE7, 0x07, 0x56, 0x00, 0x18, 0x00,
106 0xE7, 0x07, 0x06, 0x00, 0x92, 0xC0, 0xE7, 0x07,
107 0x00, 0x00, 0x1E, 0xC0, 0xE7, 0x07, 0xFF, 0xFF,
108 0x22, 0xC0, 0xE7, 0x07, 0x04, 0x00, 0x24, 0xC0,
109 0xE7, 0x07, 0xEC, 0x27, 0x28, 0xC0, 0xE7, 0x07,
110 0x16, 0x01, 0x8E, 0x00, 0xE7, 0x87, 0x01, 0x00,
111 0x0E, 0xC0, 0x97, 0xCF, 0xD7, 0x09, 0x00, 0xC0,
112 0xE7, 0x77, 0x01, 0x00, 0x92, 0xC0, 0x09, 0xC1,
113 0xE7, 0x09, 0xFE, 0x05, 0x24, 0x01, 0xE7, 0x09,
114 0x04, 0x06, 0x26, 0x01, 0xE7, 0x07, 0x07, 0x00,
115 0x92, 0xC0, 0xE7, 0x05, 0x00, 0xC0, 0xC0, 0xDF,
116 0x97, 0xCF, 0x17, 0x00, 0x57, 0x00, 0x17, 0x02,
117 0xD7, 0x09, 0x00, 0xC0, 0xE7, 0x77, 0x01, 0x00,
118 0x92, 0xC0, 0x0A, 0xC1, 0xE7, 0x57, 0xFF, 0xFF,
119 0xFA, 0x05, 0x0D, 0xC0, 0xE7, 0x57, 0x00, 0x00,
120 0xFA, 0x05, 0x0F, 0xC0, 0x9F, 0xAF, 0xC6, 0x00,
121 0xE7, 0x05, 0x00, 0xC0, 0xC8, 0x05, 0xC1, 0x05,
122 0xC0, 0x05, 0xC0, 0xDF, 0x97, 0xCF, 0x27, 0xDA,
123 0xFA, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x0B, 0x06,
124 0x73, 0xCF, 0x9F, 0xAF, 0x78, 0x01, 0x9F, 0xAF,
125 0x1A, 0x03, 0x6E, 0xCF, 0xE7, 0x09, 0xFC, 0x05,
126 0x24, 0x01, 0xE7, 0x09, 0x02, 0x06, 0x26, 0x01,
127 0xE7, 0x07, 0x07, 0x00, 0x92, 0xC0, 0xE7, 0x09,
128 0xFC, 0x05, 0xFE, 0x05, 0xE7, 0x09, 0x02, 0x06,
129 0x04, 0x06, 0xE7, 0x09, 0x00, 0x06, 0xFC, 0x05,
130 0xE7, 0x09, 0xFE, 0x05, 0x00, 0x06, 0x27, 0xDA,
131 0xFA, 0x05, 0xE7, 0x57, 0x01, 0x00, 0xFA, 0x05,
132 0x02, 0xCA, 0x04, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
133 0x66, 0x05, 0x97, 0xCF, 0xE7, 0x07, 0x40, 0x00,
134 0x02, 0x06, 0xC8, 0x09, 0xFC, 0x05, 0x9F, 0xAF,
135 0xDA, 0x02, 0x97, 0xCF, 0xCF, 0x17, 0x02, 0x00,
136 0xEF, 0x57, 0x81, 0x00, 0x09, 0x06, 0x9F, 0xA0,
137 0xB6, 0x01, 0xEF, 0x57, 0x80, 0x00, 0x09, 0x06,
138 0x9F, 0xA0, 0x40, 0x02, 0xEF, 0x57, 0x01, 0x00,
139 0x0B, 0x06, 0x9F, 0xA0, 0x46, 0x03, 0xE7, 0x07,
140 0x01, 0x00, 0x0A, 0xC0, 0x46, 0xAF, 0x47, 0xAF,
141 0x9F, 0xAF, 0x40, 0x02, 0xE7, 0x07, 0x2E, 0x00,
142 0x0A, 0xC0, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
143 0x97, 0xCF, 0x00, 0x0E, 0x01, 0x00, 0xC0, 0x57,
144 0x51, 0x00, 0x9F, 0xC0, 0x9E, 0x02, 0xC0, 0x57,
145 0x50, 0x00, 0x20, 0xC0, 0xC0, 0x57, 0x55, 0x00,
146 0x12, 0xC0, 0xC0, 0x57, 0x56, 0x00, 0x9F, 0xC0,
147 0x72, 0x02, 0x9F, 0xCF, 0xD6, 0x02, 0xC1, 0x0B,
148 0x08, 0x06, 0x01, 0xD0, 0x6F, 0x90, 0x08, 0x06,
149 0xC0, 0x07, 0x08, 0x00, 0xC1, 0x0B, 0x08, 0x06,
150 0x9F, 0xAF, 0x28, 0x05, 0x97, 0xCF, 0x2F, 0x0E,
151 0x02, 0x00, 0x08, 0x06, 0xC0, 0x07, 0x08, 0x00,
152 0xC1, 0x0B, 0x08, 0x06, 0x9F, 0xAF, 0x28, 0x05,
153 0x9F, 0xCF, 0xD6, 0x02, 0x2F, 0x0E, 0x02, 0x00,
154 0x09, 0x06, 0xEF, 0x87, 0x80, 0x00, 0x09, 0x06,
155 0x9F, 0xCF, 0xD6, 0x02, 0xEF, 0x67, 0x7F, 0xFF,
156 0x09, 0x06, 0xE7, 0x67, 0xFF, 0xFD, 0x22, 0xC0,
157 0xE7, 0x67, 0xEF, 0xFF, 0x24, 0xC0, 0xE7, 0x87,
158 0x10, 0x00, 0x28, 0xC0, 0x9F, 0xAF, 0xB8, 0x05,
159 0xE7, 0x87, 0xE0, 0x21, 0x24, 0xC0, 0x9F, 0xAF,
160 0xA8, 0x05, 0xE7, 0x87, 0x08, 0x00, 0x24, 0xC0,
161 0xE7, 0x67, 0xDF, 0xFF, 0x24, 0xC0, 0xC8, 0x07,
162 0x0A, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xC1, 0x07,
163 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0x9F, 0xAF,
164 0xB8, 0x05, 0xC0, 0x07, 0x9E, 0x00, 0x9F, 0xAF,
165 0x44, 0x05, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
166 0xC0, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
167 0x24, 0xC0, 0xC0, 0x77, 0x00, 0x02, 0x0F, 0xC1,
168 0xE7, 0x67, 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
169 0xF7, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x08, 0x00,
170 0x24, 0xC0, 0x08, 0xDA, 0x5E, 0xC1, 0xEF, 0x07,
171 0x80, 0x00, 0x09, 0x06, 0x97, 0xCF, 0xEF, 0x07,
172 0x01, 0x00, 0x0A, 0x06, 0x97, 0xCF, 0xEF, 0x07,
173 0x00, 0x00, 0x0B, 0x06, 0xEF, 0x07, 0x00, 0x00,
174 0x0A, 0x06, 0xEF, 0x67, 0x7F, 0xFF, 0x09, 0x06,
175 0xEF, 0x07, 0x00, 0x00, 0x0D, 0x06, 0xE7, 0x67,
176 0xEF, 0xFF, 0x28, 0xC0, 0xE7, 0x67, 0x17, 0xD8,
177 0x24, 0xC0, 0xE7, 0x07, 0x00, 0x00, 0x1E, 0xC0,
178 0xE7, 0x07, 0xFF, 0xFF, 0x22, 0xC0, 0x97, 0xCF,
179 0xC8, 0x07, 0x0E, 0x06, 0x9F, 0xAF, 0xDA, 0x02,
180 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
181 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0x0E, 0x06,
182 0xF4, 0x05, 0xE7, 0x07, 0xD6, 0x02, 0xF8, 0x05,
183 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
184 0x50, 0xAF, 0x97, 0xCF, 0x2F, 0x0C, 0x02, 0x00,
185 0x07, 0x06, 0x2F, 0x0C, 0x04, 0x00, 0x06, 0x06,
186 0xE7, 0x07, 0x00, 0x00, 0xF2, 0x05, 0xE7, 0x07,
187 0x10, 0x00, 0xF6, 0x05, 0xE7, 0x07, 0xE2, 0x05,
188 0xF4, 0x05, 0xE7, 0x07, 0xCE, 0x02, 0xF8, 0x05,
189 0xC8, 0x07, 0xF2, 0x05, 0xC1, 0x07, 0x00, 0x80,
190 0x51, 0xAF, 0x97, 0xCF, 0x9F, 0xAF, 0x66, 0x04,
191 0x9F, 0xAF, 0x1A, 0x03, 0x59, 0xAF, 0x97, 0xCF,
192 0xC0, 0x07, 0x0E, 0x00, 0xC1, 0x0B, 0x0C, 0x06,
193 0x41, 0xD1, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
194 0x3C, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0x68, 0x00,
195 0xC0, 0x07, 0x3B, 0x00, 0x9F, 0xAF, 0x44, 0x05,
196 0x6F, 0x00, 0x0C, 0x06, 0x68, 0x00, 0xE0, 0x07,
197 0x04, 0x01, 0xE8, 0x0B, 0x0A, 0x06, 0xE8, 0x07,
198 0x00, 0x00, 0xE0, 0x07, 0x00, 0x02, 0xE0, 0x07,
199 0xEC, 0x01, 0xE0, 0x07, 0xFC, 0xFF, 0x97, 0xCF,
200 0xE7, 0x07, 0xFF, 0xFF, 0xFA, 0x05, 0xEF, 0x07,
201 0x00, 0x00, 0x0B, 0x06, 0xE7, 0x07, 0x0E, 0x06,
202 0x24, 0x01, 0xE7, 0x07, 0x0E, 0x06, 0xFE, 0x05,
203 0xE7, 0x07, 0x40, 0x00, 0x26, 0x01, 0xE7, 0x07,
204 0x40, 0x00, 0x04, 0x06, 0xE7, 0x07, 0x07, 0x00,
205 0x92, 0xC0, 0x97, 0xCF, 0xEF, 0x07, 0x02, 0x00,
206 0x0B, 0x06, 0x9F, 0xAF, 0x78, 0x01, 0xEF, 0x77,
207 0x80, 0x00, 0x07, 0x06, 0x9F, 0xC0, 0x14, 0x04,
208 0xEF, 0x77, 0x01, 0x00, 0x07, 0x06, 0x37, 0xC0,
209 0xEF, 0x77, 0x01, 0x00, 0x0D, 0x06, 0x0F, 0xC1,
210 0xEF, 0x07, 0x01, 0x00, 0x0D, 0x06, 0xC0, 0x07,
211 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00, 0x9F, 0xAF,
212 0x28, 0x05, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
213 0x02, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07,
214 0xFF, 0x4F, 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07,
215 0x38, 0x00, 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x77,
216 0x03, 0x00, 0x02, 0xC1, 0x08, 0xDA, 0x75, 0xC1,
217 0xC1, 0x77, 0x01, 0x00, 0x0A, 0xC1, 0xC0, 0x07,
218 0x01, 0x00, 0xC1, 0x07, 0x02, 0x00, 0x9F, 0xAF,
219 0x28, 0x05, 0xEF, 0x07, 0x01, 0x00, 0x06, 0x06,
220 0x2C, 0xCF, 0xC0, 0x07, 0x01, 0x00, 0xC1, 0x07,
221 0x04, 0x00, 0x9F, 0xAF, 0x28, 0x05, 0xEF, 0x07,
222 0x00, 0x00, 0x06, 0x06, 0x22, 0xCF, 0xEF, 0x07,
223 0x00, 0x00, 0x0D, 0x06, 0xEF, 0x57, 0x01, 0x00,
224 0x06, 0x06, 0x1B, 0xC0, 0xC0, 0x07, 0x01, 0x00,
225 0xC1, 0x07, 0x01, 0x00, 0x9F, 0xAF, 0x28, 0x05,
226 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07, 0x30, 0x00,
227 0x9F, 0xAF, 0x28, 0x05, 0xC8, 0x07, 0xFF, 0x4F,
228 0x9F, 0xAF, 0xA8, 0x05, 0xC0, 0x07, 0x38, 0x00,
229 0x9F, 0xAF, 0x44, 0x05, 0xC1, 0x67, 0x03, 0x00,
230 0xC1, 0x57, 0x03, 0x00, 0x02, 0xC0, 0x08, 0xDA,
231 0x73, 0xC1, 0xC0, 0x07, 0x02, 0x00, 0xC1, 0x07,
232 0x12, 0x00, 0xEF, 0x57, 0x00, 0x00, 0x06, 0x06,
233 0x02, 0xC0, 0xC1, 0x07, 0x23, 0x00, 0x9F, 0xAF,
234 0x28, 0x05, 0xC0, 0x07, 0x14, 0x00, 0xC1, 0x0B,
235 0xEA, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
236 0x3E, 0x00, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x09,
237 0xE4, 0x05, 0xFA, 0x05, 0x27, 0xD8, 0xFA, 0x05,
238 0xE7, 0x07, 0x0E, 0x06, 0xFC, 0x05, 0xE7, 0x07,
239 0x4E, 0x06, 0x00, 0x06, 0xE7, 0x07, 0x40, 0x00,
240 0x02, 0x06, 0x9F, 0xAF, 0x66, 0x05, 0x9F, 0xAF,
241 0xC6, 0x00, 0x97, 0xCF, 0xC1, 0x0B, 0xE2, 0x05,
242 0x41, 0xD0, 0x01, 0xD2, 0xC1, 0x17, 0x23, 0x00,
243 0x9F, 0xAF, 0xDC, 0x04, 0xC0, 0x07, 0x04, 0x00,
244 0xC1, 0x0B, 0xE3, 0x05, 0x9F, 0xAF, 0x28, 0x05,
245 0xC0, 0x07, 0x06, 0x00, 0xC1, 0x09, 0xE6, 0x05,
246 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x07, 0x00,
247 0xC1, 0x09, 0xE6, 0x05, 0xC1, 0xD1, 0x9F, 0xAF,
248 0x28, 0x05, 0xC0, 0x07, 0x0B, 0x00, 0xC1, 0x09,
249 0xE8, 0x05, 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07,
250 0x0C, 0x00, 0xC1, 0x09, 0xE8, 0x05, 0xC1, 0xD1,
251 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0D, 0x00,
252 0xC1, 0x07, 0x09, 0x00, 0x9F, 0xAF, 0x28, 0x05,
253 0xC0, 0x07, 0x03, 0x00, 0xC1, 0x07, 0x32, 0x00,
254 0x9F, 0xAF, 0x28, 0x05, 0xC0, 0x07, 0x0F, 0x00,
255 0xC1, 0x07, 0x00, 0x00, 0x9F, 0xAF, 0x28, 0x05,
256 0x97, 0xCF, 0xE7, 0x67, 0xFF, 0xD9, 0x24, 0xC0,
257 0xC8, 0x07, 0x0A, 0x00, 0x40, 0x00, 0xC0, 0x67,
258 0x00, 0x02, 0x27, 0x80, 0x24, 0xC0, 0xE7, 0x87,
259 0x00, 0x04, 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xF9,
260 0x24, 0xC0, 0x01, 0xD2, 0x08, 0xDA, 0x72, 0xC1,
261 0xE7, 0x87, 0x00, 0x20, 0x24, 0xC0, 0x97, 0xCF,
262 0x27, 0x00, 0x1E, 0xC0, 0xE7, 0x87, 0xFF, 0x00,
263 0x22, 0xC0, 0xE7, 0x67, 0x7F, 0xFF, 0x24, 0xC0,
264 0xE7, 0x87, 0x80, 0x00, 0x24, 0xC0, 0xE7, 0x87,
265 0x80, 0x00, 0x24, 0xC0, 0x97, 0xCF, 0x9F, 0xAF,
266 0x0A, 0x05, 0x67, 0x00, 0x1E, 0xC0, 0xE7, 0x67,
267 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00,
268 0x24, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
269 0x97, 0xCF, 0x9F, 0xAF, 0x0A, 0x05, 0xE7, 0x67,
270 0x00, 0xFF, 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE,
271 0x24, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
272 0xC1, 0x09, 0x20, 0xC0, 0xE7, 0x87, 0x00, 0x01,
273 0x24, 0xC0, 0x97, 0xCF, 0xC0, 0x07, 0x40, 0x00,
274 0xC8, 0x09, 0xFC, 0x05, 0xE7, 0x67, 0x00, 0xFF,
275 0x22, 0xC0, 0xE7, 0x67, 0xFF, 0xFE, 0x24, 0xC0,
276 0xE7, 0x67, 0xBF, 0xFF, 0x24, 0xC0, 0xE7, 0x67,
277 0xBF, 0xFF, 0x24, 0xC0, 0x00, 0xDA, 0xE8, 0x09,
278 0x20, 0xC0, 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0,
279 0xE7, 0x87, 0x40, 0x00, 0x24, 0xC0, 0x00, 0xDA,
280 0xE8, 0x09, 0x20, 0xC0, 0x6D, 0xC1, 0xE7, 0x87,
281 0x00, 0x01, 0x24, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
282 0x32, 0x00, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
283 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0xE7, 0x07,
284 0x20, 0x4E, 0x12, 0xC0, 0xE7, 0x77, 0x00, 0x80,
285 0x12, 0xC0, 0x7C, 0xC0, 0x97, 0xCF, 0x09, 0x02,
286 0x19, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09,
287 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
288 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x00,
289 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
290 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
293 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311};
312
313static unsigned char setup5[] = {
314 0xB6, 0xC3, 0x2F, 0x01, 0x03, 0x64, 0x0E, 0x00,
315 0x14, 0x00, 0x1A, 0x00, 0x20, 0x00, 0x26, 0x00,
316 0x4A, 0x00, 0x64, 0x00, 0x6A, 0x00, 0x92, 0x00,
317 0x9A, 0x00, 0xA0, 0x00, 0xB2, 0x00, 0xB8, 0x00,
318 0xBE, 0x00, 0xC2, 0x00, 0xC8, 0x00, 0xCE, 0x00,
319 0xDC, 0x00, 0xDA, 0x00, 0xE2, 0x00, 0xE0, 0x00,
320 0xE8, 0x00, 0xE6, 0x00, 0xEE, 0x00, 0xEC, 0x00,
321 0xF2, 0x00, 0xF8, 0x00, 0x02, 0x01, 0x0A, 0x01,
322 0x0E, 0x01, 0x12, 0x01, 0x1E, 0x01, 0x22, 0x01,
323 0x28, 0x01, 0x2C, 0x01, 0x32, 0x01, 0x36, 0x01,
324 0x44, 0x01, 0x50, 0x01, 0x5E, 0x01, 0x72, 0x01,
325 0x76, 0x01, 0x7A, 0x01, 0x80, 0x01, 0x88, 0x01,
326 0x8C, 0x01, 0x94, 0x01, 0x9C, 0x01, 0xA0, 0x01,
327 0xA4, 0x01, 0xAA, 0x01, 0xB0, 0x01, 0xB4, 0x01,
328 0xBA, 0x01, 0xD0, 0x01, 0xDA, 0x01, 0xF6, 0x01,
329 0xFA, 0x01, 0x02, 0x02, 0x34, 0x02, 0x3C, 0x02,
330 0x44, 0x02, 0x4A, 0x02, 0x50, 0x02, 0x56, 0x02,
331 0x74, 0x02, 0x78, 0x02, 0x7E, 0x02, 0x84, 0x02,
332 0x8A, 0x02, 0x88, 0x02, 0x90, 0x02, 0x8E, 0x02,
333 0x94, 0x02, 0xA2, 0x02, 0xA8, 0x02, 0xAE, 0x02,
334 0xB4, 0x02, 0xBA, 0x02, 0xB8, 0x02, 0xC0, 0x02,
335 0xBE, 0x02, 0xC4, 0x02, 0xD0, 0x02, 0xD4, 0x02,
336 0xE0, 0x02, 0xE6, 0x02, 0xEE, 0x02, 0xF8, 0x02,
337 0xFC, 0x02, 0x06, 0x03, 0x1E, 0x03, 0x24, 0x03,
338 0x28, 0x03, 0x30, 0x03, 0x2E, 0x03, 0x3C, 0x03,
339 0x4A, 0x03, 0x4E, 0x03, 0x54, 0x03, 0x58, 0x03,
340 0x5E, 0x03, 0x66, 0x03, 0x6E, 0x03, 0x7A, 0x03,
341 0x86, 0x03, 0x8E, 0x03, 0x96, 0x03, 0xB2, 0x03,
342 0xB8, 0x03, 0xC6, 0x03, 0xCC, 0x03, 0xD4, 0x03,
343 0xDA, 0x03, 0xE8, 0x03, 0xF4, 0x03, 0xFC, 0x03,
344 0x04, 0x04, 0x20, 0x04, 0x2A, 0x04, 0x32, 0x04,
345 0x36, 0x04, 0x3E, 0x04, 0x44, 0x04, 0x42, 0x04,
346 0x48, 0x04, 0x4E, 0x04, 0x4C, 0x04, 0x54, 0x04,
347 0x52, 0x04, 0x5A, 0x04, 0x5E, 0x04, 0x62, 0x04,
348 0x68, 0x04, 0x74, 0x04, 0x7C, 0x04, 0x80, 0x04,
349 0x88, 0x04, 0x8C, 0x04, 0x94, 0x04, 0x9A, 0x04,
350 0xA2, 0x04, 0xA6, 0x04, 0xAE, 0x04, 0xB4, 0x04,
351 0xC0, 0x04, 0xCC, 0x04, 0xD8, 0x04, 0x2A, 0x05,
352 0x46, 0x05, 0x6C, 0x05, 0x00, 0x00
353};
354
355/* rvmalloc / rvfree copied from usbvideo.c
356 *
357 * Not sure why these are not yet non-statics which I can reference through
358 * usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime
359 * in the future.
360 *
361*/
362static void *rvmalloc(unsigned long size)
363{
364 void *mem;
365 unsigned long adr;
366
367 size = PAGE_ALIGN(size);
368 mem = vmalloc_32(size);
369 if (!mem)
370 return NULL;
371
372 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
373 adr = (unsigned long) mem;
374 while (size > 0) {
375 SetPageReserved(vmalloc_to_page((void *)adr));
376 adr += PAGE_SIZE;
377 size -= PAGE_SIZE;
378 }
379
380 return mem;
381}
382
383static void rvfree(void *mem, unsigned long size)
384{
385 unsigned long adr;
386
387 if (!mem)
388 return;
389
390 adr = (unsigned long) mem;
391 while ((long) size > 0) {
392 ClearPageReserved(vmalloc_to_page((void *)adr));
393 adr += PAGE_SIZE;
394 size -= PAGE_SIZE;
395 }
396 vfree(mem);
397}
398
399struct vicam_camera {
400 u16 shutter_speed; // capture shutter speed
401 u16 gain; // capture gain
402
403 u8 *raw_image; // raw data captured from the camera
404 u8 *framebuf; // processed data in RGB24 format
405 u8 *cntrlbuf; // area used to send control msgs
406
407 struct video_device vdev; // v4l video device
408 struct usb_device *udev; // usb device
409
410 /* guard against simultaneous accesses to the camera */
411 struct mutex cam_lock;
412
413 int is_initialized;
414 u8 open_count;
415 u8 bulkEndpoint;
416 int needsDummyRead;
417
418#if defined(CONFIG_VIDEO_PROC_FS)
419 struct proc_dir_entry *proc_dir;
420#endif
421
422};
423
424static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
425static void vicam_disconnect(struct usb_interface *intf);
426static void read_frame(struct vicam_camera *cam, int framenum);
427static void vicam_decode_color(const u8 *, u8 *);
428
429static int __send_control_msg(struct vicam_camera *cam,
430 u8 request,
431 u16 value,
432 u16 index,
433 unsigned char *cp,
434 u16 size)
435{
436 int status;
437
438 /* cp must be memory that has been allocated by kmalloc */
439
440 status = usb_control_msg(cam->udev,
441 usb_sndctrlpipe(cam->udev, 0),
442 request,
443 USB_DIR_OUT | USB_TYPE_VENDOR |
444 USB_RECIP_DEVICE, value, index,
445 cp, size, 1000);
446
447 status = min(status, 0);
448
449 if (status < 0) {
450 printk(KERN_INFO "Failed sending control message, error %d.\n",
451 status);
452 }
453
454 return status;
455}
456
457static int send_control_msg(struct vicam_camera *cam,
458 u8 request,
459 u16 value,
460 u16 index,
461 unsigned char *cp,
462 u16 size)
463{
464 int status = -ENODEV;
465 mutex_lock(&cam->cam_lock);
466 if (cam->udev) {
467 status = __send_control_msg(cam, request, value,
468 index, cp, size);
469 }
470 mutex_unlock(&cam->cam_lock);
471 return status;
472}
473static int
474initialize_camera(struct vicam_camera *cam)
475{
476 const struct {
477 u8 *data;
478 u32 size;
479 } firmware[] = {
480 { .data = setup1, .size = sizeof(setup1) },
481 { .data = setup2, .size = sizeof(setup2) },
482 { .data = setup3, .size = sizeof(setup3) },
483 { .data = setup4, .size = sizeof(setup4) },
484 { .data = setup5, .size = sizeof(setup5) },
485 { .data = setup3, .size = sizeof(setup3) },
486 { .data = NULL, .size = 0 }
487 };
488
489 int err, i;
490
491 for (i = 0, err = 0; firmware[i].data && !err; i++) {
492 memcpy(cam->cntrlbuf, firmware[i].data, firmware[i].size);
493
494 err = send_control_msg(cam, 0xff, 0, 0,
495 cam->cntrlbuf, firmware[i].size);
496 }
497
498 return err;
499}
500
501static int
502set_camera_power(struct vicam_camera *cam, int state)
503{
504 int status;
505
506 if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
507 return status;
508
509 if (state) {
510 send_control_msg(cam, 0x55, 1, 0, NULL, 0);
511 }
512
513 return 0;
514}
515
516static int
517vicam_ioctl(struct inode *inode, struct file *file, unsigned int ioctlnr, unsigned long arg)
518{
519 void __user *user_arg = (void __user *)arg;
520 struct vicam_camera *cam = file->private_data;
521 int retval = 0;
522
523 if (!cam)
524 return -ENODEV;
525
526 switch (ioctlnr) {
527 /* query capabilities */
528 case VIDIOCGCAP:
529 {
530 struct video_capability b;
531
532 DBG("VIDIOCGCAP\n");
533 memset(&b, 0, sizeof(b));
534 strcpy(b.name, "ViCam-based Camera");
535 b.type = VID_TYPE_CAPTURE;
536 b.channels = 1;
537 b.audios = 0;
538 b.maxwidth = 320; /* VIDEOSIZE_CIF */
539 b.maxheight = 240;
540 b.minwidth = 320; /* VIDEOSIZE_48_48 */
541 b.minheight = 240;
542
543 if (copy_to_user(user_arg, &b, sizeof(b)))
544 retval = -EFAULT;
545
546 break;
547 }
548 /* get/set video source - we are a camera and nothing else */
549 case VIDIOCGCHAN:
550 {
551 struct video_channel v;
552
553 DBG("VIDIOCGCHAN\n");
554 if (copy_from_user(&v, user_arg, sizeof(v))) {
555 retval = -EFAULT;
556 break;
557 }
558 if (v.channel != 0) {
559 retval = -EINVAL;
560 break;
561 }
562
563 v.channel = 0;
564 strcpy(v.name, "Camera");
565 v.tuners = 0;
566 v.flags = 0;
567 v.type = VIDEO_TYPE_CAMERA;
568 v.norm = 0;
569
570 if (copy_to_user(user_arg, &v, sizeof(v)))
571 retval = -EFAULT;
572 break;
573 }
574
575 case VIDIOCSCHAN:
576 {
577 int v;
578
579 if (copy_from_user(&v, user_arg, sizeof(v)))
580 retval = -EFAULT;
581 DBG("VIDIOCSCHAN %d\n", v);
582
583 if (retval == 0 && v != 0)
584 retval = -EINVAL;
585
586 break;
587 }
588
589 /* image properties */
590 case VIDIOCGPICT:
591 {
592 struct video_picture vp;
593 DBG("VIDIOCGPICT\n");
594 memset(&vp, 0, sizeof (struct video_picture));
595 vp.brightness = cam->gain << 8;
596 vp.depth = 24;
597 vp.palette = VIDEO_PALETTE_RGB24;
598 if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
599 retval = -EFAULT;
600 break;
601 }
602
603 case VIDIOCSPICT:
604 {
605 struct video_picture vp;
606
607 if (copy_from_user(&vp, user_arg, sizeof(vp))) {
608 retval = -EFAULT;
609 break;
610 }
611
612 DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
613 vp.palette);
614
615 cam->gain = vp.brightness >> 8;
616
617 if (vp.depth != 24
618 || vp.palette != VIDEO_PALETTE_RGB24)
619 retval = -EINVAL;
620
621 break;
622 }
623
624 /* get/set capture window */
625 case VIDIOCGWIN:
626 {
627 struct video_window vw;
628 vw.x = 0;
629 vw.y = 0;
630 vw.width = 320;
631 vw.height = 240;
632 vw.chromakey = 0;
633 vw.flags = 0;
634 vw.clips = NULL;
635 vw.clipcount = 0;
636
637 DBG("VIDIOCGWIN\n");
638
639 if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
640 retval = -EFAULT;
641
642 // I'm not sure what the deal with a capture window is, it is very poorly described
643 // in the doc. So I won't support it now.
644 break;
645 }
646
647 case VIDIOCSWIN:
648 {
649
650 struct video_window vw;
651
652 if (copy_from_user(&vw, user_arg, sizeof(vw))) {
653 retval = -EFAULT;
654 break;
655 }
656
657 DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
658
659 if ( vw.width != 320 || vw.height != 240 )
660 retval = -EFAULT;
661
662 break;
663 }
664
665 /* mmap interface */
666 case VIDIOCGMBUF:
667 {
668 struct video_mbuf vm;
669 int i;
670
671 DBG("VIDIOCGMBUF\n");
672 memset(&vm, 0, sizeof (vm));
673 vm.size =
674 VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
675 vm.frames = VICAM_FRAMES;
676 for (i = 0; i < VICAM_FRAMES; i++)
677 vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
678
679 if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
680 retval = -EFAULT;
681
682 break;
683 }
684
685 case VIDIOCMCAPTURE:
686 {
687 struct video_mmap vm;
688 // int video_size;
689
690 if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
691 retval = -EFAULT;
692 break;
693 }
694
695 DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
696
697 if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
698 retval = -EINVAL;
699
700 // in theory right here we'd start the image capturing
701 // (fill in a bulk urb and submit it asynchronously)
702 //
703 // Instead we're going to do a total hack job for now and
704 // retrieve the frame in VIDIOCSYNC
705
706 break;
707 }
708
709 case VIDIOCSYNC:
710 {
711 int frame;
712
713 if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
714 retval = -EFAULT;
715 break;
716 }
717 DBG("VIDIOCSYNC: %d\n", frame);
718
719 read_frame(cam, frame);
720 vicam_decode_color(cam->raw_image,
721 cam->framebuf +
722 frame * VICAM_MAX_FRAME_SIZE );
723
724 break;
725 }
726
727 /* pointless to implement overlay with this camera */
728 case VIDIOCCAPTURE:
729 case VIDIOCGFBUF:
730 case VIDIOCSFBUF:
731 case VIDIOCKEY:
732 retval = -EINVAL;
733 break;
734
735 /* tuner interface - we have none */
736 case VIDIOCGTUNER:
737 case VIDIOCSTUNER:
738 case VIDIOCGFREQ:
739 case VIDIOCSFREQ:
740 retval = -EINVAL;
741 break;
742
743 /* audio interface - we have none */
744 case VIDIOCGAUDIO:
745 case VIDIOCSAUDIO:
746 retval = -EINVAL;
747 break;
748 default:
749 retval = -ENOIOCTLCMD;
750 break;
751 }
752
753 return retval;
754}
755
756static int
757vicam_open(struct inode *inode, struct file *file)
758{
759 struct video_device *dev = video_devdata(file);
760 struct vicam_camera *cam =
761 (struct vicam_camera *) dev->priv;
762 DBG("open\n");
763
764 if (!cam) {
765 printk(KERN_ERR
766 "vicam video_device improperly initialized");
767 return -EINVAL;
768 }
769
770 /* the videodev_lock held above us protects us from
771 * simultaneous opens...for now. we probably shouldn't
772 * rely on this fact forever.
773 */
774
775 if (cam->open_count > 0) {
776 printk(KERN_INFO
777 "vicam_open called on already opened camera");
778 return -EBUSY;
779 }
780
781 cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
782 if (!cam->raw_image) {
783 return -ENOMEM;
784 }
785
786 cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
787 if (!cam->framebuf) {
788 kfree(cam->raw_image);
789 return -ENOMEM;
790 }
791
792 cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
793 if (!cam->cntrlbuf) {
794 kfree(cam->raw_image);
795 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
796 return -ENOMEM;
797 }
798
799 // First upload firmware, then turn the camera on
800
801 if (!cam->is_initialized) {
802 initialize_camera(cam);
803
804 cam->is_initialized = 1;
805 }
806
807 set_camera_power(cam, 1);
808
809 cam->needsDummyRead = 1;
810 cam->open_count++;
811
812 file->private_data = cam;
813
814 return 0;
815}
816
817static int
818vicam_close(struct inode *inode, struct file *file)
819{
820 struct vicam_camera *cam = file->private_data;
821 int open_count;
822 struct usb_device *udev;
823
824 DBG("close\n");
825
826 /* it's not the end of the world if
827 * we fail to turn the camera off.
828 */
829
830 set_camera_power(cam, 0);
831
832 kfree(cam->raw_image);
833 rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
834 kfree(cam->cntrlbuf);
835
836 mutex_lock(&cam->cam_lock);
837
838 cam->open_count--;
839 open_count = cam->open_count;
840 udev = cam->udev;
841
842 mutex_unlock(&cam->cam_lock);
843
844 if (!open_count && !udev) {
845 kfree(cam);
846 }
847
848 return 0;
849}
850
851static void vicam_decode_color(const u8 *data, u8 *rgb)
852{
853 /* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
854 * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
855 */
856
857 int i, prevY, nextY;
858
859 prevY = 512;
860 nextY = 512;
861
862 data += VICAM_HEADER_SIZE;
863
864 for( i = 0; i < 240; i++, data += 512 ) {
865 const int y = ( i * 242 ) / 240;
866
867 int j, prevX, nextX;
868 int Y, Cr, Cb;
869
870 if ( y == 242 - 1 ) {
871 nextY = -512;
872 }
873
874 prevX = 1;
875 nextX = 1;
876
877 for ( j = 0; j < 320; j++, rgb += 3 ) {
878 const int x = ( j * 512 ) / 320;
879 const u8 * const src = &data[x];
880
881 if ( x == 512 - 1 ) {
882 nextX = -1;
883 }
884
885 Cr = ( src[prevX] - src[0] ) +
886 ( src[nextX] - src[0] );
887 Cr /= 2;
888
889 Cb = ( src[prevY] - src[prevX + prevY] ) +
890 ( src[prevY] - src[nextX + prevY] ) +
891 ( src[nextY] - src[prevX + nextY] ) +
892 ( src[nextY] - src[nextX + nextY] );
893 Cb /= 4;
894
895 Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
896
897 if ( i & 1 ) {
898 int Ct = Cr;
899 Cr = Cb;
900 Cb = Ct;
901 }
902
903 if ( ( x ^ i ) & 1 ) {
904 Cr = -Cr;
905 Cb = -Cb;
906 }
907
908 rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
909 500 ) / 900, 0, 255 );
910 rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
911 ( 813 * Cr ) ) +
912 500 ) / 1000, 0, 255 );
913 rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
914 500 ) / 1300, 0, 255 );
915
916 prevX = -1;
917 }
918
919 prevY = -512;
920 }
921}
922
923static void
924read_frame(struct vicam_camera *cam, int framenum)
925{
926 unsigned char *request = cam->cntrlbuf;
927 int realShutter;
928 int n;
929 int actual_length;
930
931 if (cam->needsDummyRead) {
932 cam->needsDummyRead = 0;
933 read_frame(cam, framenum);
934 }
935
936 memset(request, 0, 16);
937 request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
938
939 request[1] = 0; // 512x242 capture
940
941 request[2] = 0x90; // the function of these two bytes
942 request[3] = 0x07; // is not yet understood
943
944 if (cam->shutter_speed > 60) {
945 // Short exposure
946 realShutter =
947 ((-15631900 / cam->shutter_speed) + 260533) / 1000;
948 request[4] = realShutter & 0xFF;
949 request[5] = (realShutter >> 8) & 0xFF;
950 request[6] = 0x03;
951 request[7] = 0x01;
952 } else {
953 // Long exposure
954 realShutter = 15600 / cam->shutter_speed - 1;
955 request[4] = 0;
956 request[5] = 0;
957 request[6] = realShutter & 0xFF;
958 request[7] = realShutter >> 8;
959 }
960
961 // Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
962 request[8] = 0;
963 // bytes 9-15 do not seem to affect exposure or image quality
964
965 mutex_lock(&cam->cam_lock);
966
967 if (!cam->udev) {
968 goto done;
969 }
970
971 n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
972
973 if (n < 0) {
974 printk(KERN_ERR
975 " Problem sending frame capture control message");
976 goto done;
977 }
978
979 n = usb_bulk_msg(cam->udev,
980 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
981 cam->raw_image,
982 512 * 242 + 128, &actual_length, 10000);
983
984 if (n < 0) {
985 printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
986 n);
987 }
988
989 done:
990 mutex_unlock(&cam->cam_lock);
991}
992
993static ssize_t
994vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
995{
996 struct vicam_camera *cam = file->private_data;
997
998 DBG("read %d bytes.\n", (int) count);
999
1000 if (*ppos >= VICAM_MAX_FRAME_SIZE) {
1001 *ppos = 0;
1002 return 0;
1003 }
1004
1005 if (*ppos == 0) {
1006 read_frame(cam, 0);
1007 vicam_decode_color(cam->raw_image,
1008 cam->framebuf +
1009 0 * VICAM_MAX_FRAME_SIZE);
1010 }
1011
1012 count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
1013
1014 if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
1015 count = -EFAULT;
1016 } else {
1017 *ppos += count;
1018 }
1019
1020 if (count == VICAM_MAX_FRAME_SIZE) {
1021 *ppos = 0;
1022 }
1023
1024 return count;
1025}
1026
1027
1028static int
1029vicam_mmap(struct file *file, struct vm_area_struct *vma)
1030{
1031 // TODO: allocate the raw frame buffer if necessary
1032 unsigned long page, pos;
1033 unsigned long start = vma->vm_start;
1034 unsigned long size = vma->vm_end-vma->vm_start;
1035 struct vicam_camera *cam = file->private_data;
1036
1037 if (!cam)
1038 return -ENODEV;
1039
1040 DBG("vicam_mmap: %ld\n", size);
1041
1042 /* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
1043 * to the size the application requested for mmap and it was screwing apps up.
1044 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
1045 return -EINVAL;
1046 */
1047
1048 pos = (unsigned long)cam->framebuf;
1049 while (size > 0) {
1050 page = vmalloc_to_pfn((void *)pos);
1051 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
1052 return -EAGAIN;
1053
1054 start += PAGE_SIZE;
1055 pos += PAGE_SIZE;
1056 if (size > PAGE_SIZE)
1057 size -= PAGE_SIZE;
1058 else
1059 size = 0;
1060 }
1061
1062 return 0;
1063}
1064
1065#if defined(CONFIG_VIDEO_PROC_FS)
1066
1067static struct proc_dir_entry *vicam_proc_root = NULL;
1068
1069static int vicam_read_helper(char *page, char **start, off_t off,
1070 int count, int *eof, int value)
1071{
1072 char *out = page;
1073 int len;
1074
1075 out += sprintf(out, "%d",value);
1076
1077 len = out - page;
1078 len -= off;
1079 if (len < count) {
1080 *eof = 1;
1081 if (len <= 0)
1082 return 0;
1083 } else
1084 len = count;
1085
1086 *start = page + off;
1087 return len;
1088}
1089
1090static int vicam_read_proc_shutter(char *page, char **start, off_t off,
1091 int count, int *eof, void *data)
1092{
1093 return vicam_read_helper(page,start,off,count,eof,
1094 ((struct vicam_camera *)data)->shutter_speed);
1095}
1096
1097static int vicam_read_proc_gain(char *page, char **start, off_t off,
1098 int count, int *eof, void *data)
1099{
1100 return vicam_read_helper(page,start,off,count,eof,
1101 ((struct vicam_camera *)data)->gain);
1102}
1103
1104static int
1105vicam_write_proc_shutter(struct file *file, const char *buffer,
1106 unsigned long count, void *data)
1107{
1108 u16 stmp;
1109 char kbuf[8];
1110 struct vicam_camera *cam = (struct vicam_camera *) data;
1111
1112 if (count > 6)
1113 return -EINVAL;
1114
1115 if (copy_from_user(kbuf, buffer, count))
1116 return -EFAULT;
1117
1118 stmp = (u16) simple_strtoul(kbuf, NULL, 10);
1119 if (stmp < 4 || stmp > 32000)
1120 return -EINVAL;
1121
1122 cam->shutter_speed = stmp;
1123
1124 return count;
1125}
1126
1127static int
1128vicam_write_proc_gain(struct file *file, const char *buffer,
1129 unsigned long count, void *data)
1130{
1131 u16 gtmp;
1132 char kbuf[8];
1133
1134 struct vicam_camera *cam = (struct vicam_camera *) data;
1135
1136 if (count > 4)
1137 return -EINVAL;
1138
1139 if (copy_from_user(kbuf, buffer, count))
1140 return -EFAULT;
1141
1142 gtmp = (u16) simple_strtoul(kbuf, NULL, 10);
1143 if (gtmp > 255)
1144 return -EINVAL;
1145 cam->gain = gtmp;
1146
1147 return count;
1148}
1149
1150static void
1151vicam_create_proc_root(void)
1152{
1153 vicam_proc_root = proc_mkdir("video/vicam", NULL);
1154
1155 if (vicam_proc_root)
1156 vicam_proc_root->owner = THIS_MODULE;
1157 else
1158 printk(KERN_ERR
1159 "could not create /proc entry for vicam!");
1160}
1161
1162static void
1163vicam_destroy_proc_root(void)
1164{
1165 if (vicam_proc_root)
1166 remove_proc_entry("video/vicam", 0);
1167}
1168
1169static void
1170vicam_create_proc_entry(struct vicam_camera *cam)
1171{
1172 char name[64];
1173 struct proc_dir_entry *ent;
1174
1175 DBG(KERN_INFO "vicam: creating proc entry\n");
1176
1177 if (!vicam_proc_root || !cam) {
1178 printk(KERN_INFO
1179 "vicam: could not create proc entry, %s pointer is null.\n",
1180 (!cam ? "camera" : "root"));
1181 return;
1182 }
1183
1184 sprintf(name, "video%d", cam->vdev.minor);
1185
1186 cam->proc_dir = proc_mkdir(name, vicam_proc_root);
1187
1188 if ( !cam->proc_dir )
1189 return; // FIXME: We should probably return an error here
1190
1191 ent = create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR,
1192 cam->proc_dir);
1193 if (ent) {
1194 ent->data = cam;
1195 ent->read_proc = vicam_read_proc_shutter;
1196 ent->write_proc = vicam_write_proc_shutter;
1197 ent->size = 64;
1198 }
1199
1200 ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR,
1201 cam->proc_dir);
1202 if (ent) {
1203 ent->data = cam;
1204 ent->read_proc = vicam_read_proc_gain;
1205 ent->write_proc = vicam_write_proc_gain;
1206 ent->size = 64;
1207 }
1208}
1209
1210static void
1211vicam_destroy_proc_entry(void *ptr)
1212{
1213 struct vicam_camera *cam = (struct vicam_camera *) ptr;
1214 char name[16];
1215
1216 if ( !cam->proc_dir )
1217 return;
1218
1219 sprintf(name, "video%d", cam->vdev.minor);
1220 remove_proc_entry("shutter", cam->proc_dir);
1221 remove_proc_entry("gain", cam->proc_dir);
1222 remove_proc_entry(name,vicam_proc_root);
1223 cam->proc_dir = NULL;
1224
1225}
1226
1227#else
1228static inline void vicam_create_proc_root(void) { }
1229static inline void vicam_destroy_proc_root(void) { }
1230static inline void vicam_create_proc_entry(struct vicam_camera *cam) { }
1231static inline void vicam_destroy_proc_entry(void *ptr) { }
1232#endif
1233
1234static struct file_operations vicam_fops = {
1235 .owner = THIS_MODULE,
1236 .open = vicam_open,
1237 .release = vicam_close,
1238 .read = vicam_read,
1239 .mmap = vicam_mmap,
1240 .ioctl = vicam_ioctl,
1241 .compat_ioctl = v4l_compat_ioctl32,
1242 .llseek = no_llseek,
1243};
1244
1245static struct video_device vicam_template = {
1246 .owner = THIS_MODULE,
1247 .name = "ViCam-based USB Camera",
1248 .type = VID_TYPE_CAPTURE,
1249 .hardware = VID_HARDWARE_VICAM,
1250 .fops = &vicam_fops,
1251 .minor = -1,
1252};
1253
1254/* table of devices that work with this driver */
1255static struct usb_device_id vicam_table[] = {
1256 {USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
1257 {} /* Terminating entry */
1258};
1259
1260MODULE_DEVICE_TABLE(usb, vicam_table);
1261
1262static struct usb_driver vicam_driver = {
1263 .name = "vicam",
1264 .probe = vicam_probe,
1265 .disconnect = vicam_disconnect,
1266 .id_table = vicam_table
1267};
1268
1269/**
1270 * vicam_probe
1271 * @intf: the interface
1272 * @id: the device id
1273 *
1274 * Called by the usb core when a new device is connected that it thinks
1275 * this driver might be interested in.
1276 */
1277static int
1278vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
1279{
1280 struct usb_device *dev = interface_to_usbdev(intf);
1281 int bulkEndpoint = 0;
1282 const struct usb_host_interface *interface;
1283 const struct usb_endpoint_descriptor *endpoint;
1284 struct vicam_camera *cam;
1285
1286 printk(KERN_INFO "ViCam based webcam connected\n");
1287
1288 interface = intf->cur_altsetting;
1289
1290 DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
1291 interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
1292 endpoint = &interface->endpoint[0].desc;
1293
1294 if ((endpoint->bEndpointAddress & 0x80) &&
1295 ((endpoint->bmAttributes & 3) == 0x02)) {
1296 /* we found a bulk in endpoint */
1297 bulkEndpoint = endpoint->bEndpointAddress;
1298 } else {
1299 printk(KERN_ERR
1300 "No bulk in endpoint was found ?! (this is bad)\n");
1301 }
1302
1303 if ((cam =
1304 kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
1305 printk(KERN_WARNING
1306 "could not allocate kernel memory for vicam_camera struct\n");
1307 return -ENOMEM;
1308 }
1309
1310 memset(cam, 0, sizeof (struct vicam_camera));
1311
1312 cam->shutter_speed = 15;
1313
1314 mutex_init(&cam->cam_lock);
1315
1316 memcpy(&cam->vdev, &vicam_template,
1317 sizeof (vicam_template));
1318 cam->vdev.priv = cam; // sort of a reverse mapping for those functions that get vdev only
1319
1320 cam->udev = dev;
1321 cam->bulkEndpoint = bulkEndpoint;
1322
1323 if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {
1324 kfree(cam);
1325 printk(KERN_WARNING "video_register_device failed\n");
1326 return -EIO;
1327 }
1328
1329 vicam_create_proc_entry(cam);
1330
1331 printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
1332
1333 usb_set_intfdata (intf, cam);
1334
1335 return 0;
1336}
1337
1338static void
1339vicam_disconnect(struct usb_interface *intf)
1340{
1341 int open_count;
1342 struct vicam_camera *cam = usb_get_intfdata (intf);
1343 usb_set_intfdata (intf, NULL);
1344
1345 /* we must unregister the device before taking its
1346 * cam_lock. This is because the video open call
1347 * holds the same lock as video unregister. if we
1348 * unregister inside of the cam_lock and open also
1349 * uses the cam_lock, we get deadlock.
1350 */
1351
1352 video_unregister_device(&cam->vdev);
1353
1354 /* stop the camera from being used */
1355
1356 mutex_lock(&cam->cam_lock);
1357
1358 /* mark the camera as gone */
1359
1360 cam->udev = NULL;
1361
1362 vicam_destroy_proc_entry(cam);
1363
1364 /* the only thing left to do is synchronize with
1365 * our close/release function on who should release
1366 * the camera memory. if there are any users using the
1367 * camera, it's their job. if there are no users,
1368 * it's ours.
1369 */
1370
1371 open_count = cam->open_count;
1372
1373 mutex_unlock(&cam->cam_lock);
1374
1375 if (!open_count) {
1376 kfree(cam);
1377 }
1378
1379 printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
1380}
1381
1382/*
1383 */
1384static int __init
1385usb_vicam_init(void)
1386{
1387 int retval;
1388 DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
1389 vicam_create_proc_root();
1390 retval = usb_register(&vicam_driver);
1391 if (retval)
1392 printk(KERN_WARNING "usb_register failed!\n");
1393 return retval;
1394}
1395
1396static void __exit
1397usb_vicam_exit(void)
1398{
1399 DBG(KERN_INFO
1400 "ViCam-based WebCam driver shutdown\n");
1401
1402 usb_deregister(&vicam_driver);
1403 vicam_destroy_proc_root();
1404}
1405
1406module_init(usb_vicam_init);
1407module_exit(usb_vicam_exit);
1408
1409MODULE_AUTHOR(DRIVER_AUTHOR);
1410MODULE_DESCRIPTION(DRIVER_DESC);
1411MODULE_LICENSE("GPL");