MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / usb / media / se401.c
blobc694caaac447067b29be3a8c2df7ae1db8221479
1 /*
2 * Endpoints (formerly known as AOX) se401 USB Camera Driver
4 * Copyright (c) 2000 Jeroen B. Vreeken (pe1rxq@amsat.org)
6 * Still somewhat based on the Linux ov511 driver.
7 *
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.
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.
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.
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
28 static const char version[] = "0.24";
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/init.h>
33 #include <linux/vmalloc.h>
34 #include <linux/slab.h>
35 #include <linux/pagemap.h>
36 #include <linux/usb.h>
37 #include "se401.h"
39 static int flickerless=0;
40 static int video_nr = -1;
42 static struct usb_device_id device_table [] = {
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 { }
51 MODULE_DEVICE_TABLE(usb, device_table);
53 MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
54 MODULE_DESCRIPTION("SE401 USB Camera Driver");
55 MODULE_LICENSE("GPL");
56 module_param(flickerless, int, 0);
57 MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
58 module_param(video_nr, int, 0);
60 static struct usb_driver se401_driver;
63 /**********************************************************************
65 * Memory management
67 **********************************************************************/
69 /* Here we want the physical address of the memory.
70 * This is used when initializing the contents of the area.
72 static inline unsigned long kvirt_to_pa(unsigned long adr)
74 unsigned long kva, ret;
76 kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
77 kva |= adr & (PAGE_SIZE-1); /* restore the offset */
78 ret = __pa(kva);
79 return ret;
82 static void *rvmalloc(unsigned long size)
84 void *mem;
85 unsigned long adr;
87 size = PAGE_ALIGN(size);
88 mem = vmalloc_32(size);
89 if (!mem)
90 return NULL;
92 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
93 adr = (unsigned long) mem;
94 while (size > 0) {
95 SetPageReserved(vmalloc_to_page((void *)adr));
96 adr += PAGE_SIZE;
97 size -= PAGE_SIZE;
100 return mem;
103 static void rvfree(void *mem, unsigned long size)
105 unsigned long adr;
107 if (!mem)
108 return;
110 adr = (unsigned long) mem;
111 while ((long) size > 0) {
112 ClearPageReserved(vmalloc_to_page((void *)adr));
113 adr += PAGE_SIZE;
114 size -= PAGE_SIZE;
116 vfree(mem);
121 /****************************************************************************
123 * se401 register read/write functions
125 ***************************************************************************/
127 static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
128 unsigned short value, unsigned char *cp, int size)
130 return usb_control_msg (
131 se401->dev,
132 set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
133 req,
134 (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
135 value,
138 size,
143 static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
144 unsigned short param)
146 /* specs say that the selector (address) should go in the value field
147 and the param in index, but in the logs of the windows driver they do
148 this the other way around...
150 return usb_control_msg (
151 se401->dev,
152 usb_sndctrlpipe(se401->dev, 0),
153 SE401_REQ_SET_EXT_FEATURE,
154 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
155 param,
156 selector,
157 NULL,
163 static unsigned short se401_get_feature(struct usb_se401 *se401,
164 unsigned short selector)
166 /* For 'set' the selecetor should be in index, not sure if the spec is
167 wrong here to....
169 unsigned char cp[2];
170 usb_control_msg (
171 se401->dev,
172 usb_rcvctrlpipe(se401->dev, 0),
173 SE401_REQ_GET_EXT_FEATURE,
174 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
176 selector,
181 return cp[0]+cp[1]*256;
184 /****************************************************************************
186 * Camera control
188 ***************************************************************************/
191 static int se401_send_pict(struct usb_se401 *se401)
193 se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */
194 se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */
195 se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */
196 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */
197 se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */
198 se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */
199 se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */
201 return 0;
204 static void se401_set_exposure(struct usb_se401 *se401, int brightness)
206 int integration=brightness<<5;
208 if (flickerless==50) {
209 integration=integration-integration%106667;
211 if (flickerless==60) {
212 integration=integration-integration%88889;
214 se401->brightness=integration>>5;
215 se401->expose_h=(integration>>16)&0xff;
216 se401->expose_m=(integration>>8)&0xff;
217 se401->expose_l=integration&0xff;
220 static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
222 p->brightness=se401->brightness;
223 if (se401->enhance) {
224 p->whiteness=32768;
225 } else {
226 p->whiteness=0;
228 p->colour=65535;
229 p->contrast=65535;
230 p->hue=se401->rgain<<10;
231 p->palette=se401->palette;
232 p->depth=3; /* rgb24 */
233 return 0;
237 static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
239 if (p->palette != VIDEO_PALETTE_RGB24)
240 return 1;
241 se401->palette=p->palette;
242 if (p->hue!=se401->hue) {
243 se401->rgain= p->hue>>10;
244 se401->bgain= 0x40-(p->hue>>10);
245 se401->hue=p->hue;
247 if (p->brightness!=se401->brightness) {
248 se401_set_exposure(se401, p->brightness);
250 if (p->whiteness>=32768) {
251 se401->enhance=1;
252 } else {
253 se401->enhance=0;
255 se401_send_pict(se401);
256 se401_send_pict(se401);
257 return 0;
261 Hyundai have some really nice docs about this and other sensor related
262 stuff on their homepage: www.hei.co.kr
264 static void se401_auto_resetlevel(struct usb_se401 *se401)
266 unsigned int ahrc, alrc;
267 int oldreset=se401->resetlevel;
269 /* For some reason this normally read-only register doesn't get reset
270 to zero after reading them just once...
272 se401_get_feature(se401, HV7131_REG_HIREFNOH);
273 se401_get_feature(se401, HV7131_REG_HIREFNOL);
274 se401_get_feature(se401, HV7131_REG_LOREFNOH);
275 se401_get_feature(se401, HV7131_REG_LOREFNOL);
276 ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
277 se401_get_feature(se401, HV7131_REG_HIREFNOL);
278 alrc=256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
279 se401_get_feature(se401, HV7131_REG_LOREFNOL);
281 /* Not an exact science, but it seems to work pretty well... */
282 if (alrc > 10) {
283 while (alrc>=10 && se401->resetlevel < 63) {
284 se401->resetlevel++;
285 alrc /=2;
287 } else if (ahrc > 20) {
288 while (ahrc>=20 && se401->resetlevel > 0) {
289 se401->resetlevel--;
290 ahrc /=2;
293 if (se401->resetlevel!=oldreset)
294 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
296 return;
299 /* irq handler for snapshot button */
300 static void se401_button_irq(struct urb *urb, struct pt_regs *regs)
302 struct usb_se401 *se401 = urb->context;
303 int status;
305 if (!se401->dev) {
306 info("ohoh: device vapourished");
307 return;
310 switch (urb->status) {
311 case 0:
312 /* success */
313 break;
314 case -ECONNRESET:
315 case -ENOENT:
316 case -ESHUTDOWN:
317 /* this urb is terminated, clean up */
318 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
319 return;
320 default:
321 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
322 goto exit;
325 if (urb->actual_length >=2) {
326 if (se401->button)
327 se401->buttonpressed=1;
329 exit:
330 status = usb_submit_urb (urb, GFP_ATOMIC);
331 if (status)
332 err ("%s - usb_submit_urb failed with result %d",
333 __FUNCTION__, status);
336 static void se401_video_irq(struct urb *urb, struct pt_regs *regs)
338 struct usb_se401 *se401 = urb->context;
339 int length = urb->actual_length;
341 /* ohoh... */
342 if (!se401->streaming)
343 return;
345 if (!se401->dev) {
346 info ("ohoh: device vapourished");
347 return;
350 /* 0 sized packets happen if we are to fast, but sometimes the camera
351 keeps sending them forever...
353 if (length && !urb->status) {
354 se401->nullpackets=0;
355 switch(se401->scratch[se401->scratch_next].state) {
356 case BUFFER_READY:
357 case BUFFER_BUSY: {
358 se401->dropped++;
359 break;
361 case BUFFER_UNUSED: {
362 memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length);
363 se401->scratch[se401->scratch_next].state=BUFFER_READY;
364 se401->scratch[se401->scratch_next].offset=se401->bayeroffset;
365 se401->scratch[se401->scratch_next].length=length;
366 if (waitqueue_active(&se401->wq)) {
367 wake_up_interruptible(&se401->wq);
369 se401->scratch_overflow=0;
370 se401->scratch_next++;
371 if (se401->scratch_next>=SE401_NUMSCRATCH)
372 se401->scratch_next=0;
373 break;
376 se401->bayeroffset+=length;
377 if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
378 se401->bayeroffset=0;
380 } else {
381 se401->nullpackets++;
382 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
383 if (waitqueue_active(&se401->wq)) {
384 wake_up_interruptible(&se401->wq);
389 /* Resubmit urb for new data */
390 urb->status=0;
391 urb->dev=se401->dev;
392 if(usb_submit_urb(urb, GFP_KERNEL))
393 info("urb burned down");
394 return;
397 static void se401_send_size(struct usb_se401 *se401, int width, int height)
399 int i=0;
400 int mode=0x03; /* No compression */
401 int sendheight=height;
402 int sendwidth=width;
404 /* JangGu compression can only be used with the camera supported sizes,
405 but bayer seems to work with any size that fits on the sensor.
406 We check if we can use compression with the current size with either
407 4 or 16 times subcapturing, if not we use uncompressed bayer data
408 but this will result in cutouts of the maximum size....
410 while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
411 i++;
412 while (i<se401->sizes) {
413 if (se401->width[i]==width*2 && se401->height[i]==height*2) {
414 sendheight=se401->height[i];
415 sendwidth=se401->width[i];
416 mode=0x40;
418 if (se401->width[i]==width*4 && se401->height[i]==height*4) {
419 sendheight=se401->height[i];
420 sendwidth=se401->width[i];
421 mode=0x42;
423 i++;
426 se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
427 se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
428 se401_set_feature(se401, SE401_OPERATINGMODE, mode);
430 if (mode==0x03) {
431 se401->format=FMT_BAYER;
432 } else {
433 se401->format=FMT_JANGGU;
436 return;
440 In this function se401_send_pict is called several times,
441 for some reason (depending on the state of the sensor and the phase of
442 the moon :) doing this only in either place doesn't always work...
444 static int se401_start_stream(struct usb_se401 *se401)
446 struct urb *urb;
447 int err=0, i;
448 se401->streaming=1;
450 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
451 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
453 /* Set picture settings */
454 se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
455 se401_send_pict(se401);
457 se401_send_size(se401, se401->cwidth, se401->cheight);
459 se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
461 /* Do some memory allocation */
462 for (i=0; i<SE401_NUMFRAMES; i++) {
463 se401->frame[i].data=se401->fbuf + i * se401->maxframesize;
464 se401->frame[i].curpix=0;
466 for (i=0; i<SE401_NUMSBUF; i++) {
467 se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
470 se401->bayeroffset=0;
471 se401->scratch_next=0;
472 se401->scratch_use=0;
473 se401->scratch_overflow=0;
474 for (i=0; i<SE401_NUMSCRATCH; i++) {
475 se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
476 se401->scratch[i].state=BUFFER_UNUSED;
479 for (i=0; i<SE401_NUMSBUF; i++) {
480 urb=usb_alloc_urb(0, GFP_KERNEL);
481 if(!urb)
482 return -ENOMEM;
484 usb_fill_bulk_urb(urb, se401->dev,
485 usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
486 se401->sbuf[i].data, SE401_PACKETSIZE,
487 se401_video_irq,
488 se401);
490 se401->urb[i]=urb;
492 err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
493 if(err)
494 err("urb burned down");
497 se401->framecount=0;
499 return 0;
502 static int se401_stop_stream(struct usb_se401 *se401)
504 int i;
506 if (!se401->streaming || !se401->dev)
507 return 1;
509 se401->streaming=0;
511 se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
513 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
514 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
516 for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
517 usb_unlink_urb(se401->urb[i]);
518 usb_free_urb(se401->urb[i]);
519 se401->urb[i]=NULL;
520 kfree(se401->sbuf[i].data);
522 for (i=0; i<SE401_NUMSCRATCH; i++) {
523 kfree(se401->scratch[i].data);
524 se401->scratch[i].data=NULL;
527 return 0;
530 static int se401_set_size(struct usb_se401 *se401, int width, int height)
532 int wasstreaming=se401->streaming;
533 /* Check to see if we need to change */
534 if (se401->cwidth==width && se401->cheight==height)
535 return 0;
537 /* Check for a valid mode */
538 if (!width || !height)
539 return 1;
540 if ((width & 1) || (height & 1))
541 return 1;
542 if (width>se401->width[se401->sizes-1])
543 return 1;
544 if (height>se401->height[se401->sizes-1])
545 return 1;
547 /* Stop a current stream and start it again at the new size */
548 if (wasstreaming)
549 se401_stop_stream(se401);
550 se401->cwidth=width;
551 se401->cheight=height;
552 if (wasstreaming)
553 se401_start_stream(se401);
554 return 0;
558 /****************************************************************************
560 * Video Decoding
562 ***************************************************************************/
565 This shouldn't really be done in a v4l driver....
566 But it does make the image look a lot more usable.
567 Basically it lifts the dark pixels more than the light pixels.
569 static inline void enhance_picture(unsigned char *frame, int len)
571 while (len--) {
572 *frame=(((*frame^255)*(*frame^255))/255)^255;
573 frame++;
577 static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
579 struct se401_frame *frame=&se401->frame[se401->curframe];
580 int linelength=se401->cwidth*3;
582 if (frame->curlinepix >= linelength) {
583 frame->curlinepix=0;
584 frame->curline+=linelength;
587 /* First three are absolute, all others relative.
588 * Format is rgb from right to left (mirrorred image),
589 * we flip it to get bgr from left to right. */
590 if (frame->curlinepix < 3) {
591 *(frame->curline-frame->curlinepix)=1+data*4;
592 } else {
593 *(frame->curline-frame->curlinepix)=
594 *(frame->curline-frame->curlinepix+3)+data*4;
596 frame->curlinepix++;
599 static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
601 int pos=0;
602 int vlc_cod=0;
603 int vlc_size=0;
604 int vlc_data=0;
605 int bit_cur;
606 int bit;
607 data+=4;
608 while (pos < packetlength) {
609 bit_cur=8;
610 while (bit_cur && bit_exp) {
611 bit=((*data)>>(bit_cur-1))&1;
612 if (!vlc_cod) {
613 if (bit) {
614 vlc_size++;
615 } else {
616 if (!vlc_size) {
617 decode_JangGu_integrate(se401, 0);
618 } else {
619 vlc_cod=2;
620 vlc_data=0;
623 } else {
624 if (vlc_cod==2) {
625 if (!bit)
626 vlc_data = -(1<<vlc_size) + 1;
627 vlc_cod--;
629 vlc_size--;
630 vlc_data+=bit<<vlc_size;
631 if (!vlc_size) {
632 decode_JangGu_integrate(se401, vlc_data);
633 vlc_cod=0;
636 bit_cur--;
637 bit_exp--;
639 pos++;
640 data++;
644 static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
646 unsigned char *data=buffer->data;
647 int len=buffer->length;
648 int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
649 int datapos=0;
651 /* New image? */
652 if (!se401->frame[se401->curframe].curpix) {
653 se401->frame[se401->curframe].curlinepix=0;
654 se401->frame[se401->curframe].curline=
655 se401->frame[se401->curframe].data+
656 se401->cwidth*3-1;
657 if (se401->frame[se401->curframe].grabstate==FRAME_READY)
658 se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
659 se401->vlcdatapos=0;
661 while (datapos < len) {
662 size=1024-se401->vlcdatapos;
663 if (size+datapos > len)
664 size=len-datapos;
665 memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
666 se401->vlcdatapos+=size;
667 packetlength=0;
668 if (se401->vlcdatapos >= 4) {
669 bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
670 pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
671 frameinfo=se401->vlcdata[0]&0xc0;
672 packetlength=((bit_exp+47)>>4)<<1;
673 if (packetlength > 1024) {
674 se401->vlcdatapos=0;
675 datapos=len;
676 packetlength=0;
677 se401->error++;
678 se401->frame[se401->curframe].curpix=0;
681 if (packetlength && se401->vlcdatapos >= packetlength) {
682 decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
683 se401->frame[se401->curframe].curpix+=pix_exp*3;
684 datapos+=size-(se401->vlcdatapos-packetlength);
685 se401->vlcdatapos=0;
686 if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
687 if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
688 if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
689 se401->frame[se401->curframe].grabstate=FRAME_DONE;
690 se401->framecount++;
691 se401->readcount++;
693 if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
694 se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
696 } else {
697 se401->error++;
699 se401->frame[se401->curframe].curpix=0;
700 datapos=len;
702 } else {
703 datapos+=size;
708 static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
710 unsigned char *data=buffer->data;
711 int len=buffer->length;
712 int offset=buffer->offset;
713 int datasize=se401->cwidth*se401->cheight;
714 struct se401_frame *frame=&se401->frame[se401->curframe];
716 unsigned char *framedata=frame->data, *curline, *nextline;
717 int width=se401->cwidth;
718 int blineoffset=0, bline;
719 int linelength=width*3, i;
722 if (frame->curpix==0) {
723 if (frame->grabstate==FRAME_READY) {
724 frame->grabstate=FRAME_GRABBING;
726 frame->curline=framedata+linelength;
727 frame->curlinepix=0;
730 if (offset!=frame->curpix) {
731 /* Regard frame as lost :( */
732 frame->curpix=0;
733 se401->error++;
734 return;
737 /* Check if we have to much data */
738 if (frame->curpix+len > datasize) {
739 len=datasize-frame->curpix;
741 if (se401->cheight%4)
742 blineoffset=1;
743 bline=frame->curpix/se401->cwidth+blineoffset;
745 curline=frame->curline;
746 nextline=curline+linelength;
747 if (nextline >= framedata+datasize*3)
748 nextline=curline;
749 while (len) {
750 if (frame->curlinepix>=width) {
751 frame->curlinepix-=width;
752 bline=frame->curpix/width+blineoffset;
753 curline+=linelength*2;
754 nextline+=linelength*2;
755 if (curline >= framedata+datasize*3) {
756 frame->curlinepix++;
757 curline-=3;
758 nextline-=3;
759 len--;
760 data++;
761 frame->curpix++;
763 if (nextline >= framedata+datasize*3)
764 nextline=curline;
766 if ((bline&1)) {
767 if ((frame->curlinepix&1)) {
768 *(curline+2)=*data;
769 *(curline-1)=*data;
770 *(nextline+2)=*data;
771 *(nextline-1)=*data;
772 } else {
773 *(curline+1)=
774 (*(curline+1)+*data)/2;
775 *(curline-2)=
776 (*(curline-2)+*data)/2;
777 *(nextline+1)=*data;
778 *(nextline-2)=*data;
780 } else {
781 if ((frame->curlinepix&1)) {
782 *(curline+1)=
783 (*(curline+1)+*data)/2;
784 *(curline-2)=
785 (*(curline-2)+*data)/2;
786 *(nextline+1)=*data;
787 *(nextline-2)=*data;
788 } else {
789 *curline=*data;
790 *(curline-3)=*data;
791 *nextline=*data;
792 *(nextline-3)=*data;
795 frame->curlinepix++;
796 curline-=3;
797 nextline-=3;
798 len--;
799 data++;
800 frame->curpix++;
802 frame->curline=curline;
804 if (frame->curpix>=datasize) {
805 /* Fix the top line */
806 framedata+=linelength;
807 for (i=0; i<linelength; i++) {
808 framedata--;
809 *framedata=*(framedata+linelength);
811 /* Fix the left side (green is already present) */
812 for (i=0; i<se401->cheight; i++) {
813 *framedata=*(framedata+3);
814 *(framedata+1)=*(framedata+4);
815 *(framedata+2)=*(framedata+5);
816 framedata+=linelength;
818 frame->curpix=0;
819 frame->grabstate=FRAME_DONE;
820 se401->framecount++;
821 se401->readcount++;
822 if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
823 se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
828 static int se401_newframe(struct usb_se401 *se401, int framenr)
830 DECLARE_WAITQUEUE(wait, current);
831 int errors=0;
833 while (se401->streaming &&
834 (se401->frame[framenr].grabstate==FRAME_READY ||
835 se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
836 if(!se401->frame[framenr].curpix) {
837 errors++;
839 wait_interruptible(
840 se401->scratch[se401->scratch_use].state!=BUFFER_READY,
841 &se401->wq,
842 &wait
844 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
845 se401->nullpackets=0;
846 info("to many null length packets, restarting capture");
847 se401_stop_stream(se401);
848 se401_start_stream(se401);
849 } else {
850 if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
851 se401->frame[framenr].grabstate=FRAME_ERROR;
852 return -EIO;
854 se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
855 if (se401->format==FMT_JANGGU) {
856 decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
857 } else {
858 decode_bayer(se401, &se401->scratch[se401->scratch_use]);
860 se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
861 se401->scratch_use++;
862 if (se401->scratch_use>=SE401_NUMSCRATCH)
863 se401->scratch_use=0;
864 if (errors > SE401_MAX_ERRORS) {
865 errors=0;
866 info("to much errors, restarting capture");
867 se401_stop_stream(se401);
868 se401_start_stream(se401);
873 if (se401->frame[framenr].grabstate==FRAME_DONE)
874 if (se401->enhance)
875 enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
876 return 0;
879 static void usb_se401_remove_disconnected (struct usb_se401 *se401)
881 int i;
883 se401->dev = NULL;
885 for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
886 usb_unlink_urb(se401->urb[i]);
887 usb_free_urb(se401->urb[i]);
888 se401->urb[i] = NULL;
889 kfree(se401->sbuf[i].data);
891 for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {
892 kfree(se401->scratch[i].data);
894 if (se401->inturb) {
895 usb_unlink_urb(se401->inturb);
896 usb_free_urb(se401->inturb);
898 info("%s disconnected", se401->camera_name);
900 /* Free the memory */
901 kfree(se401->width);
902 kfree(se401->height);
903 kfree(se401);
908 /****************************************************************************
910 * Video4Linux
912 ***************************************************************************/
915 static int se401_open(struct inode *inode, struct file *file)
917 struct video_device *dev = video_devdata(file);
918 struct usb_se401 *se401 = (struct usb_se401 *)dev;
919 int err = 0;
921 if (se401->user)
922 return -EBUSY;
923 se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
924 if (se401->fbuf)
925 file->private_data = dev;
926 else
927 err = -ENOMEM;
928 se401->user = !err;
930 return err;
933 static int se401_close(struct inode *inode, struct file *file)
935 struct video_device *dev = file->private_data;
936 struct usb_se401 *se401 = (struct usb_se401 *)dev;
937 int i;
939 rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
940 if (se401->removed) {
941 usb_se401_remove_disconnected(se401);
942 info("device unregistered");
943 } else {
944 for (i=0; i<SE401_NUMFRAMES; i++)
945 se401->frame[i].grabstate=FRAME_UNUSED;
946 if (se401->streaming)
947 se401_stop_stream(se401);
948 se401->user=0;
950 file->private_data = NULL;
951 return 0;
954 static int se401_do_ioctl(struct inode *inode, struct file *file,
955 unsigned int cmd, void *arg)
957 struct video_device *vdev = file->private_data;
958 struct usb_se401 *se401 = (struct usb_se401 *)vdev;
960 if (!se401->dev)
961 return -EIO;
963 switch (cmd) {
964 case VIDIOCGCAP:
966 struct video_capability *b = arg;
967 strcpy(b->name, se401->camera_name);
968 b->type = VID_TYPE_CAPTURE;
969 b->channels = 1;
970 b->audios = 0;
971 b->maxwidth = se401->width[se401->sizes-1];
972 b->maxheight = se401->height[se401->sizes-1];
973 b->minwidth = se401->width[0];
974 b->minheight = se401->height[0];
975 return 0;
977 case VIDIOCGCHAN:
979 struct video_channel *v = arg;
981 if (v->channel != 0)
982 return -EINVAL;
983 v->flags = 0;
984 v->tuners = 0;
985 v->type = VIDEO_TYPE_CAMERA;
986 strcpy(v->name, "Camera");
987 return 0;
989 case VIDIOCSCHAN:
991 struct video_channel *v = arg;
993 if (v->channel != 0)
994 return -EINVAL;
995 return 0;
997 case VIDIOCGPICT:
999 struct video_picture *p = arg;
1001 se401_get_pict(se401, p);
1002 return 0;
1004 case VIDIOCSPICT:
1006 struct video_picture *p = arg;
1008 if (se401_set_pict(se401, p))
1009 return -EINVAL;
1010 return 0;
1012 case VIDIOCSWIN:
1014 struct video_window *vw = arg;
1016 if (vw->flags)
1017 return -EINVAL;
1018 if (vw->clipcount)
1019 return -EINVAL;
1020 if (se401_set_size(se401, vw->width, vw->height))
1021 return -EINVAL;
1022 return 0;
1024 case VIDIOCGWIN:
1026 struct video_window *vw = arg;
1028 vw->x = 0; /* FIXME */
1029 vw->y = 0;
1030 vw->chromakey = 0;
1031 vw->flags = 0;
1032 vw->clipcount = 0;
1033 vw->width = se401->cwidth;
1034 vw->height = se401->cheight;
1035 return 0;
1037 case VIDIOCGMBUF:
1039 struct video_mbuf *vm = arg;
1040 int i;
1042 memset(vm, 0, sizeof(*vm));
1043 vm->size = SE401_NUMFRAMES * se401->maxframesize;
1044 vm->frames = SE401_NUMFRAMES;
1045 for (i=0; i<SE401_NUMFRAMES; i++)
1046 vm->offsets[i] = se401->maxframesize * i;
1047 return 0;
1049 case VIDIOCMCAPTURE:
1051 struct video_mmap *vm = arg;
1053 if (vm->format != VIDEO_PALETTE_RGB24)
1054 return -EINVAL;
1055 if (vm->frame >= SE401_NUMFRAMES)
1056 return -EINVAL;
1057 if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
1058 return -EBUSY;
1060 /* Is this according to the v4l spec??? */
1061 if (se401_set_size(se401, vm->width, vm->height))
1062 return -EINVAL;
1063 se401->frame[vm->frame].grabstate=FRAME_READY;
1065 if (!se401->streaming)
1066 se401_start_stream(se401);
1068 /* Set the picture properties */
1069 if (se401->framecount==0)
1070 se401_send_pict(se401);
1071 /* Calibrate the reset level after a few frames. */
1072 if (se401->framecount%20==1)
1073 se401_auto_resetlevel(se401);
1075 return 0;
1077 case VIDIOCSYNC:
1079 int *frame = arg;
1080 int ret=0;
1082 if(*frame <0 || *frame >= SE401_NUMFRAMES)
1083 return -EINVAL;
1085 ret=se401_newframe(se401, *frame);
1086 se401->frame[*frame].grabstate=FRAME_UNUSED;
1087 return ret;
1089 case VIDIOCGFBUF:
1091 struct video_buffer *vb = arg;
1093 memset(vb, 0, sizeof(*vb));
1094 return 0;
1096 case VIDIOCKEY:
1097 return 0;
1098 case VIDIOCCAPTURE:
1099 return -EINVAL;
1100 case VIDIOCSFBUF:
1101 return -EINVAL;
1102 case VIDIOCGTUNER:
1103 case VIDIOCSTUNER:
1104 return -EINVAL;
1105 case VIDIOCGFREQ:
1106 case VIDIOCSFREQ:
1107 return -EINVAL;
1108 case VIDIOCGAUDIO:
1109 case VIDIOCSAUDIO:
1110 return -EINVAL;
1111 default:
1112 return -ENOIOCTLCMD;
1113 } /* end switch */
1115 return 0;
1118 static int se401_ioctl(struct inode *inode, struct file *file,
1119 unsigned int cmd, unsigned long arg)
1121 return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);
1124 static ssize_t se401_read(struct file *file, char __user *buf,
1125 size_t count, loff_t *ppos)
1127 int realcount=count, ret=0;
1128 struct video_device *dev = file->private_data;
1129 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1132 if (se401->dev == NULL)
1133 return -EIO;
1134 if (realcount > se401->cwidth*se401->cheight*3)
1135 realcount=se401->cwidth*se401->cheight*3;
1137 /* Shouldn't happen: */
1138 if (se401->frame[0].grabstate==FRAME_GRABBING)
1139 return -EBUSY;
1140 se401->frame[0].grabstate=FRAME_READY;
1141 se401->frame[1].grabstate=FRAME_UNUSED;
1142 se401->curframe=0;
1144 if (!se401->streaming)
1145 se401_start_stream(se401);
1147 /* Set the picture properties */
1148 if (se401->framecount==0)
1149 se401_send_pict(se401);
1150 /* Calibrate the reset level after a few frames. */
1151 if (se401->framecount%20==1)
1152 se401_auto_resetlevel(se401);
1154 ret=se401_newframe(se401, 0);
1156 se401->frame[0].grabstate=FRAME_UNUSED;
1157 if (ret)
1158 return ret;
1159 if (copy_to_user(buf, se401->frame[0].data, realcount))
1160 return -EFAULT;
1162 return realcount;
1165 static int se401_mmap(struct file *file, struct vm_area_struct *vma)
1167 struct video_device *dev = file->private_data;
1168 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1169 unsigned long start = vma->vm_start;
1170 unsigned long size = vma->vm_end-vma->vm_start;
1171 unsigned long page, pos;
1173 down(&se401->lock);
1175 if (se401->dev == NULL) {
1176 up(&se401->lock);
1177 return -EIO;
1179 if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
1180 up(&se401->lock);
1181 return -EINVAL;
1183 pos = (unsigned long)se401->fbuf;
1184 while (size > 0) {
1185 page = kvirt_to_pa(pos);
1186 if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
1187 up(&se401->lock);
1188 return -EAGAIN;
1190 start += PAGE_SIZE;
1191 pos += PAGE_SIZE;
1192 if (size > PAGE_SIZE)
1193 size -= PAGE_SIZE;
1194 else
1195 size = 0;
1197 up(&se401->lock);
1199 return 0;
1202 static struct file_operations se401_fops = {
1203 .owner = THIS_MODULE,
1204 .open = se401_open,
1205 .release = se401_close,
1206 .read = se401_read,
1207 .mmap = se401_mmap,
1208 .ioctl = se401_ioctl,
1209 .llseek = no_llseek,
1211 static struct video_device se401_template = {
1212 .owner = THIS_MODULE,
1213 .name = "se401 USB camera",
1214 .type = VID_TYPE_CAPTURE,
1215 .hardware = VID_HARDWARE_SE401,
1216 .fops = &se401_fops,
1221 /***************************/
1222 static int se401_init(struct usb_se401 *se401, int button)
1224 int i=0, rc;
1225 unsigned char cp[0x40];
1226 char temp[200];
1228 /* led on */
1229 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1231 /* get camera descriptor */
1232 rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
1233 if (cp[1]!=0x41) {
1234 err("Wrong descriptor type");
1235 return 1;
1237 sprintf (temp, "ExtraFeatures: %d", cp[3]);
1239 se401->sizes=cp[4]+cp[5]*256;
1240 se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1241 if (!se401->width)
1242 return 1;
1243 se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1244 if (!se401->height) {
1245 kfree(se401->width);
1246 return 1;
1248 for (i=0; i<se401->sizes; i++) {
1249 se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
1250 se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
1252 sprintf (temp, "%s Sizes:", temp);
1253 for (i=0; i<se401->sizes; i++) {
1254 sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
1256 info("%s", temp);
1257 se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
1259 rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1260 se401->cwidth=cp[0]+cp[1]*256;
1261 rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1262 se401->cheight=cp[0]+cp[1]*256;
1264 if (!cp[2] && SE401_FORMAT_BAYER) {
1265 err("Bayer format not supported!");
1266 return 1;
1268 /* set output mode (BAYER) */
1269 se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
1271 rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1272 se401->brightness=cp[0]+cp[1]*256;
1273 /* some default values */
1274 se401->resetlevel=0x2d;
1275 se401->rgain=0x20;
1276 se401->ggain=0x20;
1277 se401->bgain=0x20;
1278 se401_set_exposure(se401, 20000);
1279 se401->palette=VIDEO_PALETTE_RGB24;
1280 se401->enhance=1;
1281 se401->dropped=0;
1282 se401->error=0;
1283 se401->framecount=0;
1284 se401->readcount=0;
1286 /* Start interrupt transfers for snapshot button */
1287 if (button) {
1288 se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
1289 if (!se401->inturb) {
1290 info("Allocation of inturb failed");
1291 return 1;
1293 usb_fill_int_urb(se401->inturb, se401->dev,
1294 usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1295 &se401->button, sizeof(se401->button),
1296 se401_button_irq,
1297 se401,
1300 if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
1301 info("int urb burned down");
1302 return 1;
1304 } else
1305 se401->inturb=NULL;
1307 /* Flash the led */
1308 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1309 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1310 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1311 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1313 return 0;
1316 static int se401_probe(struct usb_interface *intf,
1317 const struct usb_device_id *id)
1319 struct usb_device *dev = interface_to_usbdev(intf);
1320 struct usb_interface_descriptor *interface;
1321 struct usb_se401 *se401;
1322 char *camera_name=NULL;
1323 int button=1;
1325 /* We don't handle multi-config cameras */
1326 if (dev->descriptor.bNumConfigurations != 1)
1327 return -ENODEV;
1329 interface = &intf->cur_altsetting->desc;
1331 /* Is it an se401? */
1332 if (dev->descriptor.idVendor == 0x03e8 &&
1333 dev->descriptor.idProduct == 0x0004) {
1334 camera_name="Endpoints/Aox SE401";
1335 } else if (dev->descriptor.idVendor == 0x0471 &&
1336 dev->descriptor.idProduct == 0x030b) {
1337 camera_name="Philips PCVC665K";
1338 } else if (dev->descriptor.idVendor == 0x047d &&
1339 dev->descriptor.idProduct == 0x5001) {
1340 camera_name="Kensington VideoCAM 67014";
1341 } else if (dev->descriptor.idVendor == 0x047d &&
1342 dev->descriptor.idProduct == 0x5002) {
1343 camera_name="Kensington VideoCAM 6701(5/7)";
1344 } else if (dev->descriptor.idVendor == 0x047d &&
1345 dev->descriptor.idProduct == 0x5003) {
1346 camera_name="Kensington VideoCAM 67016";
1347 button=0;
1348 } else
1349 return -ENODEV;
1351 /* Checking vendor/product should be enough, but what the hell */
1352 if (interface->bInterfaceClass != 0x00)
1353 return -ENODEV;
1354 if (interface->bInterfaceSubClass != 0x00)
1355 return -ENODEV;
1357 /* We found one */
1358 info("SE401 camera found: %s", camera_name);
1360 if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
1361 err("couldn't kmalloc se401 struct");
1362 return -ENOMEM;
1365 memset(se401, 0, sizeof(*se401));
1367 se401->dev = dev;
1368 se401->iface = interface->bInterfaceNumber;
1369 se401->camera_name = camera_name;
1371 info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
1373 if (se401_init(se401, button)) {
1374 kfree(se401);
1375 return -EIO;
1378 memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
1379 memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
1380 init_waitqueue_head(&se401->wq);
1381 init_MUTEX(&se401->lock);
1382 wmb();
1384 if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
1385 kfree(se401);
1386 err("video_register_device failed");
1387 return -EIO;
1389 info("registered new video device: video%d", se401->vdev.minor);
1391 usb_set_intfdata (intf, se401);
1392 return 0;
1395 static void se401_disconnect(struct usb_interface *intf)
1397 struct usb_se401 *se401 = usb_get_intfdata (intf);
1399 usb_set_intfdata (intf, NULL);
1400 if (se401) {
1401 video_unregister_device(&se401->vdev);
1402 if (!se401->user){
1403 usb_se401_remove_disconnected(se401);
1404 } else {
1405 se401->frame[0].grabstate = FRAME_ERROR;
1406 se401->frame[0].grabstate = FRAME_ERROR;
1408 se401->streaming = 0;
1410 wake_up_interruptible(&se401->wq);
1411 se401->removed = 1;
1416 static struct usb_driver se401_driver = {
1417 .owner = THIS_MODULE,
1418 .name = "se401",
1419 .id_table = device_table,
1420 .probe = se401_probe,
1421 .disconnect = se401_disconnect,
1426 /****************************************************************************
1428 * Module routines
1430 ***************************************************************************/
1432 static int __init usb_se401_init(void)
1434 info("SE401 usb camera driver version %s registering", version);
1435 if (flickerless)
1436 if (flickerless!=50 && flickerless!=60) {
1437 info("Invallid flickerless value, use 0, 50 or 60.");
1438 return -1;
1440 return usb_register(&se401_driver);
1443 static void __exit usb_se401_exit(void)
1445 usb_deregister(&se401_driver);
1446 info("SE401 driver deregistered");
1449 module_init(usb_se401_init);
1450 module_exit(usb_se401_exit);