headers: smp_lock.h redux
[linux-block.git] / drivers / media / video / se401.c
CommitLineData
1da177e4
LT
1/*
2 * Endpoints (formerly known as AOX) se401 USB Camera Driver
3 *
4 * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
5 *
6 * Still somewhat based on the Linux ov511 driver.
d56410e0 7 *
1da177e4
LT
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 *
23 * Thanks to Endpoints Inc. (www.endpoints.com) for making documentation on
24 * their chipset available and supporting me while writing this driver.
25 * - Jeroen Vreeken
26 */
27
28static const char version[] = "0.24";
29
1da177e4
LT
30#include <linux/module.h>
31#include <linux/init.h>
32#include <linux/vmalloc.h>
33#include <linux/slab.h>
405f5571 34#include <linux/smp_lock.h>
1da177e4
LT
35#include <linux/pagemap.h>
36#include <linux/usb.h>
37#include "se401.h"
38
ff699e6b 39static int flickerless;
1da177e4
LT
40static int video_nr = -1;
41
aae40fd2 42static struct usb_device_id device_table[] = {
1da177e4
LT
43 { USB_DEVICE(0x03e8, 0x0004) },/* Endpoints/Aox SE401 */
44 { USB_DEVICE(0x0471, 0x030b) },/* Philips PCVC665K */
45 { USB_DEVICE(0x047d, 0x5001) },/* Kensington 67014 */
46 { USB_DEVICE(0x047d, 0x5002) },/* Kensington 6701(5/7) */
47 { USB_DEVICE(0x047d, 0x5003) },/* Kensington 67016 */
48 { }
49};
50
51MODULE_DEVICE_TABLE(usb, device_table);
52
53MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
54MODULE_DESCRIPTION("SE401 USB Camera Driver");
55MODULE_LICENSE("GPL");
56module_param(flickerless, int, 0);
aae40fd2
AC
57MODULE_PARM_DESC(flickerless,
58 "Net frequency to adjust exposure time to (0/50/60)");
1da177e4
LT
59module_param(video_nr, int, 0);
60
61static struct usb_driver se401_driver;
62
63
64/**********************************************************************
65 *
66 * Memory management
67 *
68 **********************************************************************/
69static void *rvmalloc(unsigned long size)
70{
71 void *mem;
72 unsigned long adr;
73
74 size = PAGE_ALIGN(size);
75 mem = vmalloc_32(size);
76 if (!mem)
77 return NULL;
78
79 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
80 adr = (unsigned long) mem;
81 while (size > 0) {
82 SetPageReserved(vmalloc_to_page((void *)adr));
aae40fd2
AC
83 adr += PAGE_SIZE;
84 size -= PAGE_SIZE;
1da177e4
LT
85 }
86
87 return mem;
88}
89
90static void rvfree(void *mem, unsigned long size)
91{
92 unsigned long adr;
93
94 if (!mem)
95 return;
96
97 adr = (unsigned long) mem;
98 while ((long) size > 0) {
99 ClearPageReserved(vmalloc_to_page((void *)adr));
aae40fd2
AC
100 adr += PAGE_SIZE;
101 size -= PAGE_SIZE;
1da177e4
LT
102 }
103 vfree(mem);
104}
105
106
107
108/****************************************************************************
109 *
110 * se401 register read/write functions
111 *
112 ***************************************************************************/
113
114static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
115 unsigned short value, unsigned char *cp, int size)
116{
aae40fd2 117 return usb_control_msg(
d56410e0
MCC
118 se401->dev,
119 set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
120 req,
121 (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
122 value,
123 0,
124 cp,
125 size,
126 1000
127 );
1da177e4
LT
128}
129
130static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
131 unsigned short param)
132{
133 /* specs say that the selector (address) should go in the value field
134 and the param in index, but in the logs of the windows driver they do
135 this the other way around...
136 */
aae40fd2 137 return usb_control_msg(
1da177e4
LT
138 se401->dev,
139 usb_sndctrlpipe(se401->dev, 0),
140 SE401_REQ_SET_EXT_FEATURE,
141 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
142 param,
143 selector,
d56410e0
MCC
144 NULL,
145 0,
146 1000
147 );
1da177e4
LT
148}
149
d56410e0
MCC
150static unsigned short se401_get_feature(struct usb_se401 *se401,
151 unsigned short selector)
1da177e4
LT
152{
153 /* For 'set' the selecetor should be in index, not sure if the spec is
154 wrong here to....
155 */
156 unsigned char cp[2];
aae40fd2 157 usb_control_msg(
d56410e0
MCC
158 se401->dev,
159 usb_rcvctrlpipe(se401->dev, 0),
160 SE401_REQ_GET_EXT_FEATURE,
161 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
162 0,
163 selector,
164 cp,
165 2,
166 1000
167 );
1da177e4
LT
168 return cp[0]+cp[1]*256;
169}
170
171/****************************************************************************
172 *
173 * Camera control
174 *
175 ***************************************************************************/
176
177
178static int se401_send_pict(struct usb_se401 *se401)
179{
aae40fd2
AC
180 /* integration time low */
181 se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);
182 /* integration time mid */
183 se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);
184 /* integration time mid */
185 se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);
186 /* reset level value */
187 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
188 /* red color gain */
189 se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);
190 /* green color gain */
191 se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);
192 /* blue color gain */
193 se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);
d56410e0 194
1da177e4
LT
195 return 0;
196}
197
198static void se401_set_exposure(struct usb_se401 *se401, int brightness)
199{
aae40fd2
AC
200 int integration = brightness << 5;
201
202 if (flickerless == 50)
203 integration = integration-integration % 106667;
204 if (flickerless == 60)
205 integration = integration-integration % 88889;
206 se401->brightness = integration >> 5;
207 se401->expose_h = (integration >> 16) & 0xff;
208 se401->expose_m = (integration >> 8) & 0xff;
209 se401->expose_l = integration & 0xff;
1da177e4
LT
210}
211
212static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
213{
aae40fd2
AC
214 p->brightness = se401->brightness;
215 if (se401->enhance)
216 p->whiteness = 32768;
217 else
218 p->whiteness = 0;
219
220 p->colour = 65535;
221 p->contrast = 65535;
222 p->hue = se401->rgain << 10;
223 p->palette = se401->palette;
224 p->depth = 3; /* rgb24 */
1da177e4
LT
225 return 0;
226}
227
228
229static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
230{
231 if (p->palette != VIDEO_PALETTE_RGB24)
232 return 1;
aae40fd2
AC
233 se401->palette = p->palette;
234 if (p->hue != se401->hue) {
235 se401->rgain = p->hue >> 10;
236 se401->bgain = 0x40-(p->hue >> 10);
237 se401->hue = p->hue;
1da177e4 238 }
aae40fd2 239 if (p->brightness != se401->brightness)
1da177e4 240 se401_set_exposure(se401, p->brightness);
aae40fd2
AC
241
242 if (p->whiteness >= 32768)
243 se401->enhance = 1;
244 else
245 se401->enhance = 0;
1da177e4
LT
246 se401_send_pict(se401);
247 se401_send_pict(se401);
248 return 0;
249}
250
251/*
252 Hyundai have some really nice docs about this and other sensor related
253 stuff on their homepage: www.hei.co.kr
254*/
255static void se401_auto_resetlevel(struct usb_se401 *se401)
256{
257 unsigned int ahrc, alrc;
aae40fd2 258 int oldreset = se401->resetlevel;
1da177e4
LT
259
260 /* For some reason this normally read-only register doesn't get reset
261 to zero after reading them just once...
262 */
d56410e0 263 se401_get_feature(se401, HV7131_REG_HIREFNOH);
1da177e4
LT
264 se401_get_feature(se401, HV7131_REG_HIREFNOL);
265 se401_get_feature(se401, HV7131_REG_LOREFNOH);
266 se401_get_feature(se401, HV7131_REG_LOREFNOL);
aae40fd2 267 ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
1da177e4 268 se401_get_feature(se401, HV7131_REG_HIREFNOL);
aae40fd2 269 alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
1da177e4
LT
270 se401_get_feature(se401, HV7131_REG_LOREFNOL);
271
272 /* Not an exact science, but it seems to work pretty well... */
273 if (alrc > 10) {
aae40fd2 274 while (alrc >= 10 && se401->resetlevel < 63) {
1da177e4 275 se401->resetlevel++;
aae40fd2 276 alrc /= 2;
1da177e4
LT
277 }
278 } else if (ahrc > 20) {
aae40fd2 279 while (ahrc >= 20 && se401->resetlevel > 0) {
1da177e4 280 se401->resetlevel--;
aae40fd2 281 ahrc /= 2;
1da177e4
LT
282 }
283 }
aae40fd2 284 if (se401->resetlevel != oldreset)
1da177e4
LT
285 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
286
287 return;
288}
289
290/* irq handler for snapshot button */
7d12e780 291static void se401_button_irq(struct urb *urb)
1da177e4
LT
292{
293 struct usb_se401 *se401 = urb->context;
294 int status;
d56410e0 295
1da177e4 296 if (!se401->dev) {
a482f327 297 dev_info(&urb->dev->dev, "device vapourished\n");
1da177e4
LT
298 return;
299 }
d56410e0 300
1da177e4
LT
301 switch (urb->status) {
302 case 0:
303 /* success */
304 break;
305 case -ECONNRESET:
306 case -ENOENT:
307 case -ESHUTDOWN:
308 /* this urb is terminated, clean up */
aae40fd2
AC
309 dbg("%s - urb shutting down with status: %d",
310 __func__, urb->status);
1da177e4
LT
311 return;
312 default:
aae40fd2
AC
313 dbg("%s - nonzero urb status received: %d",
314 __func__, urb->status);
1da177e4
LT
315 goto exit;
316 }
317
aae40fd2 318 if (urb->actual_length >= 2)
1da177e4 319 if (se401->button)
aae40fd2 320 se401->buttonpressed = 1;
1da177e4 321exit:
aae40fd2 322 status = usb_submit_urb(urb, GFP_ATOMIC);
1da177e4 323 if (status)
aae40fd2 324 err("%s - usb_submit_urb failed with result %d",
7e28adb2 325 __func__, status);
1da177e4
LT
326}
327
7d12e780 328static void se401_video_irq(struct urb *urb)
1da177e4
LT
329{
330 struct usb_se401 *se401 = urb->context;
331 int length = urb->actual_length;
332
333 /* ohoh... */
334 if (!se401->streaming)
335 return;
336
337 if (!se401->dev) {
a482f327 338 dev_info(&urb->dev->dev, "device vapourished\n");
1da177e4
LT
339 return;
340 }
341
342 /* 0 sized packets happen if we are to fast, but sometimes the camera
343 keeps sending them forever...
344 */
345 if (length && !urb->status) {
aae40fd2
AC
346 se401->nullpackets = 0;
347 switch (se401->scratch[se401->scratch_next].state) {
348 case BUFFER_READY:
349 case BUFFER_BUSY:
350 se401->dropped++;
351 break;
352 case BUFFER_UNUSED:
353 memcpy(se401->scratch[se401->scratch_next].data,
354 (unsigned char *)urb->transfer_buffer, length);
355 se401->scratch[se401->scratch_next].state
356 = BUFFER_READY;
357 se401->scratch[se401->scratch_next].offset
358 = se401->bayeroffset;
359 se401->scratch[se401->scratch_next].length = length;
360 if (waitqueue_active(&se401->wq))
361 wake_up_interruptible(&se401->wq);
362 se401->scratch_overflow = 0;
363 se401->scratch_next++;
364 if (se401->scratch_next >= SE401_NUMSCRATCH)
365 se401->scratch_next = 0;
366 break;
1da177e4 367 }
aae40fd2
AC
368 se401->bayeroffset += length;
369 if (se401->bayeroffset >= se401->cheight * se401->cwidth)
370 se401->bayeroffset = 0;
1da177e4
LT
371 } else {
372 se401->nullpackets++;
aae40fd2
AC
373 if (se401->nullpackets > SE401_MAX_NULLPACKETS)
374 if (waitqueue_active(&se401->wq))
1da177e4 375 wake_up_interruptible(&se401->wq);
1da177e4
LT
376 }
377
378 /* Resubmit urb for new data */
aae40fd2
AC
379 urb->status = 0;
380 urb->dev = se401->dev;
381 if (usb_submit_urb(urb, GFP_KERNEL))
a482f327 382 dev_info(&urb->dev->dev, "urb burned down\n");
1da177e4
LT
383 return;
384}
385
386static void se401_send_size(struct usb_se401 *se401, int width, int height)
387{
aae40fd2
AC
388 int i = 0;
389 int mode = 0x03; /* No compression */
390 int sendheight = height;
391 int sendwidth = width;
1da177e4
LT
392
393 /* JangGu compression can only be used with the camera supported sizes,
394 but bayer seems to work with any size that fits on the sensor.
395 We check if we can use compression with the current size with either
396 4 or 16 times subcapturing, if not we use uncompressed bayer data
397 but this will result in cutouts of the maximum size....
398 */
aae40fd2
AC
399 while (i < se401->sizes && !(se401->width[i] == width &&
400 se401->height[i] == height))
1da177e4 401 i++;
aae40fd2
AC
402 while (i < se401->sizes) {
403 if (se401->width[i] == width * 2 &&
404 se401->height[i] == height * 2) {
405 sendheight = se401->height[i];
406 sendwidth = se401->width[i];
407 mode = 0x40;
1da177e4 408 }
aae40fd2
AC
409 if (se401->width[i] == width * 4 &&
410 se401->height[i] == height * 4) {
411 sendheight = se401->height[i];
412 sendwidth = se401->width[i];
413 mode = 0x42;
1da177e4
LT
414 }
415 i++;
416 }
417
418 se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
419 se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
420 se401_set_feature(se401, SE401_OPERATINGMODE, mode);
421
aae40fd2
AC
422 if (mode == 0x03)
423 se401->format = FMT_BAYER;
424 else
425 se401->format = FMT_JANGGU;
1da177e4
LT
426}
427
428/*
429 In this function se401_send_pict is called several times,
430 for some reason (depending on the state of the sensor and the phase of
431 the moon :) doing this only in either place doesn't always work...
432*/
433static int se401_start_stream(struct usb_se401 *se401)
434{
435 struct urb *urb;
aae40fd2
AC
436 int err = 0, i;
437 se401->streaming = 1;
1da177e4 438
d56410e0
MCC
439 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
440 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1da177e4
LT
441
442 /* Set picture settings */
aae40fd2
AC
443 /* windowed + pix intg */
444 se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);
1da177e4
LT
445 se401_send_pict(se401);
446
447 se401_send_size(se401, se401->cwidth, se401->cheight);
448
aae40fd2
AC
449 se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE,
450 0, NULL, 0);
1da177e4
LT
451
452 /* Do some memory allocation */
aae40fd2
AC
453 for (i = 0; i < SE401_NUMFRAMES; i++) {
454 se401->frame[i].data = se401->fbuf + i * se401->maxframesize;
455 se401->frame[i].curpix = 0;
1da177e4 456 }
aae40fd2
AC
457 for (i = 0; i < SE401_NUMSBUF; i++) {
458 se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
fd51c697 459 if (!se401->sbuf[i].data) {
aae40fd2 460 for (i = i - 1; i >= 0; i--) {
fd51c697
AC
461 kfree(se401->sbuf[i].data);
462 se401->sbuf[i].data = NULL;
463 }
464 return -ENOMEM;
465 }
1da177e4
LT
466 }
467
aae40fd2
AC
468 se401->bayeroffset = 0;
469 se401->scratch_next = 0;
470 se401->scratch_use = 0;
471 se401->scratch_overflow = 0;
472 for (i = 0; i < SE401_NUMSCRATCH; i++) {
473 se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
fd51c697 474 if (!se401->scratch[i].data) {
aae40fd2 475 for (i = i - 1; i >= 0; i--) {
fd51c697
AC
476 kfree(se401->scratch[i].data);
477 se401->scratch[i].data = NULL;
478 }
479 goto nomem_sbuf;
480 }
aae40fd2 481 se401->scratch[i].state = BUFFER_UNUSED;
1da177e4
LT
482 }
483
aae40fd2
AC
484 for (i = 0; i < SE401_NUMSBUF; i++) {
485 urb = usb_alloc_urb(0, GFP_KERNEL);
486 if (!urb) {
487 for (i = i - 1; i >= 0; i--) {
fd51c697
AC
488 usb_kill_urb(se401->urb[i]);
489 usb_free_urb(se401->urb[i]);
490 se401->urb[i] = NULL;
491 }
492 goto nomem_scratch;
493 }
1da177e4
LT
494
495 usb_fill_bulk_urb(urb, se401->dev,
496 usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
497 se401->sbuf[i].data, SE401_PACKETSIZE,
498 se401_video_irq,
499 se401);
500
aae40fd2 501 se401->urb[i] = urb;
1da177e4 502
aae40fd2
AC
503 err = usb_submit_urb(se401->urb[i], GFP_KERNEL);
504 if (err)
1da177e4
LT
505 err("urb burned down");
506 }
507
aae40fd2 508 se401->framecount = 0;
1da177e4
LT
509
510 return 0;
fd51c697
AC
511
512 nomem_scratch:
aae40fd2 513 for (i = 0; i < SE401_NUMSCRATCH; i++) {
fd51c697
AC
514 kfree(se401->scratch[i].data);
515 se401->scratch[i].data = NULL;
516 }
517 nomem_sbuf:
aae40fd2 518 for (i = 0; i < SE401_NUMSBUF; i++) {
fd51c697
AC
519 kfree(se401->sbuf[i].data);
520 se401->sbuf[i].data = NULL;
521 }
522 return -ENOMEM;
1da177e4
LT
523}
524
525static int se401_stop_stream(struct usb_se401 *se401)
526{
527 int i;
528
529 if (!se401->streaming || !se401->dev)
530 return 1;
531
aae40fd2 532 se401->streaming = 0;
1da177e4
LT
533
534 se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
535
536 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
537 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
538
aae40fd2
AC
539 for (i = 0; i < SE401_NUMSBUF; i++)
540 if (se401->urb[i]) {
541 usb_kill_urb(se401->urb[i]);
542 usb_free_urb(se401->urb[i]);
543 se401->urb[i] = NULL;
544 kfree(se401->sbuf[i].data);
545 }
546 for (i = 0; i < SE401_NUMSCRATCH; i++) {
1da177e4 547 kfree(se401->scratch[i].data);
aae40fd2 548 se401->scratch[i].data = NULL;
1da177e4
LT
549 }
550
551 return 0;
552}
553
554static int se401_set_size(struct usb_se401 *se401, int width, int height)
555{
aae40fd2 556 int wasstreaming = se401->streaming;
1da177e4 557 /* Check to see if we need to change */
aae40fd2 558 if (se401->cwidth == width && se401->cheight == height)
1da177e4
LT
559 return 0;
560
561 /* Check for a valid mode */
562 if (!width || !height)
563 return 1;
564 if ((width & 1) || (height & 1))
565 return 1;
aae40fd2 566 if (width > se401->width[se401->sizes-1])
1da177e4 567 return 1;
aae40fd2 568 if (height > se401->height[se401->sizes-1])
1da177e4
LT
569 return 1;
570
571 /* Stop a current stream and start it again at the new size */
572 if (wasstreaming)
573 se401_stop_stream(se401);
aae40fd2
AC
574 se401->cwidth = width;
575 se401->cheight = height;
1da177e4
LT
576 if (wasstreaming)
577 se401_start_stream(se401);
578 return 0;
579}
580
581
582/****************************************************************************
583 *
584 * Video Decoding
585 *
586 ***************************************************************************/
587
588/*
589 This shouldn't really be done in a v4l driver....
590 But it does make the image look a lot more usable.
591 Basically it lifts the dark pixels more than the light pixels.
592*/
593static inline void enhance_picture(unsigned char *frame, int len)
594{
595 while (len--) {
aae40fd2 596 *frame = (((*frame^255)*(*frame^255))/255)^255;
1da177e4
LT
597 frame++;
598 }
599}
600
601static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
602{
aae40fd2
AC
603 struct se401_frame *frame = &se401->frame[se401->curframe];
604 int linelength = se401->cwidth * 3;
1da177e4
LT
605
606 if (frame->curlinepix >= linelength) {
aae40fd2
AC
607 frame->curlinepix = 0;
608 frame->curline += linelength;
1da177e4
LT
609 }
610
611 /* First three are absolute, all others relative.
d56410e0 612 * Format is rgb from right to left (mirrorred image),
1da177e4 613 * we flip it to get bgr from left to right. */
aae40fd2
AC
614 if (frame->curlinepix < 3)
615 *(frame->curline-frame->curlinepix) = 1 + data * 4;
616 else
617 *(frame->curline-frame->curlinepix) =
618 *(frame->curline-frame->curlinepix + 3) + data * 4;
1da177e4
LT
619 frame->curlinepix++;
620}
621
aae40fd2
AC
622static inline void decode_JangGu_vlc(struct usb_se401 *se401,
623 unsigned char *data, int bit_exp, int packetlength)
1da177e4 624{
aae40fd2
AC
625 int pos = 0;
626 int vlc_cod = 0;
627 int vlc_size = 0;
628 int vlc_data = 0;
1da177e4
LT
629 int bit_cur;
630 int bit;
aae40fd2 631 data += 4;
1da177e4 632 while (pos < packetlength) {
aae40fd2 633 bit_cur = 8;
1da177e4 634 while (bit_cur && bit_exp) {
aae40fd2 635 bit = ((*data) >> (bit_cur-1))&1;
1da177e4
LT
636 if (!vlc_cod) {
637 if (bit) {
638 vlc_size++;
639 } else {
aae40fd2 640 if (!vlc_size)
1da177e4 641 decode_JangGu_integrate(se401, 0);
aae40fd2
AC
642 else {
643 vlc_cod = 2;
644 vlc_data = 0;
1da177e4
LT
645 }
646 }
647 } else {
aae40fd2 648 if (vlc_cod == 2) {
1da177e4 649 if (!bit)
aae40fd2 650 vlc_data = -(1 << vlc_size) + 1;
1da177e4
LT
651 vlc_cod--;
652 }
653 vlc_size--;
aae40fd2 654 vlc_data += bit << vlc_size;
1da177e4
LT
655 if (!vlc_size) {
656 decode_JangGu_integrate(se401, vlc_data);
aae40fd2 657 vlc_cod = 0;
1da177e4
LT
658 }
659 }
660 bit_cur--;
661 bit_exp--;
662 }
663 pos++;
664 data++;
665 }
666}
667
aae40fd2
AC
668static inline void decode_JangGu(struct usb_se401 *se401,
669 struct se401_scratch *buffer)
1da177e4 670{
aae40fd2
AC
671 unsigned char *data = buffer->data;
672 int len = buffer->length;
673 int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size;
674 int datapos = 0;
1da177e4
LT
675
676 /* New image? */
677 if (!se401->frame[se401->curframe].curpix) {
aae40fd2
AC
678 se401->frame[se401->curframe].curlinepix = 0;
679 se401->frame[se401->curframe].curline =
1da177e4 680 se401->frame[se401->curframe].data+
aae40fd2
AC
681 se401->cwidth * 3 - 1;
682 if (se401->frame[se401->curframe].grabstate == FRAME_READY)
683 se401->frame[se401->curframe].grabstate = FRAME_GRABBING;
684 se401->vlcdatapos = 0;
1da177e4
LT
685 }
686 while (datapos < len) {
aae40fd2 687 size = 1024 - se401->vlcdatapos;
1da177e4 688 if (size+datapos > len)
aae40fd2 689 size = len-datapos;
1da177e4 690 memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
aae40fd2
AC
691 se401->vlcdatapos += size;
692 packetlength = 0;
1da177e4 693 if (se401->vlcdatapos >= 4) {
aae40fd2
AC
694 bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8);
695 pix_exp = se401->vlcdata[1] +
696 ((se401->vlcdata[0] & 0x3f) << 8);
697 frameinfo = se401->vlcdata[0] & 0xc0;
698 packetlength = ((bit_exp + 47) >> 4) << 1;
1da177e4 699 if (packetlength > 1024) {
aae40fd2
AC
700 se401->vlcdatapos = 0;
701 datapos = len;
702 packetlength = 0;
1da177e4 703 se401->error++;
aae40fd2 704 se401->frame[se401->curframe].curpix = 0;
1da177e4
LT
705 }
706 }
707 if (packetlength && se401->vlcdatapos >= packetlength) {
aae40fd2
AC
708 decode_JangGu_vlc(se401, se401->vlcdata, bit_exp,
709 packetlength);
710 se401->frame[se401->curframe].curpix += pix_exp * 3;
711 datapos += size-(se401->vlcdatapos-packetlength);
712 se401->vlcdatapos = 0;
713 if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) {
714 if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) {
715 if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) {
716 se401->frame[se401->curframe].grabstate = FRAME_DONE;
1da177e4
LT
717 se401->framecount++;
718 se401->readcount++;
719 }
aae40fd2
AC
720 if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY)
721 se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1);
722 } else
1da177e4 723 se401->error++;
aae40fd2
AC
724 se401->frame[se401->curframe].curpix = 0;
725 datapos = len;
1da177e4 726 }
aae40fd2
AC
727 } else
728 datapos += size;
1da177e4
LT
729 }
730}
731
aae40fd2
AC
732static inline void decode_bayer(struct usb_se401 *se401,
733 struct se401_scratch *buffer)
1da177e4 734{
aae40fd2
AC
735 unsigned char *data = buffer->data;
736 int len = buffer->length;
737 int offset = buffer->offset;
738 int datasize = se401->cwidth * se401->cheight;
739 struct se401_frame *frame = &se401->frame[se401->curframe];
740 unsigned char *framedata = frame->data, *curline, *nextline;
741 int width = se401->cwidth;
742 int blineoffset = 0, bline;
743 int linelength = width * 3, i;
1da177e4 744
d56410e0 745
aae40fd2
AC
746 if (frame->curpix == 0) {
747 if (frame->grabstate == FRAME_READY)
748 frame->grabstate = FRAME_GRABBING;
1da177e4 749
aae40fd2
AC
750 frame->curline = framedata + linelength;
751 frame->curlinepix = 0;
1da177e4
LT
752 }
753
aae40fd2 754 if (offset != frame->curpix) {
1da177e4 755 /* Regard frame as lost :( */
aae40fd2 756 frame->curpix = 0;
1da177e4
LT
757 se401->error++;
758 return;
759 }
760
761 /* Check if we have to much data */
aae40fd2
AC
762 if (frame->curpix + len > datasize)
763 len = datasize-frame->curpix;
764
765 if (se401->cheight % 4)
766 blineoffset = 1;
767 bline = frame->curpix / se401->cwidth+blineoffset;
768
769 curline = frame->curline;
770 nextline = curline + linelength;
771 if (nextline >= framedata+datasize * 3)
772 nextline = curline;
1da177e4 773 while (len) {
aae40fd2
AC
774 if (frame->curlinepix >= width) {
775 frame->curlinepix -= width;
776 bline = frame->curpix / width + blineoffset;
777 curline += linelength*2;
778 nextline += linelength*2;
779 if (curline >= framedata+datasize * 3) {
1da177e4 780 frame->curlinepix++;
aae40fd2
AC
781 curline -= 3;
782 nextline -= 3;
1da177e4
LT
783 len--;
784 data++;
785 frame->curpix++;
786 }
787 if (nextline >= framedata+datasize*3)
aae40fd2 788 nextline = curline;
1da177e4 789 }
aae40fd2
AC
790 if (bline & 1) {
791 if (frame->curlinepix & 1) {
792 *(curline + 2) = *data;
793 *(curline - 1) = *data;
794 *(nextline + 2) = *data;
795 *(nextline - 1) = *data;
1da177e4 796 } else {
aae40fd2
AC
797 *(curline + 1) =
798 (*(curline + 1) + *data) / 2;
799 *(curline-2) =
800 (*(curline - 2) + *data) / 2;
801 *(nextline + 1) = *data;
802 *(nextline - 2) = *data;
1da177e4
LT
803 }
804 } else {
aae40fd2
AC
805 if (frame->curlinepix & 1) {
806 *(curline + 1) =
807 (*(curline + 1) + *data) / 2;
808 *(curline - 2) =
809 (*(curline - 2) + *data) / 2;
810 *(nextline + 1) = *data;
811 *(nextline - 2) = *data;
1da177e4 812 } else {
aae40fd2
AC
813 *curline = *data;
814 *(curline - 3) = *data;
815 *nextline = *data;
816 *(nextline - 3) = *data;
1da177e4
LT
817 }
818 }
819 frame->curlinepix++;
aae40fd2
AC
820 curline -= 3;
821 nextline -= 3;
1da177e4
LT
822 len--;
823 data++;
824 frame->curpix++;
825 }
aae40fd2 826 frame->curline = curline;
1da177e4 827
aae40fd2 828 if (frame->curpix >= datasize) {
1da177e4 829 /* Fix the top line */
aae40fd2
AC
830 framedata += linelength;
831 for (i = 0; i < linelength; i++) {
1da177e4 832 framedata--;
aae40fd2 833 *framedata = *(framedata + linelength);
1da177e4
LT
834 }
835 /* Fix the left side (green is already present) */
aae40fd2
AC
836 for (i = 0; i < se401->cheight; i++) {
837 *framedata = *(framedata + 3);
838 *(framedata + 1) = *(framedata + 4);
839 *(framedata + 2) = *(framedata + 5);
840 framedata += linelength;
1da177e4 841 }
aae40fd2
AC
842 frame->curpix = 0;
843 frame->grabstate = FRAME_DONE;
1da177e4
LT
844 se401->framecount++;
845 se401->readcount++;
aae40fd2
AC
846 if (se401->frame[(se401->curframe + 1) &
847 (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) {
848 se401->curframe = (se401->curframe+1) &
849 (SE401_NUMFRAMES-1);
1da177e4
LT
850 }
851 }
852}
853
854static int se401_newframe(struct usb_se401 *se401, int framenr)
855{
856 DECLARE_WAITQUEUE(wait, current);
aae40fd2 857 int errors = 0;
1da177e4
LT
858
859 while (se401->streaming &&
aae40fd2
AC
860 (se401->frame[framenr].grabstate == FRAME_READY ||
861 se401->frame[framenr].grabstate == FRAME_GRABBING)) {
862 if (!se401->frame[framenr].curpix)
1da177e4 863 errors++;
aae40fd2 864
1da177e4 865 wait_interruptible(
aae40fd2
AC
866 se401->scratch[se401->scratch_use].state != BUFFER_READY,
867 &se401->wq, &wait);
1da177e4 868 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
aae40fd2 869 se401->nullpackets = 0;
a482f327 870 dev_info(&se401->dev->dev,
aae40fd2 871 "too many null length packets, restarting capture\n");
1da177e4 872 se401_stop_stream(se401);
d56410e0 873 se401_start_stream(se401);
1da177e4 874 } else {
aae40fd2
AC
875 if (se401->scratch[se401->scratch_use].state !=
876 BUFFER_READY) {
877 se401->frame[framenr].grabstate = FRAME_ERROR;
1da177e4
LT
878 return -EIO;
879 }
aae40fd2
AC
880 se401->scratch[se401->scratch_use].state = BUFFER_BUSY;
881 if (se401->format == FMT_JANGGU)
882 decode_JangGu(se401,
883 &se401->scratch[se401->scratch_use]);
884 else
885 decode_bayer(se401,
886 &se401->scratch[se401->scratch_use]);
887
888 se401->scratch[se401->scratch_use].state =
889 BUFFER_UNUSED;
1da177e4 890 se401->scratch_use++;
aae40fd2
AC
891 if (se401->scratch_use >= SE401_NUMSCRATCH)
892 se401->scratch_use = 0;
1da177e4 893 if (errors > SE401_MAX_ERRORS) {
aae40fd2 894 errors = 0;
a482f327 895 dev_info(&se401->dev->dev,
aae40fd2 896 "too many errors, restarting capture\n");
1da177e4
LT
897 se401_stop_stream(se401);
898 se401_start_stream(se401);
899 }
900 }
901 }
902
aae40fd2 903 if (se401->frame[framenr].grabstate == FRAME_DONE)
1da177e4 904 if (se401->enhance)
aae40fd2
AC
905 enhance_picture(se401->frame[framenr].data,
906 se401->cheight * se401->cwidth * 3);
1da177e4
LT
907 return 0;
908}
909
aae40fd2 910static void usb_se401_remove_disconnected(struct usb_se401 *se401)
1da177e4
LT
911{
912 int i;
913
d56410e0 914 se401->dev = NULL;
1da177e4 915
aae40fd2 916 for (i = 0; i < SE401_NUMSBUF; i++)
1bc3c9e1
JJ
917 if (se401->urb[i]) {
918 usb_kill_urb(se401->urb[i]);
919 usb_free_urb(se401->urb[i]);
920 se401->urb[i] = NULL;
921 kfree(se401->sbuf[i].data);
922 }
aae40fd2
AC
923
924 for (i = 0; i < SE401_NUMSCRATCH; i++)
1da177e4 925 kfree(se401->scratch[i].data);
aae40fd2 926
1da177e4
LT
927 if (se401->inturb) {
928 usb_kill_urb(se401->inturb);
929 usb_free_urb(se401->inturb);
930 }
a482f327 931 dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name);
1da177e4 932
d56410e0 933 /* Free the memory */
1da177e4
LT
934 kfree(se401->width);
935 kfree(se401->height);
936 kfree(se401);
937}
938
939
940
941/****************************************************************************
942 *
943 * Video4Linux
944 *
945 ***************************************************************************/
946
947
bec43661 948static int se401_open(struct file *file)
1da177e4
LT
949{
950 struct video_device *dev = video_devdata(file);
951 struct usb_se401 *se401 = (struct usb_se401 *)dev;
952 int err = 0;
953
d56dc612
HV
954 lock_kernel();
955 if (se401->user) {
956 unlock_kernel();
1da177e4 957 return -EBUSY;
d56dc612 958 }
1da177e4
LT
959 se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
960 if (se401->fbuf)
961 file->private_data = dev;
d56410e0 962 else
1da177e4
LT
963 err = -ENOMEM;
964 se401->user = !err;
d56dc612 965 unlock_kernel();
1da177e4
LT
966
967 return err;
968}
969
bec43661 970static int se401_close(struct file *file)
1da177e4
LT
971{
972 struct video_device *dev = file->private_data;
d56410e0 973 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1da177e4
LT
974 int i;
975
976 rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
d56410e0 977 if (se401->removed) {
a482f327 978 dev_info(&se401->dev->dev, "device unregistered\n");
1da177e4 979 usb_se401_remove_disconnected(se401);
1da177e4 980 } else {
aae40fd2
AC
981 for (i = 0; i < SE401_NUMFRAMES; i++)
982 se401->frame[i].grabstate = FRAME_UNUSED;
1da177e4
LT
983 if (se401->streaming)
984 se401_stop_stream(se401);
aae40fd2 985 se401->user = 0;
1da177e4
LT
986 }
987 file->private_data = NULL;
988 return 0;
989}
990
069b7479 991static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
1da177e4
LT
992{
993 struct video_device *vdev = file->private_data;
d56410e0 994 struct usb_se401 *se401 = (struct usb_se401 *)vdev;
1da177e4 995
d56410e0
MCC
996 if (!se401->dev)
997 return -EIO;
1da177e4 998
d56410e0 999 switch (cmd) {
1da177e4
LT
1000 case VIDIOCGCAP:
1001 {
1002 struct video_capability *b = arg;
1003 strcpy(b->name, se401->camera_name);
1004 b->type = VID_TYPE_CAPTURE;
1005 b->channels = 1;
1006 b->audios = 0;
1007 b->maxwidth = se401->width[se401->sizes-1];
1008 b->maxheight = se401->height[se401->sizes-1];
1009 b->minwidth = se401->width[0];
1010 b->minheight = se401->height[0];
1011 return 0;
1012 }
1013 case VIDIOCGCHAN:
1014 {
1015 struct video_channel *v = arg;
1016
1017 if (v->channel != 0)
1018 return -EINVAL;
1019 v->flags = 0;
1020 v->tuners = 0;
1021 v->type = VIDEO_TYPE_CAMERA;
1022 strcpy(v->name, "Camera");
1023 return 0;
1024 }
1025 case VIDIOCSCHAN:
1026 {
1027 struct video_channel *v = arg;
1028
1029 if (v->channel != 0)
1030 return -EINVAL;
1031 return 0;
1032 }
d56410e0
MCC
1033 case VIDIOCGPICT:
1034 {
1da177e4
LT
1035 struct video_picture *p = arg;
1036
1037 se401_get_pict(se401, p);
1038 return 0;
1039 }
1040 case VIDIOCSPICT:
1041 {
1042 struct video_picture *p = arg;
1043
1044 if (se401_set_pict(se401, p))
1045 return -EINVAL;
1046 return 0;
1047 }
1048 case VIDIOCSWIN:
1049 {
1050 struct video_window *vw = arg;
1051
1052 if (vw->flags)
1053 return -EINVAL;
1054 if (vw->clipcount)
1055 return -EINVAL;
1056 if (se401_set_size(se401, vw->width, vw->height))
1057 return -EINVAL;
1058 return 0;
d56410e0 1059 }
1da177e4
LT
1060 case VIDIOCGWIN:
1061 {
1062 struct video_window *vw = arg;
1063
1064 vw->x = 0; /* FIXME */
1065 vw->y = 0;
1066 vw->chromakey = 0;
1067 vw->flags = 0;
1068 vw->clipcount = 0;
1069 vw->width = se401->cwidth;
1070 vw->height = se401->cheight;
1071 return 0;
1072 }
1073 case VIDIOCGMBUF:
1074 {
1075 struct video_mbuf *vm = arg;
1076 int i;
1077
1078 memset(vm, 0, sizeof(*vm));
1079 vm->size = SE401_NUMFRAMES * se401->maxframesize;
1080 vm->frames = SE401_NUMFRAMES;
aae40fd2 1081 for (i = 0; i < SE401_NUMFRAMES; i++)
1da177e4
LT
1082 vm->offsets[i] = se401->maxframesize * i;
1083 return 0;
1084 }
1085 case VIDIOCMCAPTURE:
1086 {
1087 struct video_mmap *vm = arg;
1088
1089 if (vm->format != VIDEO_PALETTE_RGB24)
1090 return -EINVAL;
1091 if (vm->frame >= SE401_NUMFRAMES)
1092 return -EINVAL;
1093 if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
1094 return -EBUSY;
1095
1096 /* Is this according to the v4l spec??? */
1097 if (se401_set_size(se401, vm->width, vm->height))
1098 return -EINVAL;
aae40fd2 1099 se401->frame[vm->frame].grabstate = FRAME_READY;
1da177e4
LT
1100
1101 if (!se401->streaming)
1102 se401_start_stream(se401);
1103
1104 /* Set the picture properties */
aae40fd2 1105 if (se401->framecount == 0)
1da177e4
LT
1106 se401_send_pict(se401);
1107 /* Calibrate the reset level after a few frames. */
aae40fd2 1108 if (se401->framecount % 20 == 1)
1da177e4
LT
1109 se401_auto_resetlevel(se401);
1110
1111 return 0;
1112 }
1113 case VIDIOCSYNC:
1114 {
1115 int *frame = arg;
aae40fd2 1116 int ret = 0;
1da177e4 1117
aae40fd2 1118 if (*frame < 0 || *frame >= SE401_NUMFRAMES)
1da177e4
LT
1119 return -EINVAL;
1120
aae40fd2
AC
1121 ret = se401_newframe(se401, *frame);
1122 se401->frame[*frame].grabstate = FRAME_UNUSED;
1da177e4
LT
1123 return ret;
1124 }
1125 case VIDIOCGFBUF:
1126 {
1127 struct video_buffer *vb = arg;
1128
1129 memset(vb, 0, sizeof(*vb));
1130 return 0;
1131 }
1132 case VIDIOCKEY:
1133 return 0;
1134 case VIDIOCCAPTURE:
1135 return -EINVAL;
1136 case VIDIOCSFBUF:
1137 return -EINVAL;
1138 case VIDIOCGTUNER:
1139 case VIDIOCSTUNER:
1140 return -EINVAL;
1141 case VIDIOCGFREQ:
1142 case VIDIOCSFREQ:
1143 return -EINVAL;
1144 case VIDIOCGAUDIO:
1145 case VIDIOCSAUDIO:
1146 return -EINVAL;
d56410e0
MCC
1147 default:
1148 return -ENOIOCTLCMD;
1149 } /* end switch */
1da177e4 1150
d56410e0 1151 return 0;
1da177e4
LT
1152}
1153
069b7479 1154static long se401_ioctl(struct file *file,
1da177e4
LT
1155 unsigned int cmd, unsigned long arg)
1156{
f473bf76 1157 return video_usercopy(file, cmd, arg, se401_do_ioctl);
1da177e4
LT
1158}
1159
1160static ssize_t se401_read(struct file *file, char __user *buf,
1161 size_t count, loff_t *ppos)
1162{
aae40fd2 1163 int realcount = count, ret = 0;
1da177e4
LT
1164 struct video_device *dev = file->private_data;
1165 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1166
1167
aae40fd2 1168 if (se401->dev == NULL)
1da177e4
LT
1169 return -EIO;
1170 if (realcount > se401->cwidth*se401->cheight*3)
aae40fd2 1171 realcount = se401->cwidth*se401->cheight*3;
1da177e4
LT
1172
1173 /* Shouldn't happen: */
aae40fd2 1174 if (se401->frame[0].grabstate == FRAME_GRABBING)
1da177e4 1175 return -EBUSY;
aae40fd2
AC
1176 se401->frame[0].grabstate = FRAME_READY;
1177 se401->frame[1].grabstate = FRAME_UNUSED;
1178 se401->curframe = 0;
1da177e4
LT
1179
1180 if (!se401->streaming)
1181 se401_start_stream(se401);
1182
1183 /* Set the picture properties */
aae40fd2 1184 if (se401->framecount == 0)
1da177e4
LT
1185 se401_send_pict(se401);
1186 /* Calibrate the reset level after a few frames. */
aae40fd2 1187 if (se401->framecount%20 == 1)
1da177e4
LT
1188 se401_auto_resetlevel(se401);
1189
aae40fd2 1190 ret = se401_newframe(se401, 0);
1da177e4 1191
aae40fd2 1192 se401->frame[0].grabstate = FRAME_UNUSED;
1da177e4 1193 if (ret)
d56410e0 1194 return ret;
1da177e4
LT
1195 if (copy_to_user(buf, se401->frame[0].data, realcount))
1196 return -EFAULT;
1197
1198 return realcount;
1199}
1200
1201static int se401_mmap(struct file *file, struct vm_area_struct *vma)
1202{
1203 struct video_device *dev = file->private_data;
1204 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1205 unsigned long start = vma->vm_start;
1206 unsigned long size = vma->vm_end-vma->vm_start;
1207 unsigned long page, pos;
1208
4186ecf8 1209 mutex_lock(&se401->lock);
1da177e4 1210
aae40fd2 1211 if (se401->dev == NULL) {
4186ecf8 1212 mutex_unlock(&se401->lock);
1da177e4
LT
1213 return -EIO;
1214 }
aae40fd2
AC
1215 if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1)
1216 & ~(PAGE_SIZE - 1))) {
4186ecf8 1217 mutex_unlock(&se401->lock);
1da177e4
LT
1218 return -EINVAL;
1219 }
1220 pos = (unsigned long)se401->fbuf;
1221 while (size > 0) {
1222 page = vmalloc_to_pfn((void *)pos);
1223 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
4186ecf8 1224 mutex_unlock(&se401->lock);
1da177e4
LT
1225 return -EAGAIN;
1226 }
aae40fd2
AC
1227 start += PAGE_SIZE;
1228 pos += PAGE_SIZE;
1da177e4 1229 if (size > PAGE_SIZE)
aae40fd2 1230 size -= PAGE_SIZE;
1da177e4
LT
1231 else
1232 size = 0;
1233 }
4186ecf8 1234 mutex_unlock(&se401->lock);
1da177e4 1235
d56410e0 1236 return 0;
1da177e4
LT
1237}
1238
bec43661 1239static const struct v4l2_file_operations se401_fops = {
aae40fd2 1240 .owner = THIS_MODULE,
d56410e0
MCC
1241 .open = se401_open,
1242 .release = se401_close,
1243 .read = se401_read,
1244 .mmap = se401_mmap,
1da177e4 1245 .ioctl = se401_ioctl,
1da177e4
LT
1246};
1247static struct video_device se401_template = {
d56410e0 1248 .name = "se401 USB camera",
1da177e4 1249 .fops = &se401_fops,
aa5e90af 1250 .release = video_device_release_empty,
1da177e4
LT
1251};
1252
1253
1254
1255/***************************/
1256static int se401_init(struct usb_se401 *se401, int button)
1257{
aae40fd2 1258 int i = 0, rc;
d56410e0 1259 unsigned char cp[0x40];
1da177e4 1260 char temp[200];
6f4d7239 1261 int slen;
1da177e4
LT
1262
1263 /* led on */
d56410e0 1264 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1da177e4
LT
1265
1266 /* get camera descriptor */
aae40fd2
AC
1267 rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0,
1268 cp, sizeof(cp));
6f4d7239 1269 if (cp[1] != 0x41) {
1da177e4
LT
1270 err("Wrong descriptor type");
1271 return 1;
1272 }
6f4d7239 1273 slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]);
1da177e4 1274
aae40fd2
AC
1275 se401->sizes = cp[4] + cp[5] * 256;
1276 se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1da177e4
LT
1277 if (!se401->width)
1278 return 1;
aae40fd2 1279 se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1da177e4
LT
1280 if (!se401->height) {
1281 kfree(se401->width);
1282 return 1;
1283 }
aae40fd2
AC
1284 for (i = 0; i < se401->sizes; i++) {
1285 se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256;
1286 se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256;
1da177e4 1287 }
aae40fd2
AC
1288 slen += snprintf(temp + slen, 200 - slen, " Sizes:");
1289 for (i = 0; i < se401->sizes; i++) {
1290 slen += snprintf(temp + slen, 200 - slen,
6f4d7239 1291 " %dx%d", se401->width[i], se401->height[i]);
1da177e4 1292 }
a482f327 1293 dev_info(&se401->dev->dev, "%s\n", temp);
aae40fd2
AC
1294 se401->maxframesize = se401->width[se401->sizes-1] *
1295 se401->height[se401->sizes - 1] * 3;
1da177e4 1296
aae40fd2
AC
1297 rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1298 se401->cwidth = cp[0]+cp[1]*256;
1299 rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1300 se401->cheight = cp[0]+cp[1]*256;
1da177e4 1301
33b4af91 1302 if (!(cp[2] & SE401_FORMAT_BAYER)) {
1da177e4
LT
1303 err("Bayer format not supported!");
1304 return 1;
1305 }
1306 /* set output mode (BAYER) */
aae40fd2
AC
1307 se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE,
1308 SE401_FORMAT_BAYER, NULL, 0);
1da177e4 1309
aae40fd2
AC
1310 rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1311 se401->brightness = cp[0]+cp[1]*256;
1da177e4 1312 /* some default values */
aae40fd2
AC
1313 se401->resetlevel = 0x2d;
1314 se401->rgain = 0x20;
1315 se401->ggain = 0x20;
1316 se401->bgain = 0x20;
1da177e4 1317 se401_set_exposure(se401, 20000);
aae40fd2
AC
1318 se401->palette = VIDEO_PALETTE_RGB24;
1319 se401->enhance = 1;
1320 se401->dropped = 0;
1321 se401->error = 0;
1322 se401->framecount = 0;
1323 se401->readcount = 0;
1da177e4
LT
1324
1325 /* Start interrupt transfers for snapshot button */
1326 if (button) {
aae40fd2 1327 se401->inturb = usb_alloc_urb(0, GFP_KERNEL);
1da177e4 1328 if (!se401->inturb) {
a482f327
GKH
1329 dev_info(&se401->dev->dev,
1330 "Allocation of inturb failed\n");
1da177e4
LT
1331 return 1;
1332 }
1333 usb_fill_int_urb(se401->inturb, se401->dev,
1334 usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1335 &se401->button, sizeof(se401->button),
1336 se401_button_irq,
1337 se401,
1338 8
1339 );
1340 if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
a482f327 1341 dev_info(&se401->dev->dev, "int urb burned down\n");
1da177e4
LT
1342 return 1;
1343 }
1344 } else
aae40fd2 1345 se401->inturb = NULL;
1da177e4 1346
d56410e0
MCC
1347 /* Flash the led */
1348 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1349 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1350 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1da177e4
LT
1351 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1352
d56410e0 1353 return 0;
1da177e4
LT
1354}
1355
1356static int se401_probe(struct usb_interface *intf,
1357 const struct usb_device_id *id)
1358{
1359 struct usb_device *dev = interface_to_usbdev(intf);
d56410e0
MCC
1360 struct usb_interface_descriptor *interface;
1361 struct usb_se401 *se401;
aae40fd2
AC
1362 char *camera_name = NULL;
1363 int button = 1;
1da177e4 1364
d56410e0
MCC
1365 /* We don't handle multi-config cameras */
1366 if (dev->descriptor.bNumConfigurations != 1)
1367 return -ENODEV;
1da177e4 1368
d56410e0 1369 interface = &intf->cur_altsetting->desc;
1da177e4 1370
d56410e0 1371 /* Is it an se401? */
aae40fd2
AC
1372 if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
1373 le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
1374 camera_name = "Endpoints/Aox SE401";
1375 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
1376 le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
1377 camera_name = "Philips PCVC665K";
1378 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1379 le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
1380 camera_name = "Kensington VideoCAM 67014";
1381 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1382 le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
1383 camera_name = "Kensington VideoCAM 6701(5/7)";
1384 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1385 le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
1386 camera_name = "Kensington VideoCAM 67016";
1387 button = 0;
1da177e4
LT
1388 } else
1389 return -ENODEV;
1390
d56410e0
MCC
1391 /* Checking vendor/product should be enough, but what the hell */
1392 if (interface->bInterfaceClass != 0x00)
1da177e4 1393 return -ENODEV;
d56410e0 1394 if (interface->bInterfaceSubClass != 0x00)
1da177e4
LT
1395 return -ENODEV;
1396
d56410e0 1397 /* We found one */
a482f327 1398 dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
1da177e4 1399
aae40fd2
AC
1400 se401 = kzalloc(sizeof(*se401), GFP_KERNEL);
1401 if (se401 == NULL) {
d56410e0 1402 err("couldn't kmalloc se401 struct");
1da177e4 1403 return -ENOMEM;
d56410e0 1404 }
1da177e4 1405
d56410e0
MCC
1406 se401->dev = dev;
1407 se401->iface = interface->bInterfaceNumber;
1408 se401->camera_name = camera_name;
1da177e4 1409
a482f327
GKH
1410 dev_info(&intf->dev, "firmware version: %02x\n",
1411 le16_to_cpu(dev->descriptor.bcdDevice) & 255);
1da177e4 1412
d56410e0 1413 if (se401_init(se401, button)) {
1da177e4
LT
1414 kfree(se401);
1415 return -EIO;
1416 }
1417
1418 memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
aae40fd2
AC
1419 memcpy(se401->vdev.name, se401->camera_name,
1420 strlen(se401->camera_name));
1da177e4 1421 init_waitqueue_head(&se401->wq);
4186ecf8 1422 mutex_init(&se401->lock);
1da177e4
LT
1423 wmb();
1424
aae40fd2
AC
1425 if (video_register_device(&se401->vdev,
1426 VFL_TYPE_GRABBER, video_nr) < 0) {
1da177e4
LT
1427 kfree(se401);
1428 err("video_register_device failed");
1429 return -EIO;
1430 }
a482f327 1431 dev_info(&intf->dev, "registered new video device: video%d\n",
c6330fb8 1432 se401->vdev.num);
1da177e4 1433
aae40fd2 1434 usb_set_intfdata(intf, se401);
d56410e0 1435 return 0;
1da177e4
LT
1436}
1437
1438static void se401_disconnect(struct usb_interface *intf)
1439{
aae40fd2 1440 struct usb_se401 *se401 = usb_get_intfdata(intf);
1da177e4 1441
aae40fd2 1442 usb_set_intfdata(intf, NULL);
1da177e4
LT
1443 if (se401) {
1444 video_unregister_device(&se401->vdev);
aae40fd2 1445 if (!se401->user)
1da177e4 1446 usb_se401_remove_disconnected(se401);
aae40fd2 1447 else {
1da177e4
LT
1448 se401->frame[0].grabstate = FRAME_ERROR;
1449 se401->frame[0].grabstate = FRAME_ERROR;
1450
1451 se401->streaming = 0;
1452
1453 wake_up_interruptible(&se401->wq);
1454 se401->removed = 1;
1455 }
1456 }
1457}
1458
1459static struct usb_driver se401_driver = {
aae40fd2
AC
1460 .name = "se401",
1461 .id_table = device_table,
1462 .probe = se401_probe,
1463 .disconnect = se401_disconnect,
1da177e4
LT
1464};
1465
1466
1467
1468/****************************************************************************
1469 *
1470 * Module routines
1471 *
1472 ***************************************************************************/
1473
1474static int __init usb_se401_init(void)
1475{
aae40fd2
AC
1476 printk(KERN_INFO "SE401 usb camera driver version %s registering\n",
1477 version);
1da177e4 1478 if (flickerless)
aae40fd2 1479 if (flickerless != 50 && flickerless != 60) {
a482f327 1480 printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
1da177e4
LT
1481 return -1;
1482 }
1483 return usb_register(&se401_driver);
1484}
1485
1486static void __exit usb_se401_exit(void)
1487{
1488 usb_deregister(&se401_driver);
a482f327 1489 printk(KERN_INFO "SE401 driver deregistered\frame");
1da177e4
LT
1490}
1491
1492module_init(usb_se401_init);
1493module_exit(usb_se401_exit);