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.
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
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.
28 static const char version[] = "0.24";
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>
38 static int flickerless;
39 static int video_nr = -1;
41 static 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 */
50 MODULE_DEVICE_TABLE(usb, device_table);
52 MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
53 MODULE_DESCRIPTION("SE401 USB Camera Driver");
54 MODULE_LICENSE("GPL");
55 module_param(flickerless, int, 0);
56 MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)");
57 module_param(video_nr, int, 0);
59 static struct usb_driver se401_driver;
62 /**********************************************************************
66 **********************************************************************/
67 static void *rvmalloc(unsigned long size)
72 size = PAGE_ALIGN(size);
73 mem = vmalloc_32(size);
77 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
78 adr = (unsigned long) mem;
80 SetPageReserved(vmalloc_to_page((void *)adr));
88 static void rvfree(void *mem, unsigned long size)
95 adr = (unsigned long) mem;
96 while ((long) size > 0) {
97 ClearPageReserved(vmalloc_to_page((void *)adr));
106 /****************************************************************************
108 * se401 register read/write functions
110 ***************************************************************************/
112 static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
113 unsigned short value, unsigned char *cp, int size)
115 return usb_control_msg (
117 set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
119 (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
128 static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
129 unsigned short param)
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...
135 return usb_control_msg (
137 usb_sndctrlpipe(se401->dev, 0),
138 SE401_REQ_SET_EXT_FEATURE,
139 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
148 static unsigned short se401_get_feature(struct usb_se401 *se401,
149 unsigned short selector)
151 /* For 'set' the selecetor should be in index, not sure if the spec is
157 usb_rcvctrlpipe(se401->dev, 0),
158 SE401_REQ_GET_EXT_FEATURE,
159 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
166 return cp[0]+cp[1]*256;
169 /****************************************************************************
173 ***************************************************************************/
176 static int se401_send_pict(struct usb_se401 *se401)
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 */
189 static void se401_set_exposure(struct usb_se401 *se401, int brightness)
191 int integration=brightness<<5;
193 if (flickerless==50) {
194 integration=integration-integration%106667;
196 if (flickerless==60) {
197 integration=integration-integration%88889;
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;
205 static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
207 p->brightness=se401->brightness;
208 if (se401->enhance) {
215 p->hue=se401->rgain<<10;
216 p->palette=se401->palette;
217 p->depth=3; /* rgb24 */
222 static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
224 if (p->palette != VIDEO_PALETTE_RGB24)
226 se401->palette=p->palette;
227 if (p->hue!=se401->hue) {
228 se401->rgain= p->hue>>10;
229 se401->bgain= 0x40-(p->hue>>10);
232 if (p->brightness!=se401->brightness) {
233 se401_set_exposure(se401, p->brightness);
235 if (p->whiteness>=32768) {
240 se401_send_pict(se401);
241 se401_send_pict(se401);
246 Hyundai have some really nice docs about this and other sensor related
247 stuff on their homepage: www.hei.co.kr
249 static void se401_auto_resetlevel(struct usb_se401 *se401)
251 unsigned int ahrc, alrc;
252 int oldreset=se401->resetlevel;
254 /* For some reason this normally read-only register doesn't get reset
255 to zero after reading them just once...
257 se401_get_feature(se401, HV7131_REG_HIREFNOH);
258 se401_get_feature(se401, HV7131_REG_HIREFNOL);
259 se401_get_feature(se401, HV7131_REG_LOREFNOH);
260 se401_get_feature(se401, HV7131_REG_LOREFNOL);
261 ahrc=256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
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);
266 /* Not an exact science, but it seems to work pretty well... */
268 while (alrc>=10 && se401->resetlevel < 63) {
272 } else if (ahrc > 20) {
273 while (ahrc>=20 && se401->resetlevel > 0) {
278 if (se401->resetlevel!=oldreset)
279 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
284 /* irq handler for snapshot button */
285 static void se401_button_irq(struct urb *urb)
287 struct usb_se401 *se401 = urb->context;
291 info("ohoh: device vapourished");
295 switch (urb->status) {
302 /* this urb is terminated, clean up */
303 dbg("%s - urb shutting down with status: %d", __func__, urb->status);
306 dbg("%s - nonzero urb status received: %d", __func__, urb->status);
310 if (urb->actual_length >=2) {
312 se401->buttonpressed=1;
315 status = usb_submit_urb (urb, GFP_ATOMIC);
317 err ("%s - usb_submit_urb failed with result %d",
321 static void se401_video_irq(struct urb *urb)
323 struct usb_se401 *se401 = urb->context;
324 int length = urb->actual_length;
327 if (!se401->streaming)
331 info ("ohoh: device vapourished");
335 /* 0 sized packets happen if we are to fast, but sometimes the camera
336 keeps sending them forever...
338 if (length && !urb->status) {
339 se401->nullpackets=0;
340 switch(se401->scratch[se401->scratch_next].state) {
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);
354 se401->scratch_overflow=0;
355 se401->scratch_next++;
356 if (se401->scratch_next>=SE401_NUMSCRATCH)
357 se401->scratch_next=0;
361 se401->bayeroffset+=length;
362 if (se401->bayeroffset>=se401->cheight*se401->cwidth) {
363 se401->bayeroffset=0;
366 se401->nullpackets++;
367 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
368 if (waitqueue_active(&se401->wq)) {
369 wake_up_interruptible(&se401->wq);
374 /* Resubmit urb for new data */
377 if(usb_submit_urb(urb, GFP_KERNEL))
378 info("urb burned down");
382 static void se401_send_size(struct usb_se401 *se401, int width, int height)
385 int mode=0x03; /* No compression */
386 int sendheight=height;
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....
395 while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height))
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];
403 if (se401->width[i]==width*4 && se401->height[i]==height*4) {
404 sendheight=se401->height[i];
405 sendwidth=se401->width[i];
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);
416 se401->format=FMT_BAYER;
418 se401->format=FMT_JANGGU;
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...
429 static int se401_start_stream(struct usb_se401 *se401)
435 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
436 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
438 /* Set picture settings */
439 se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */
440 se401_send_pict(se401);
442 se401_send_size(se401, se401->cwidth, se401->cheight);
444 se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0);
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;
451 for (i=0; i<SE401_NUMSBUF; i++) {
452 se401->sbuf[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
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;
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);
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;
475 se401->scratch[i].state=BUFFER_UNUSED;
478 for (i=0; i<SE401_NUMSBUF; i++) {
479 urb=usb_alloc_urb(0, GFP_KERNEL);
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;
489 usb_fill_bulk_urb(urb, se401->dev,
490 usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
491 se401->sbuf[i].data, SE401_PACKETSIZE,
497 err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
499 err("urb burned down");
507 for (i=0; i<SE401_NUMSCRATCH; i++) {
508 kfree(se401->scratch[i].data);
509 se401->scratch[i].data = NULL;
512 for (i=0; i<SE401_NUMSBUF; i++) {
513 kfree(se401->sbuf[i].data);
514 se401->sbuf[i].data = NULL;
519 static int se401_stop_stream(struct usb_se401 *se401)
523 if (!se401->streaming || !se401->dev)
528 se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
530 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
531 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
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]);
537 kfree(se401->sbuf[i].data);
539 for (i=0; i<SE401_NUMSCRATCH; i++) {
540 kfree(se401->scratch[i].data);
541 se401->scratch[i].data=NULL;
547 static int se401_set_size(struct usb_se401 *se401, int width, int height)
549 int wasstreaming=se401->streaming;
550 /* Check to see if we need to change */
551 if (se401->cwidth==width && se401->cheight==height)
554 /* Check for a valid mode */
555 if (!width || !height)
557 if ((width & 1) || (height & 1))
559 if (width>se401->width[se401->sizes-1])
561 if (height>se401->height[se401->sizes-1])
564 /* Stop a current stream and start it again at the new size */
566 se401_stop_stream(se401);
568 se401->cheight=height;
570 se401_start_stream(se401);
575 /****************************************************************************
579 ***************************************************************************/
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.
586 static inline void enhance_picture(unsigned char *frame, int len)
589 *frame=(((*frame^255)*(*frame^255))/255)^255;
594 static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
596 struct se401_frame *frame=&se401->frame[se401->curframe];
597 int linelength=se401->cwidth*3;
599 if (frame->curlinepix >= linelength) {
601 frame->curline+=linelength;
604 /* First three are absolute, all others relative.
605 * Format is rgb from right to left (mirrorred image),
606 * we flip it to get bgr from left to right. */
607 if (frame->curlinepix < 3) {
608 *(frame->curline-frame->curlinepix)=1+data*4;
610 *(frame->curline-frame->curlinepix)=
611 *(frame->curline-frame->curlinepix+3)+data*4;
616 static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
625 while (pos < packetlength) {
627 while (bit_cur && bit_exp) {
628 bit=((*data)>>(bit_cur-1))&1;
634 decode_JangGu_integrate(se401, 0);
643 vlc_data = -(1<<vlc_size) + 1;
647 vlc_data+=bit<<vlc_size;
649 decode_JangGu_integrate(se401, vlc_data);
661 static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
663 unsigned char *data=buffer->data;
664 int len=buffer->length;
665 int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
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+
674 if (se401->frame[se401->curframe].grabstate==FRAME_READY)
675 se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
678 while (datapos < len) {
679 size=1024-se401->vlcdatapos;
680 if (size+datapos > len)
682 memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
683 se401->vlcdatapos+=size;
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) {
695 se401->frame[se401->curframe].curpix=0;
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);
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;
710 if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
711 se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
716 se401->frame[se401->curframe].curpix=0;
725 static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
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];
733 unsigned char *framedata=frame->data, *curline, *nextline;
734 int width=se401->cwidth;
735 int blineoffset=0, bline;
736 int linelength=width*3, i;
739 if (frame->curpix==0) {
740 if (frame->grabstate==FRAME_READY) {
741 frame->grabstate=FRAME_GRABBING;
743 frame->curline=framedata+linelength;
747 if (offset!=frame->curpix) {
748 /* Regard frame as lost :( */
754 /* Check if we have to much data */
755 if (frame->curpix+len > datasize) {
756 len=datasize-frame->curpix;
758 if (se401->cheight%4)
760 bline=frame->curpix/se401->cwidth+blineoffset;
762 curline=frame->curline;
763 nextline=curline+linelength;
764 if (nextline >= framedata+datasize*3)
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) {
780 if (nextline >= framedata+datasize*3)
784 if ((frame->curlinepix&1)) {
791 (*(curline+1)+*data)/2;
793 (*(curline-2)+*data)/2;
798 if ((frame->curlinepix&1)) {
800 (*(curline+1)+*data)/2;
802 (*(curline-2)+*data)/2;
819 frame->curline=curline;
821 if (frame->curpix>=datasize) {
822 /* Fix the top line */
823 framedata+=linelength;
824 for (i=0; i<linelength; i++) {
826 *framedata=*(framedata+linelength);
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;
836 frame->grabstate=FRAME_DONE;
839 if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
840 se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
845 static int se401_newframe(struct usb_se401 *se401, int framenr)
847 DECLARE_WAITQUEUE(wait, current);
850 while (se401->streaming &&
851 (se401->frame[framenr].grabstate==FRAME_READY ||
852 se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
853 if(!se401->frame[framenr].curpix) {
857 se401->scratch[se401->scratch_use].state!=BUFFER_READY,
861 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
862 se401->nullpackets=0;
863 info("to many null length packets, restarting capture");
864 se401_stop_stream(se401);
865 se401_start_stream(se401);
867 if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
868 se401->frame[framenr].grabstate=FRAME_ERROR;
871 se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
872 if (se401->format==FMT_JANGGU) {
873 decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
875 decode_bayer(se401, &se401->scratch[se401->scratch_use]);
877 se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
878 se401->scratch_use++;
879 if (se401->scratch_use>=SE401_NUMSCRATCH)
880 se401->scratch_use=0;
881 if (errors > SE401_MAX_ERRORS) {
883 info("to much errors, restarting capture");
884 se401_stop_stream(se401);
885 se401_start_stream(se401);
890 if (se401->frame[framenr].grabstate==FRAME_DONE)
892 enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
896 static void usb_se401_remove_disconnected (struct usb_se401 *se401)
902 for (i=0; i<SE401_NUMSBUF; i++)
904 usb_kill_urb(se401->urb[i]);
905 usb_free_urb(se401->urb[i]);
906 se401->urb[i] = NULL;
907 kfree(se401->sbuf[i].data);
909 for (i=0; i<SE401_NUMSCRATCH; i++) {
910 kfree(se401->scratch[i].data);
913 usb_kill_urb(se401->inturb);
914 usb_free_urb(se401->inturb);
916 info("%s disconnected", se401->camera_name);
918 /* Free the memory */
920 kfree(se401->height);
926 /****************************************************************************
930 ***************************************************************************/
933 static int se401_open(struct inode *inode, struct file *file)
935 struct video_device *dev = video_devdata(file);
936 struct usb_se401 *se401 = (struct usb_se401 *)dev;
944 se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
946 file->private_data = dev;
955 static int se401_close(struct inode *inode, struct file *file)
957 struct video_device *dev = file->private_data;
958 struct usb_se401 *se401 = (struct usb_se401 *)dev;
961 rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
962 if (se401->removed) {
963 usb_se401_remove_disconnected(se401);
964 info("device unregistered");
966 for (i=0; i<SE401_NUMFRAMES; i++)
967 se401->frame[i].grabstate=FRAME_UNUSED;
968 if (se401->streaming)
969 se401_stop_stream(se401);
972 file->private_data = NULL;
976 static int se401_do_ioctl(struct inode *inode, struct file *file,
977 unsigned int cmd, void *arg)
979 struct video_device *vdev = file->private_data;
980 struct usb_se401 *se401 = (struct usb_se401 *)vdev;
988 struct video_capability *b = arg;
989 strcpy(b->name, se401->camera_name);
990 b->type = VID_TYPE_CAPTURE;
993 b->maxwidth = se401->width[se401->sizes-1];
994 b->maxheight = se401->height[se401->sizes-1];
995 b->minwidth = se401->width[0];
996 b->minheight = se401->height[0];
1001 struct video_channel *v = arg;
1003 if (v->channel != 0)
1007 v->type = VIDEO_TYPE_CAMERA;
1008 strcpy(v->name, "Camera");
1013 struct video_channel *v = arg;
1015 if (v->channel != 0)
1021 struct video_picture *p = arg;
1023 se401_get_pict(se401, p);
1028 struct video_picture *p = arg;
1030 if (se401_set_pict(se401, p))
1036 struct video_window *vw = arg;
1042 if (se401_set_size(se401, vw->width, vw->height))
1048 struct video_window *vw = arg;
1050 vw->x = 0; /* FIXME */
1055 vw->width = se401->cwidth;
1056 vw->height = se401->cheight;
1061 struct video_mbuf *vm = arg;
1064 memset(vm, 0, sizeof(*vm));
1065 vm->size = SE401_NUMFRAMES * se401->maxframesize;
1066 vm->frames = SE401_NUMFRAMES;
1067 for (i=0; i<SE401_NUMFRAMES; i++)
1068 vm->offsets[i] = se401->maxframesize * i;
1071 case VIDIOCMCAPTURE:
1073 struct video_mmap *vm = arg;
1075 if (vm->format != VIDEO_PALETTE_RGB24)
1077 if (vm->frame >= SE401_NUMFRAMES)
1079 if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
1082 /* Is this according to the v4l spec??? */
1083 if (se401_set_size(se401, vm->width, vm->height))
1085 se401->frame[vm->frame].grabstate=FRAME_READY;
1087 if (!se401->streaming)
1088 se401_start_stream(se401);
1090 /* Set the picture properties */
1091 if (se401->framecount==0)
1092 se401_send_pict(se401);
1093 /* Calibrate the reset level after a few frames. */
1094 if (se401->framecount%20==1)
1095 se401_auto_resetlevel(se401);
1104 if(*frame <0 || *frame >= SE401_NUMFRAMES)
1107 ret=se401_newframe(se401, *frame);
1108 se401->frame[*frame].grabstate=FRAME_UNUSED;
1113 struct video_buffer *vb = arg;
1115 memset(vb, 0, sizeof(*vb));
1134 return -ENOIOCTLCMD;
1140 static int se401_ioctl(struct inode *inode, struct file *file,
1141 unsigned int cmd, unsigned long arg)
1143 return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);
1146 static ssize_t se401_read(struct file *file, char __user *buf,
1147 size_t count, loff_t *ppos)
1149 int realcount=count, ret=0;
1150 struct video_device *dev = file->private_data;
1151 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1154 if (se401->dev == NULL)
1156 if (realcount > se401->cwidth*se401->cheight*3)
1157 realcount=se401->cwidth*se401->cheight*3;
1159 /* Shouldn't happen: */
1160 if (se401->frame[0].grabstate==FRAME_GRABBING)
1162 se401->frame[0].grabstate=FRAME_READY;
1163 se401->frame[1].grabstate=FRAME_UNUSED;
1166 if (!se401->streaming)
1167 se401_start_stream(se401);
1169 /* Set the picture properties */
1170 if (se401->framecount==0)
1171 se401_send_pict(se401);
1172 /* Calibrate the reset level after a few frames. */
1173 if (se401->framecount%20==1)
1174 se401_auto_resetlevel(se401);
1176 ret=se401_newframe(se401, 0);
1178 se401->frame[0].grabstate=FRAME_UNUSED;
1181 if (copy_to_user(buf, se401->frame[0].data, realcount))
1187 static int se401_mmap(struct file *file, struct vm_area_struct *vma)
1189 struct video_device *dev = file->private_data;
1190 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1191 unsigned long start = vma->vm_start;
1192 unsigned long size = vma->vm_end-vma->vm_start;
1193 unsigned long page, pos;
1195 mutex_lock(&se401->lock);
1197 if (se401->dev == NULL) {
1198 mutex_unlock(&se401->lock);
1201 if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
1202 mutex_unlock(&se401->lock);
1205 pos = (unsigned long)se401->fbuf;
1207 page = vmalloc_to_pfn((void *)pos);
1208 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
1209 mutex_unlock(&se401->lock);
1214 if (size > PAGE_SIZE)
1219 mutex_unlock(&se401->lock);
1224 static const struct file_operations se401_fops = {
1225 .owner = THIS_MODULE,
1227 .release = se401_close,
1230 .ioctl = se401_ioctl,
1231 #ifdef CONFIG_COMPAT
1232 .compat_ioctl = v4l_compat_ioctl32,
1234 .llseek = no_llseek,
1236 static struct video_device se401_template = {
1237 .name = "se401 USB camera",
1238 .fops = &se401_fops,
1243 /***************************/
1244 static int se401_init(struct usb_se401 *se401, int button)
1247 unsigned char cp[0x40];
1251 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1253 /* get camera descriptor */
1254 rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
1256 err("Wrong descriptor type");
1259 sprintf (temp, "ExtraFeatures: %d", cp[3]);
1261 se401->sizes=cp[4]+cp[5]*256;
1262 se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1265 se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1266 if (!se401->height) {
1267 kfree(se401->width);
1270 for (i=0; i<se401->sizes; i++) {
1271 se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
1272 se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
1274 sprintf (temp, "%s Sizes:", temp);
1275 for (i=0; i<se401->sizes; i++) {
1276 sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
1279 se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
1281 rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1282 se401->cwidth=cp[0]+cp[1]*256;
1283 rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1284 se401->cheight=cp[0]+cp[1]*256;
1286 if (!(cp[2] & SE401_FORMAT_BAYER)) {
1287 err("Bayer format not supported!");
1290 /* set output mode (BAYER) */
1291 se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
1293 rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1294 se401->brightness=cp[0]+cp[1]*256;
1295 /* some default values */
1296 se401->resetlevel=0x2d;
1300 se401_set_exposure(se401, 20000);
1301 se401->palette=VIDEO_PALETTE_RGB24;
1305 se401->framecount=0;
1308 /* Start interrupt transfers for snapshot button */
1310 se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
1311 if (!se401->inturb) {
1312 info("Allocation of inturb failed");
1315 usb_fill_int_urb(se401->inturb, se401->dev,
1316 usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1317 &se401->button, sizeof(se401->button),
1322 if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
1323 info("int urb burned down");
1330 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1331 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1332 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1333 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1338 static int se401_probe(struct usb_interface *intf,
1339 const struct usb_device_id *id)
1341 struct usb_device *dev = interface_to_usbdev(intf);
1342 struct usb_interface_descriptor *interface;
1343 struct usb_se401 *se401;
1344 char *camera_name=NULL;
1347 /* We don't handle multi-config cameras */
1348 if (dev->descriptor.bNumConfigurations != 1)
1351 interface = &intf->cur_altsetting->desc;
1353 /* Is it an se401? */
1354 if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
1355 le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
1356 camera_name="Endpoints/Aox SE401";
1357 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
1358 le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
1359 camera_name="Philips PCVC665K";
1360 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1361 le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
1362 camera_name="Kensington VideoCAM 67014";
1363 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1364 le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
1365 camera_name="Kensington VideoCAM 6701(5/7)";
1366 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1367 le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
1368 camera_name="Kensington VideoCAM 67016";
1373 /* Checking vendor/product should be enough, but what the hell */
1374 if (interface->bInterfaceClass != 0x00)
1376 if (interface->bInterfaceSubClass != 0x00)
1380 info("SE401 camera found: %s", camera_name);
1382 if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
1383 err("couldn't kmalloc se401 struct");
1388 se401->iface = interface->bInterfaceNumber;
1389 se401->camera_name = camera_name;
1391 info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);
1393 if (se401_init(se401, button)) {
1398 memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
1399 memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
1400 init_waitqueue_head(&se401->wq);
1401 mutex_init(&se401->lock);
1404 if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
1406 err("video_register_device failed");
1409 info("registered new video device: video%d", se401->vdev.minor);
1411 usb_set_intfdata (intf, se401);
1415 static void se401_disconnect(struct usb_interface *intf)
1417 struct usb_se401 *se401 = usb_get_intfdata (intf);
1419 usb_set_intfdata (intf, NULL);
1421 video_unregister_device(&se401->vdev);
1423 usb_se401_remove_disconnected(se401);
1425 se401->frame[0].grabstate = FRAME_ERROR;
1426 se401->frame[0].grabstate = FRAME_ERROR;
1428 se401->streaming = 0;
1430 wake_up_interruptible(&se401->wq);
1436 static struct usb_driver se401_driver = {
1438 .id_table = device_table,
1439 .probe = se401_probe,
1440 .disconnect = se401_disconnect,
1445 /****************************************************************************
1449 ***************************************************************************/
1451 static int __init usb_se401_init(void)
1453 info("SE401 usb camera driver version %s registering", version);
1455 if (flickerless!=50 && flickerless!=60) {
1456 info("Invallid flickerless value, use 0, 50 or 60.");
1459 return usb_register(&se401_driver);
1462 static void __exit usb_se401_exit(void)
1464 usb_deregister(&se401_driver);
1465 info("SE401 driver deregistered");
1468 module_init(usb_se401_init);
1469 module_exit(usb_se401_exit);