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=0;
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, struct pt_regs *regs)
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", __FUNCTION__, urb->status);
306 dbg("%s - nonzero urb status received: %d", __FUNCTION__, 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",
318 __FUNCTION__, status);
321 static void se401_video_irq(struct urb *urb, struct pt_regs *regs)
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);
455 se401->bayeroffset=0;
456 se401->scratch_next=0;
457 se401->scratch_use=0;
458 se401->scratch_overflow=0;
459 for (i=0; i<SE401_NUMSCRATCH; i++) {
460 se401->scratch[i].data=kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
461 se401->scratch[i].state=BUFFER_UNUSED;
464 for (i=0; i<SE401_NUMSBUF; i++) {
465 urb=usb_alloc_urb(0, GFP_KERNEL);
469 usb_fill_bulk_urb(urb, se401->dev,
470 usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
471 se401->sbuf[i].data, SE401_PACKETSIZE,
477 err=usb_submit_urb(se401->urb[i], GFP_KERNEL);
479 err("urb burned down");
487 static int se401_stop_stream(struct usb_se401 *se401)
491 if (!se401->streaming || !se401->dev)
496 se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
498 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
499 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
501 for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {
502 usb_kill_urb(se401->urb[i]);
503 usb_free_urb(se401->urb[i]);
505 kfree(se401->sbuf[i].data);
507 for (i=0; i<SE401_NUMSCRATCH; i++) {
508 kfree(se401->scratch[i].data);
509 se401->scratch[i].data=NULL;
515 static int se401_set_size(struct usb_se401 *se401, int width, int height)
517 int wasstreaming=se401->streaming;
518 /* Check to see if we need to change */
519 if (se401->cwidth==width && se401->cheight==height)
522 /* Check for a valid mode */
523 if (!width || !height)
525 if ((width & 1) || (height & 1))
527 if (width>se401->width[se401->sizes-1])
529 if (height>se401->height[se401->sizes-1])
532 /* Stop a current stream and start it again at the new size */
534 se401_stop_stream(se401);
536 se401->cheight=height;
538 se401_start_stream(se401);
543 /****************************************************************************
547 ***************************************************************************/
550 This shouldn't really be done in a v4l driver....
551 But it does make the image look a lot more usable.
552 Basically it lifts the dark pixels more than the light pixels.
554 static inline void enhance_picture(unsigned char *frame, int len)
557 *frame=(((*frame^255)*(*frame^255))/255)^255;
562 static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
564 struct se401_frame *frame=&se401->frame[se401->curframe];
565 int linelength=se401->cwidth*3;
567 if (frame->curlinepix >= linelength) {
569 frame->curline+=linelength;
572 /* First three are absolute, all others relative.
573 * Format is rgb from right to left (mirrorred image),
574 * we flip it to get bgr from left to right. */
575 if (frame->curlinepix < 3) {
576 *(frame->curline-frame->curlinepix)=1+data*4;
578 *(frame->curline-frame->curlinepix)=
579 *(frame->curline-frame->curlinepix+3)+data*4;
584 static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength)
593 while (pos < packetlength) {
595 while (bit_cur && bit_exp) {
596 bit=((*data)>>(bit_cur-1))&1;
602 decode_JangGu_integrate(se401, 0);
611 vlc_data = -(1<<vlc_size) + 1;
615 vlc_data+=bit<<vlc_size;
617 decode_JangGu_integrate(se401, vlc_data);
629 static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer)
631 unsigned char *data=buffer->data;
632 int len=buffer->length;
633 int bit_exp=0, pix_exp=0, frameinfo=0, packetlength=0, size;
637 if (!se401->frame[se401->curframe].curpix) {
638 se401->frame[se401->curframe].curlinepix=0;
639 se401->frame[se401->curframe].curline=
640 se401->frame[se401->curframe].data+
642 if (se401->frame[se401->curframe].grabstate==FRAME_READY)
643 se401->frame[se401->curframe].grabstate=FRAME_GRABBING;
646 while (datapos < len) {
647 size=1024-se401->vlcdatapos;
648 if (size+datapos > len)
650 memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
651 se401->vlcdatapos+=size;
653 if (se401->vlcdatapos >= 4) {
654 bit_exp=se401->vlcdata[3]+(se401->vlcdata[2]<<8);
655 pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8);
656 frameinfo=se401->vlcdata[0]&0xc0;
657 packetlength=((bit_exp+47)>>4)<<1;
658 if (packetlength > 1024) {
663 se401->frame[se401->curframe].curpix=0;
666 if (packetlength && se401->vlcdatapos >= packetlength) {
667 decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength);
668 se401->frame[se401->curframe].curpix+=pix_exp*3;
669 datapos+=size-(se401->vlcdatapos-packetlength);
671 if (se401->frame[se401->curframe].curpix>=se401->cwidth*se401->cheight*3) {
672 if (se401->frame[se401->curframe].curpix==se401->cwidth*se401->cheight*3) {
673 if (se401->frame[se401->curframe].grabstate==FRAME_GRABBING) {
674 se401->frame[se401->curframe].grabstate=FRAME_DONE;
678 if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
679 se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
684 se401->frame[se401->curframe].curpix=0;
693 static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer)
695 unsigned char *data=buffer->data;
696 int len=buffer->length;
697 int offset=buffer->offset;
698 int datasize=se401->cwidth*se401->cheight;
699 struct se401_frame *frame=&se401->frame[se401->curframe];
701 unsigned char *framedata=frame->data, *curline, *nextline;
702 int width=se401->cwidth;
703 int blineoffset=0, bline;
704 int linelength=width*3, i;
707 if (frame->curpix==0) {
708 if (frame->grabstate==FRAME_READY) {
709 frame->grabstate=FRAME_GRABBING;
711 frame->curline=framedata+linelength;
715 if (offset!=frame->curpix) {
716 /* Regard frame as lost :( */
722 /* Check if we have to much data */
723 if (frame->curpix+len > datasize) {
724 len=datasize-frame->curpix;
726 if (se401->cheight%4)
728 bline=frame->curpix/se401->cwidth+blineoffset;
730 curline=frame->curline;
731 nextline=curline+linelength;
732 if (nextline >= framedata+datasize*3)
735 if (frame->curlinepix>=width) {
736 frame->curlinepix-=width;
737 bline=frame->curpix/width+blineoffset;
738 curline+=linelength*2;
739 nextline+=linelength*2;
740 if (curline >= framedata+datasize*3) {
748 if (nextline >= framedata+datasize*3)
752 if ((frame->curlinepix&1)) {
759 (*(curline+1)+*data)/2;
761 (*(curline-2)+*data)/2;
766 if ((frame->curlinepix&1)) {
768 (*(curline+1)+*data)/2;
770 (*(curline-2)+*data)/2;
787 frame->curline=curline;
789 if (frame->curpix>=datasize) {
790 /* Fix the top line */
791 framedata+=linelength;
792 for (i=0; i<linelength; i++) {
794 *framedata=*(framedata+linelength);
796 /* Fix the left side (green is already present) */
797 for (i=0; i<se401->cheight; i++) {
798 *framedata=*(framedata+3);
799 *(framedata+1)=*(framedata+4);
800 *(framedata+2)=*(framedata+5);
801 framedata+=linelength;
804 frame->grabstate=FRAME_DONE;
807 if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) {
808 se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1);
813 static int se401_newframe(struct usb_se401 *se401, int framenr)
815 DECLARE_WAITQUEUE(wait, current);
818 while (se401->streaming &&
819 (se401->frame[framenr].grabstate==FRAME_READY ||
820 se401->frame[framenr].grabstate==FRAME_GRABBING) ) {
821 if(!se401->frame[framenr].curpix) {
825 se401->scratch[se401->scratch_use].state!=BUFFER_READY,
829 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
830 se401->nullpackets=0;
831 info("to many null length packets, restarting capture");
832 se401_stop_stream(se401);
833 se401_start_stream(se401);
835 if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) {
836 se401->frame[framenr].grabstate=FRAME_ERROR;
839 se401->scratch[se401->scratch_use].state=BUFFER_BUSY;
840 if (se401->format==FMT_JANGGU) {
841 decode_JangGu(se401, &se401->scratch[se401->scratch_use]);
843 decode_bayer(se401, &se401->scratch[se401->scratch_use]);
845 se401->scratch[se401->scratch_use].state=BUFFER_UNUSED;
846 se401->scratch_use++;
847 if (se401->scratch_use>=SE401_NUMSCRATCH)
848 se401->scratch_use=0;
849 if (errors > SE401_MAX_ERRORS) {
851 info("to much errors, restarting capture");
852 se401_stop_stream(se401);
853 se401_start_stream(se401);
858 if (se401->frame[framenr].grabstate==FRAME_DONE)
860 enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3);
864 static void usb_se401_remove_disconnected (struct usb_se401 *se401)
870 for (i=0; i<SE401_NUMSBUF; i++)
872 usb_kill_urb(se401->urb[i]);
873 usb_free_urb(se401->urb[i]);
874 se401->urb[i] = NULL;
875 kfree(se401->sbuf[i].data);
877 for (i=0; i<SE401_NUMSCRATCH; i++) {
878 kfree(se401->scratch[i].data);
881 usb_kill_urb(se401->inturb);
882 usb_free_urb(se401->inturb);
884 info("%s disconnected", se401->camera_name);
886 /* Free the memory */
888 kfree(se401->height);
894 /****************************************************************************
898 ***************************************************************************/
901 static int se401_open(struct inode *inode, struct file *file)
903 struct video_device *dev = video_devdata(file);
904 struct usb_se401 *se401 = (struct usb_se401 *)dev;
909 se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
911 file->private_data = dev;
919 static int se401_close(struct inode *inode, struct file *file)
921 struct video_device *dev = file->private_data;
922 struct usb_se401 *se401 = (struct usb_se401 *)dev;
925 rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
926 if (se401->removed) {
927 usb_se401_remove_disconnected(se401);
928 info("device unregistered");
930 for (i=0; i<SE401_NUMFRAMES; i++)
931 se401->frame[i].grabstate=FRAME_UNUSED;
932 if (se401->streaming)
933 se401_stop_stream(se401);
936 file->private_data = NULL;
940 static int se401_do_ioctl(struct inode *inode, struct file *file,
941 unsigned int cmd, void *arg)
943 struct video_device *vdev = file->private_data;
944 struct usb_se401 *se401 = (struct usb_se401 *)vdev;
952 struct video_capability *b = arg;
953 strcpy(b->name, se401->camera_name);
954 b->type = VID_TYPE_CAPTURE;
957 b->maxwidth = se401->width[se401->sizes-1];
958 b->maxheight = se401->height[se401->sizes-1];
959 b->minwidth = se401->width[0];
960 b->minheight = se401->height[0];
965 struct video_channel *v = arg;
971 v->type = VIDEO_TYPE_CAMERA;
972 strcpy(v->name, "Camera");
977 struct video_channel *v = arg;
985 struct video_picture *p = arg;
987 se401_get_pict(se401, p);
992 struct video_picture *p = arg;
994 if (se401_set_pict(se401, p))
1000 struct video_window *vw = arg;
1006 if (se401_set_size(se401, vw->width, vw->height))
1012 struct video_window *vw = arg;
1014 vw->x = 0; /* FIXME */
1019 vw->width = se401->cwidth;
1020 vw->height = se401->cheight;
1025 struct video_mbuf *vm = arg;
1028 memset(vm, 0, sizeof(*vm));
1029 vm->size = SE401_NUMFRAMES * se401->maxframesize;
1030 vm->frames = SE401_NUMFRAMES;
1031 for (i=0; i<SE401_NUMFRAMES; i++)
1032 vm->offsets[i] = se401->maxframesize * i;
1035 case VIDIOCMCAPTURE:
1037 struct video_mmap *vm = arg;
1039 if (vm->format != VIDEO_PALETTE_RGB24)
1041 if (vm->frame >= SE401_NUMFRAMES)
1043 if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
1046 /* Is this according to the v4l spec??? */
1047 if (se401_set_size(se401, vm->width, vm->height))
1049 se401->frame[vm->frame].grabstate=FRAME_READY;
1051 if (!se401->streaming)
1052 se401_start_stream(se401);
1054 /* Set the picture properties */
1055 if (se401->framecount==0)
1056 se401_send_pict(se401);
1057 /* Calibrate the reset level after a few frames. */
1058 if (se401->framecount%20==1)
1059 se401_auto_resetlevel(se401);
1068 if(*frame <0 || *frame >= SE401_NUMFRAMES)
1071 ret=se401_newframe(se401, *frame);
1072 se401->frame[*frame].grabstate=FRAME_UNUSED;
1077 struct video_buffer *vb = arg;
1079 memset(vb, 0, sizeof(*vb));
1098 return -ENOIOCTLCMD;
1104 static int se401_ioctl(struct inode *inode, struct file *file,
1105 unsigned int cmd, unsigned long arg)
1107 return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);
1110 static ssize_t se401_read(struct file *file, char __user *buf,
1111 size_t count, loff_t *ppos)
1113 int realcount=count, ret=0;
1114 struct video_device *dev = file->private_data;
1115 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1118 if (se401->dev == NULL)
1120 if (realcount > se401->cwidth*se401->cheight*3)
1121 realcount=se401->cwidth*se401->cheight*3;
1123 /* Shouldn't happen: */
1124 if (se401->frame[0].grabstate==FRAME_GRABBING)
1126 se401->frame[0].grabstate=FRAME_READY;
1127 se401->frame[1].grabstate=FRAME_UNUSED;
1130 if (!se401->streaming)
1131 se401_start_stream(se401);
1133 /* Set the picture properties */
1134 if (se401->framecount==0)
1135 se401_send_pict(se401);
1136 /* Calibrate the reset level after a few frames. */
1137 if (se401->framecount%20==1)
1138 se401_auto_resetlevel(se401);
1140 ret=se401_newframe(se401, 0);
1142 se401->frame[0].grabstate=FRAME_UNUSED;
1145 if (copy_to_user(buf, se401->frame[0].data, realcount))
1151 static int se401_mmap(struct file *file, struct vm_area_struct *vma)
1153 struct video_device *dev = file->private_data;
1154 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1155 unsigned long start = vma->vm_start;
1156 unsigned long size = vma->vm_end-vma->vm_start;
1157 unsigned long page, pos;
1159 mutex_lock(&se401->lock);
1161 if (se401->dev == NULL) {
1162 mutex_unlock(&se401->lock);
1165 if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {
1166 mutex_unlock(&se401->lock);
1169 pos = (unsigned long)se401->fbuf;
1171 page = vmalloc_to_pfn((void *)pos);
1172 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
1173 mutex_unlock(&se401->lock);
1178 if (size > PAGE_SIZE)
1183 mutex_unlock(&se401->lock);
1188 static struct file_operations se401_fops = {
1189 .owner = THIS_MODULE,
1191 .release = se401_close,
1194 .ioctl = se401_ioctl,
1195 .compat_ioctl = v4l_compat_ioctl32,
1196 .llseek = no_llseek,
1198 static struct video_device se401_template = {
1199 .owner = THIS_MODULE,
1200 .name = "se401 USB camera",
1201 .type = VID_TYPE_CAPTURE,
1202 .hardware = VID_HARDWARE_SE401,
1203 .fops = &se401_fops,
1208 /***************************/
1209 static int se401_init(struct usb_se401 *se401, int button)
1212 unsigned char cp[0x40];
1216 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1218 /* get camera descriptor */
1219 rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp));
1221 err("Wrong descriptor type");
1224 sprintf (temp, "ExtraFeatures: %d", cp[3]);
1226 se401->sizes=cp[4]+cp[5]*256;
1227 se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1230 se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1231 if (!se401->height) {
1232 kfree(se401->width);
1235 for (i=0; i<se401->sizes; i++) {
1236 se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;
1237 se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;
1239 sprintf (temp, "%s Sizes:", temp);
1240 for (i=0; i<se401->sizes; i++) {
1241 sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);
1244 se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3;
1246 rc=se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1247 se401->cwidth=cp[0]+cp[1]*256;
1248 rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1249 se401->cheight=cp[0]+cp[1]*256;
1251 if (!cp[2] && SE401_FORMAT_BAYER) {
1252 err("Bayer format not supported!");
1255 /* set output mode (BAYER) */
1256 se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0);
1258 rc=se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1259 se401->brightness=cp[0]+cp[1]*256;
1260 /* some default values */
1261 se401->resetlevel=0x2d;
1265 se401_set_exposure(se401, 20000);
1266 se401->palette=VIDEO_PALETTE_RGB24;
1270 se401->framecount=0;
1273 /* Start interrupt transfers for snapshot button */
1275 se401->inturb=usb_alloc_urb(0, GFP_KERNEL);
1276 if (!se401->inturb) {
1277 info("Allocation of inturb failed");
1280 usb_fill_int_urb(se401->inturb, se401->dev,
1281 usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1282 &se401->button, sizeof(se401->button),
1287 if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
1288 info("int urb burned down");
1295 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1296 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1297 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1298 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1303 static int se401_probe(struct usb_interface *intf,
1304 const struct usb_device_id *id)
1306 struct usb_device *dev = interface_to_usbdev(intf);
1307 struct usb_interface_descriptor *interface;
1308 struct usb_se401 *se401;
1309 char *camera_name=NULL;
1312 /* We don't handle multi-config cameras */
1313 if (dev->descriptor.bNumConfigurations != 1)
1316 interface = &intf->cur_altsetting->desc;
1318 /* Is it an se401? */
1319 if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
1320 le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
1321 camera_name="Endpoints/Aox SE401";
1322 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
1323 le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
1324 camera_name="Philips PCVC665K";
1325 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1326 le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
1327 camera_name="Kensington VideoCAM 67014";
1328 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1329 le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
1330 camera_name="Kensington VideoCAM 6701(5/7)";
1331 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1332 le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
1333 camera_name="Kensington VideoCAM 67016";
1338 /* Checking vendor/product should be enough, but what the hell */
1339 if (interface->bInterfaceClass != 0x00)
1341 if (interface->bInterfaceSubClass != 0x00)
1345 info("SE401 camera found: %s", camera_name);
1347 if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {
1348 err("couldn't kmalloc se401 struct");
1353 se401->iface = interface->bInterfaceNumber;
1354 se401->camera_name = camera_name;
1356 info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);
1358 if (se401_init(se401, button)) {
1363 memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
1364 memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));
1365 init_waitqueue_head(&se401->wq);
1366 mutex_init(&se401->lock);
1369 if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {
1371 err("video_register_device failed");
1374 info("registered new video device: video%d", se401->vdev.minor);
1376 usb_set_intfdata (intf, se401);
1380 static void se401_disconnect(struct usb_interface *intf)
1382 struct usb_se401 *se401 = usb_get_intfdata (intf);
1384 usb_set_intfdata (intf, NULL);
1386 video_unregister_device(&se401->vdev);
1388 usb_se401_remove_disconnected(se401);
1390 se401->frame[0].grabstate = FRAME_ERROR;
1391 se401->frame[0].grabstate = FRAME_ERROR;
1393 se401->streaming = 0;
1395 wake_up_interruptible(&se401->wq);
1401 static struct usb_driver se401_driver = {
1403 .id_table = device_table,
1404 .probe = se401_probe,
1405 .disconnect = se401_disconnect,
1410 /****************************************************************************
1414 ***************************************************************************/
1416 static int __init usb_se401_init(void)
1418 info("SE401 usb camera driver version %s registering", version);
1420 if (flickerless!=50 && flickerless!=60) {
1421 info("Invallid flickerless value, use 0, 50 or 60.");
1424 return usb_register(&se401_driver);
1427 static void __exit usb_se401_exit(void)
1429 usb_deregister(&se401_driver);
1430 info("SE401 driver deregistered");
1433 module_init(usb_se401_init);
1434 module_exit(usb_se401_exit);