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