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,
57 "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 /**********************************************************************
67 **********************************************************************/
68 static void *rvmalloc(unsigned long size)
73 size = PAGE_ALIGN(size);
74 mem = vmalloc_32(size);
78 memset(mem, 0, size); /* Clear the ram out, no junk to the user */
79 adr = (unsigned long) mem;
81 SetPageReserved(vmalloc_to_page((void *)adr));
89 static void rvfree(void *mem, unsigned long size)
96 adr = (unsigned long) mem;
97 while ((long) size > 0) {
98 ClearPageReserved(vmalloc_to_page((void *)adr));
107 /****************************************************************************
109 * se401 register read/write functions
111 ***************************************************************************/
113 static int se401_sndctrl(int set, struct usb_se401 *se401, unsigned short req,
114 unsigned short value, unsigned char *cp, int size)
116 return usb_control_msg(
118 set ? usb_sndctrlpipe(se401->dev, 0) : usb_rcvctrlpipe(se401->dev, 0),
120 (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
129 static int se401_set_feature(struct usb_se401 *se401, unsigned short selector,
130 unsigned short param)
132 /* specs say that the selector (address) should go in the value field
133 and the param in index, but in the logs of the windows driver they do
134 this the other way around...
136 return usb_control_msg(
138 usb_sndctrlpipe(se401->dev, 0),
139 SE401_REQ_SET_EXT_FEATURE,
140 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
149 static unsigned short se401_get_feature(struct usb_se401 *se401,
150 unsigned short selector)
152 /* For 'set' the selecetor should be in index, not sure if the spec is
158 usb_rcvctrlpipe(se401->dev, 0),
159 SE401_REQ_GET_EXT_FEATURE,
160 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
167 return cp[0]+cp[1]*256;
170 /****************************************************************************
174 ***************************************************************************/
177 static int se401_send_pict(struct usb_se401 *se401)
179 /* integration time low */
180 se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);
181 /* integration time mid */
182 se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);
183 /* integration time mid */
184 se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);
185 /* reset level value */
186 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
188 se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);
189 /* green color gain */
190 se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);
191 /* blue color gain */
192 se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);
197 static void se401_set_exposure(struct usb_se401 *se401, int brightness)
199 int integration = brightness << 5;
201 if (flickerless == 50)
202 integration = integration-integration % 106667;
203 if (flickerless == 60)
204 integration = integration-integration % 88889;
205 se401->brightness = integration >> 5;
206 se401->expose_h = (integration >> 16) & 0xff;
207 se401->expose_m = (integration >> 8) & 0xff;
208 se401->expose_l = integration & 0xff;
211 static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p)
213 p->brightness = se401->brightness;
215 p->whiteness = 32768;
221 p->hue = se401->rgain << 10;
222 p->palette = se401->palette;
223 p->depth = 3; /* rgb24 */
228 static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p)
230 if (p->palette != VIDEO_PALETTE_RGB24)
232 se401->palette = p->palette;
233 if (p->hue != se401->hue) {
234 se401->rgain = p->hue >> 10;
235 se401->bgain = 0x40-(p->hue >> 10);
238 if (p->brightness != se401->brightness)
239 se401_set_exposure(se401, p->brightness);
241 if (p->whiteness >= 32768)
245 se401_send_pict(se401);
246 se401_send_pict(se401);
251 Hyundai have some really nice docs about this and other sensor related
252 stuff on their homepage: www.hei.co.kr
254 static void se401_auto_resetlevel(struct usb_se401 *se401)
256 unsigned int ahrc, alrc;
257 int oldreset = se401->resetlevel;
259 /* For some reason this normally read-only register doesn't get reset
260 to zero after reading them just once...
262 se401_get_feature(se401, HV7131_REG_HIREFNOH);
263 se401_get_feature(se401, HV7131_REG_HIREFNOL);
264 se401_get_feature(se401, HV7131_REG_LOREFNOH);
265 se401_get_feature(se401, HV7131_REG_LOREFNOL);
266 ahrc = 256*se401_get_feature(se401, HV7131_REG_HIREFNOH) +
267 se401_get_feature(se401, HV7131_REG_HIREFNOL);
268 alrc = 256*se401_get_feature(se401, HV7131_REG_LOREFNOH) +
269 se401_get_feature(se401, HV7131_REG_LOREFNOL);
271 /* Not an exact science, but it seems to work pretty well... */
273 while (alrc >= 10 && se401->resetlevel < 63) {
277 } else if (ahrc > 20) {
278 while (ahrc >= 20 && se401->resetlevel > 0) {
283 if (se401->resetlevel != oldreset)
284 se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);
289 /* irq handler for snapshot button */
290 static void se401_button_irq(struct urb *urb)
292 struct usb_se401 *se401 = urb->context;
296 dev_info(&urb->dev->dev, "device vapourished\n");
300 switch (urb->status) {
307 /* this urb is terminated, clean up */
308 dbg("%s - urb shutting down with status: %d",
309 __func__, urb->status);
312 dbg("%s - nonzero urb status received: %d",
313 __func__, urb->status);
317 if (urb->actual_length >= 2)
319 se401->buttonpressed = 1;
321 status = usb_submit_urb(urb, GFP_ATOMIC);
323 err("%s - usb_submit_urb failed with result %d",
327 static void se401_video_irq(struct urb *urb)
329 struct usb_se401 *se401 = urb->context;
330 int length = urb->actual_length;
333 if (!se401->streaming)
337 dev_info(&urb->dev->dev, "device vapourished\n");
341 /* 0 sized packets happen if we are to fast, but sometimes the camera
342 keeps sending them forever...
344 if (length && !urb->status) {
345 se401->nullpackets = 0;
346 switch (se401->scratch[se401->scratch_next].state) {
352 memcpy(se401->scratch[se401->scratch_next].data,
353 (unsigned char *)urb->transfer_buffer, length);
354 se401->scratch[se401->scratch_next].state
356 se401->scratch[se401->scratch_next].offset
357 = se401->bayeroffset;
358 se401->scratch[se401->scratch_next].length = length;
359 if (waitqueue_active(&se401->wq))
360 wake_up_interruptible(&se401->wq);
361 se401->scratch_overflow = 0;
362 se401->scratch_next++;
363 if (se401->scratch_next >= SE401_NUMSCRATCH)
364 se401->scratch_next = 0;
367 se401->bayeroffset += length;
368 if (se401->bayeroffset >= se401->cheight * se401->cwidth)
369 se401->bayeroffset = 0;
371 se401->nullpackets++;
372 if (se401->nullpackets > SE401_MAX_NULLPACKETS)
373 if (waitqueue_active(&se401->wq))
374 wake_up_interruptible(&se401->wq);
377 /* Resubmit urb for new data */
379 urb->dev = se401->dev;
380 if (usb_submit_urb(urb, GFP_KERNEL))
381 dev_info(&urb->dev->dev, "urb burned down\n");
385 static void se401_send_size(struct usb_se401 *se401, int width, int height)
388 int mode = 0x03; /* No compression */
389 int sendheight = height;
390 int sendwidth = width;
392 /* JangGu compression can only be used with the camera supported sizes,
393 but bayer seems to work with any size that fits on the sensor.
394 We check if we can use compression with the current size with either
395 4 or 16 times subcapturing, if not we use uncompressed bayer data
396 but this will result in cutouts of the maximum size....
398 while (i < se401->sizes && !(se401->width[i] == width &&
399 se401->height[i] == height))
401 while (i < se401->sizes) {
402 if (se401->width[i] == width * 2 &&
403 se401->height[i] == height * 2) {
404 sendheight = se401->height[i];
405 sendwidth = se401->width[i];
408 if (se401->width[i] == width * 4 &&
409 se401->height[i] == height * 4) {
410 sendheight = se401->height[i];
411 sendwidth = se401->width[i];
417 se401_sndctrl(1, se401, SE401_REQ_SET_WIDTH, sendwidth, NULL, 0);
418 se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0);
419 se401_set_feature(se401, SE401_OPERATINGMODE, mode);
422 se401->format = FMT_BAYER;
424 se401->format = FMT_JANGGU;
428 In this function se401_send_pict is called several times,
429 for some reason (depending on the state of the sensor and the phase of
430 the moon :) doing this only in either place doesn't always work...
432 static int se401_start_stream(struct usb_se401 *se401)
436 se401->streaming = 1;
438 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
439 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
441 /* Set picture settings */
442 /* windowed + pix intg */
443 se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);
444 se401_send_pict(se401);
446 se401_send_size(se401, se401->cwidth, se401->cheight);
448 se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE,
451 /* Do some memory allocation */
452 for (i = 0; i < SE401_NUMFRAMES; i++) {
453 se401->frame[i].data = se401->fbuf + i * se401->maxframesize;
454 se401->frame[i].curpix = 0;
456 for (i = 0; i < SE401_NUMSBUF; i++) {
457 se401->sbuf[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
458 if (!se401->sbuf[i].data) {
459 for (i = i - 1; i >= 0; i--) {
460 kfree(se401->sbuf[i].data);
461 se401->sbuf[i].data = NULL;
467 se401->bayeroffset = 0;
468 se401->scratch_next = 0;
469 se401->scratch_use = 0;
470 se401->scratch_overflow = 0;
471 for (i = 0; i < SE401_NUMSCRATCH; i++) {
472 se401->scratch[i].data = kmalloc(SE401_PACKETSIZE, GFP_KERNEL);
473 if (!se401->scratch[i].data) {
474 for (i = i - 1; i >= 0; i--) {
475 kfree(se401->scratch[i].data);
476 se401->scratch[i].data = NULL;
480 se401->scratch[i].state = BUFFER_UNUSED;
483 for (i = 0; i < SE401_NUMSBUF; i++) {
484 urb = usb_alloc_urb(0, GFP_KERNEL);
486 for (i = i - 1; i >= 0; i--) {
487 usb_kill_urb(se401->urb[i]);
488 usb_free_urb(se401->urb[i]);
489 se401->urb[i] = NULL;
494 usb_fill_bulk_urb(urb, se401->dev,
495 usb_rcvbulkpipe(se401->dev, SE401_VIDEO_ENDPOINT),
496 se401->sbuf[i].data, SE401_PACKETSIZE,
502 err = usb_submit_urb(se401->urb[i], GFP_KERNEL);
504 err("urb burned down");
507 se401->framecount = 0;
512 for (i = 0; i < SE401_NUMSCRATCH; i++) {
513 kfree(se401->scratch[i].data);
514 se401->scratch[i].data = NULL;
517 for (i = 0; i < SE401_NUMSBUF; i++) {
518 kfree(se401->sbuf[i].data);
519 se401->sbuf[i].data = NULL;
524 static int se401_stop_stream(struct usb_se401 *se401)
528 if (!se401->streaming || !se401->dev)
531 se401->streaming = 0;
533 se401_sndctrl(1, se401, SE401_REQ_STOP_CONTINUOUS_CAPTURE, 0, NULL, 0);
535 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
536 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
538 for (i = 0; i < SE401_NUMSBUF; i++)
540 usb_kill_urb(se401->urb[i]);
541 usb_free_urb(se401->urb[i]);
542 se401->urb[i] = NULL;
543 kfree(se401->sbuf[i].data);
545 for (i = 0; i < SE401_NUMSCRATCH; i++) {
546 kfree(se401->scratch[i].data);
547 se401->scratch[i].data = NULL;
553 static int se401_set_size(struct usb_se401 *se401, int width, int height)
555 int wasstreaming = se401->streaming;
556 /* Check to see if we need to change */
557 if (se401->cwidth == width && se401->cheight == height)
560 /* Check for a valid mode */
561 if (!width || !height)
563 if ((width & 1) || (height & 1))
565 if (width > se401->width[se401->sizes-1])
567 if (height > se401->height[se401->sizes-1])
570 /* Stop a current stream and start it again at the new size */
572 se401_stop_stream(se401);
573 se401->cwidth = width;
574 se401->cheight = height;
576 se401_start_stream(se401);
581 /****************************************************************************
585 ***************************************************************************/
588 This shouldn't really be done in a v4l driver....
589 But it does make the image look a lot more usable.
590 Basically it lifts the dark pixels more than the light pixels.
592 static inline void enhance_picture(unsigned char *frame, int len)
595 *frame = (((*frame^255)*(*frame^255))/255)^255;
600 static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data)
602 struct se401_frame *frame = &se401->frame[se401->curframe];
603 int linelength = se401->cwidth * 3;
605 if (frame->curlinepix >= linelength) {
606 frame->curlinepix = 0;
607 frame->curline += linelength;
610 /* First three are absolute, all others relative.
611 * Format is rgb from right to left (mirrorred image),
612 * we flip it to get bgr from left to right. */
613 if (frame->curlinepix < 3)
614 *(frame->curline-frame->curlinepix) = 1 + data * 4;
616 *(frame->curline-frame->curlinepix) =
617 *(frame->curline-frame->curlinepix + 3) + data * 4;
621 static inline void decode_JangGu_vlc(struct usb_se401 *se401,
622 unsigned char *data, int bit_exp, int packetlength)
631 while (pos < packetlength) {
633 while (bit_cur && bit_exp) {
634 bit = ((*data) >> (bit_cur-1))&1;
640 decode_JangGu_integrate(se401, 0);
649 vlc_data = -(1 << vlc_size) + 1;
653 vlc_data += bit << vlc_size;
655 decode_JangGu_integrate(se401, vlc_data);
667 static inline void decode_JangGu(struct usb_se401 *se401,
668 struct se401_scratch *buffer)
670 unsigned char *data = buffer->data;
671 int len = buffer->length;
672 int bit_exp = 0, pix_exp = 0, frameinfo = 0, packetlength = 0, size;
676 if (!se401->frame[se401->curframe].curpix) {
677 se401->frame[se401->curframe].curlinepix = 0;
678 se401->frame[se401->curframe].curline =
679 se401->frame[se401->curframe].data+
680 se401->cwidth * 3 - 1;
681 if (se401->frame[se401->curframe].grabstate == FRAME_READY)
682 se401->frame[se401->curframe].grabstate = FRAME_GRABBING;
683 se401->vlcdatapos = 0;
685 while (datapos < len) {
686 size = 1024 - se401->vlcdatapos;
687 if (size+datapos > len)
689 memcpy(se401->vlcdata+se401->vlcdatapos, data+datapos, size);
690 se401->vlcdatapos += size;
692 if (se401->vlcdatapos >= 4) {
693 bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8);
694 pix_exp = se401->vlcdata[1] +
695 ((se401->vlcdata[0] & 0x3f) << 8);
696 frameinfo = se401->vlcdata[0] & 0xc0;
697 packetlength = ((bit_exp + 47) >> 4) << 1;
698 if (packetlength > 1024) {
699 se401->vlcdatapos = 0;
703 se401->frame[se401->curframe].curpix = 0;
706 if (packetlength && se401->vlcdatapos >= packetlength) {
707 decode_JangGu_vlc(se401, se401->vlcdata, bit_exp,
709 se401->frame[se401->curframe].curpix += pix_exp * 3;
710 datapos += size-(se401->vlcdatapos-packetlength);
711 se401->vlcdatapos = 0;
712 if (se401->frame[se401->curframe].curpix >= se401->cwidth * se401->cheight * 3) {
713 if (se401->frame[se401->curframe].curpix == se401->cwidth * se401->cheight * 3) {
714 if (se401->frame[se401->curframe].grabstate == FRAME_GRABBING) {
715 se401->frame[se401->curframe].grabstate = FRAME_DONE;
719 if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY)
720 se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1);
723 se401->frame[se401->curframe].curpix = 0;
731 static inline void decode_bayer(struct usb_se401 *se401,
732 struct se401_scratch *buffer)
734 unsigned char *data = buffer->data;
735 int len = buffer->length;
736 int offset = buffer->offset;
737 int datasize = se401->cwidth * se401->cheight;
738 struct se401_frame *frame = &se401->frame[se401->curframe];
739 unsigned char *framedata = frame->data, *curline, *nextline;
740 int width = se401->cwidth;
741 int blineoffset = 0, bline;
742 int linelength = width * 3, i;
745 if (frame->curpix == 0) {
746 if (frame->grabstate == FRAME_READY)
747 frame->grabstate = FRAME_GRABBING;
749 frame->curline = framedata + linelength;
750 frame->curlinepix = 0;
753 if (offset != frame->curpix) {
754 /* Regard frame as lost :( */
760 /* Check if we have to much data */
761 if (frame->curpix + len > datasize)
762 len = datasize-frame->curpix;
764 if (se401->cheight % 4)
766 bline = frame->curpix / se401->cwidth+blineoffset;
768 curline = frame->curline;
769 nextline = curline + linelength;
770 if (nextline >= framedata+datasize * 3)
773 if (frame->curlinepix >= width) {
774 frame->curlinepix -= width;
775 bline = frame->curpix / width + blineoffset;
776 curline += linelength*2;
777 nextline += linelength*2;
778 if (curline >= framedata+datasize * 3) {
786 if (nextline >= framedata+datasize*3)
790 if (frame->curlinepix & 1) {
791 *(curline + 2) = *data;
792 *(curline - 1) = *data;
793 *(nextline + 2) = *data;
794 *(nextline - 1) = *data;
797 (*(curline + 1) + *data) / 2;
799 (*(curline - 2) + *data) / 2;
800 *(nextline + 1) = *data;
801 *(nextline - 2) = *data;
804 if (frame->curlinepix & 1) {
806 (*(curline + 1) + *data) / 2;
808 (*(curline - 2) + *data) / 2;
809 *(nextline + 1) = *data;
810 *(nextline - 2) = *data;
813 *(curline - 3) = *data;
815 *(nextline - 3) = *data;
825 frame->curline = curline;
827 if (frame->curpix >= datasize) {
828 /* Fix the top line */
829 framedata += linelength;
830 for (i = 0; i < linelength; i++) {
832 *framedata = *(framedata + linelength);
834 /* Fix the left side (green is already present) */
835 for (i = 0; i < se401->cheight; i++) {
836 *framedata = *(framedata + 3);
837 *(framedata + 1) = *(framedata + 4);
838 *(framedata + 2) = *(framedata + 5);
839 framedata += linelength;
842 frame->grabstate = FRAME_DONE;
845 if (se401->frame[(se401->curframe + 1) &
846 (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) {
847 se401->curframe = (se401->curframe+1) &
853 static int se401_newframe(struct usb_se401 *se401, int framenr)
855 DECLARE_WAITQUEUE(wait, current);
858 while (se401->streaming &&
859 (se401->frame[framenr].grabstate == FRAME_READY ||
860 se401->frame[framenr].grabstate == FRAME_GRABBING)) {
861 if (!se401->frame[framenr].curpix)
865 se401->scratch[se401->scratch_use].state != BUFFER_READY,
867 if (se401->nullpackets > SE401_MAX_NULLPACKETS) {
868 se401->nullpackets = 0;
869 dev_info(&se401->dev->dev,
870 "too many null length packets, restarting capture\n");
871 se401_stop_stream(se401);
872 se401_start_stream(se401);
874 if (se401->scratch[se401->scratch_use].state !=
876 se401->frame[framenr].grabstate = FRAME_ERROR;
879 se401->scratch[se401->scratch_use].state = BUFFER_BUSY;
880 if (se401->format == FMT_JANGGU)
882 &se401->scratch[se401->scratch_use]);
885 &se401->scratch[se401->scratch_use]);
887 se401->scratch[se401->scratch_use].state =
889 se401->scratch_use++;
890 if (se401->scratch_use >= SE401_NUMSCRATCH)
891 se401->scratch_use = 0;
892 if (errors > SE401_MAX_ERRORS) {
894 dev_info(&se401->dev->dev,
895 "too many errors, restarting capture\n");
896 se401_stop_stream(se401);
897 se401_start_stream(se401);
902 if (se401->frame[framenr].grabstate == FRAME_DONE)
904 enhance_picture(se401->frame[framenr].data,
905 se401->cheight * se401->cwidth * 3);
909 static void usb_se401_remove_disconnected(struct usb_se401 *se401)
915 for (i = 0; i < SE401_NUMSBUF; i++)
917 usb_kill_urb(se401->urb[i]);
918 usb_free_urb(se401->urb[i]);
919 se401->urb[i] = NULL;
920 kfree(se401->sbuf[i].data);
923 for (i = 0; i < SE401_NUMSCRATCH; i++)
924 kfree(se401->scratch[i].data);
927 usb_kill_urb(se401->inturb);
928 usb_free_urb(se401->inturb);
930 dev_info(&se401->dev->dev, "%s disconnected", se401->camera_name);
932 /* Free the memory */
934 kfree(se401->height);
940 /****************************************************************************
944 ***************************************************************************/
947 static int se401_open(struct file *file)
949 struct video_device *dev = video_devdata(file);
950 struct usb_se401 *se401 = (struct usb_se401 *)dev;
958 se401->fbuf = rvmalloc(se401->maxframesize * SE401_NUMFRAMES);
960 file->private_data = dev;
969 static int se401_close(struct file *file)
971 struct video_device *dev = file->private_data;
972 struct usb_se401 *se401 = (struct usb_se401 *)dev;
975 rvfree(se401->fbuf, se401->maxframesize * SE401_NUMFRAMES);
976 if (se401->removed) {
977 dev_info(&se401->dev->dev, "device unregistered\n");
978 usb_se401_remove_disconnected(se401);
980 for (i = 0; i < SE401_NUMFRAMES; i++)
981 se401->frame[i].grabstate = FRAME_UNUSED;
982 if (se401->streaming)
983 se401_stop_stream(se401);
986 file->private_data = NULL;
990 static long se401_do_ioctl(struct file *file, unsigned int cmd, void *arg)
992 struct video_device *vdev = file->private_data;
993 struct usb_se401 *se401 = (struct usb_se401 *)vdev;
1001 struct video_capability *b = arg;
1002 strcpy(b->name, se401->camera_name);
1003 b->type = VID_TYPE_CAPTURE;
1006 b->maxwidth = se401->width[se401->sizes-1];
1007 b->maxheight = se401->height[se401->sizes-1];
1008 b->minwidth = se401->width[0];
1009 b->minheight = se401->height[0];
1014 struct video_channel *v = arg;
1016 if (v->channel != 0)
1020 v->type = VIDEO_TYPE_CAMERA;
1021 strcpy(v->name, "Camera");
1026 struct video_channel *v = arg;
1028 if (v->channel != 0)
1034 struct video_picture *p = arg;
1036 se401_get_pict(se401, p);
1041 struct video_picture *p = arg;
1043 if (se401_set_pict(se401, p))
1049 struct video_window *vw = arg;
1055 if (se401_set_size(se401, vw->width, vw->height))
1061 struct video_window *vw = arg;
1063 vw->x = 0; /* FIXME */
1068 vw->width = se401->cwidth;
1069 vw->height = se401->cheight;
1074 struct video_mbuf *vm = arg;
1077 memset(vm, 0, sizeof(*vm));
1078 vm->size = SE401_NUMFRAMES * se401->maxframesize;
1079 vm->frames = SE401_NUMFRAMES;
1080 for (i = 0; i < SE401_NUMFRAMES; i++)
1081 vm->offsets[i] = se401->maxframesize * i;
1084 case VIDIOCMCAPTURE:
1086 struct video_mmap *vm = arg;
1088 if (vm->format != VIDEO_PALETTE_RGB24)
1090 if (vm->frame >= SE401_NUMFRAMES)
1092 if (se401->frame[vm->frame].grabstate != FRAME_UNUSED)
1095 /* Is this according to the v4l spec??? */
1096 if (se401_set_size(se401, vm->width, vm->height))
1098 se401->frame[vm->frame].grabstate = FRAME_READY;
1100 if (!se401->streaming)
1101 se401_start_stream(se401);
1103 /* Set the picture properties */
1104 if (se401->framecount == 0)
1105 se401_send_pict(se401);
1106 /* Calibrate the reset level after a few frames. */
1107 if (se401->framecount % 20 == 1)
1108 se401_auto_resetlevel(se401);
1117 if (*frame < 0 || *frame >= SE401_NUMFRAMES)
1120 ret = se401_newframe(se401, *frame);
1121 se401->frame[*frame].grabstate = FRAME_UNUSED;
1126 struct video_buffer *vb = arg;
1128 memset(vb, 0, sizeof(*vb));
1147 return -ENOIOCTLCMD;
1153 static long se401_ioctl(struct file *file,
1154 unsigned int cmd, unsigned long arg)
1156 return video_usercopy(file, cmd, arg, se401_do_ioctl);
1159 static ssize_t se401_read(struct file *file, char __user *buf,
1160 size_t count, loff_t *ppos)
1162 int realcount = count, ret = 0;
1163 struct video_device *dev = file->private_data;
1164 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1167 if (se401->dev == NULL)
1169 if (realcount > se401->cwidth*se401->cheight*3)
1170 realcount = se401->cwidth*se401->cheight*3;
1172 /* Shouldn't happen: */
1173 if (se401->frame[0].grabstate == FRAME_GRABBING)
1175 se401->frame[0].grabstate = FRAME_READY;
1176 se401->frame[1].grabstate = FRAME_UNUSED;
1177 se401->curframe = 0;
1179 if (!se401->streaming)
1180 se401_start_stream(se401);
1182 /* Set the picture properties */
1183 if (se401->framecount == 0)
1184 se401_send_pict(se401);
1185 /* Calibrate the reset level after a few frames. */
1186 if (se401->framecount%20 == 1)
1187 se401_auto_resetlevel(se401);
1189 ret = se401_newframe(se401, 0);
1191 se401->frame[0].grabstate = FRAME_UNUSED;
1194 if (copy_to_user(buf, se401->frame[0].data, realcount))
1200 static int se401_mmap(struct file *file, struct vm_area_struct *vma)
1202 struct video_device *dev = file->private_data;
1203 struct usb_se401 *se401 = (struct usb_se401 *)dev;
1204 unsigned long start = vma->vm_start;
1205 unsigned long size = vma->vm_end-vma->vm_start;
1206 unsigned long page, pos;
1208 mutex_lock(&se401->lock);
1210 if (se401->dev == NULL) {
1211 mutex_unlock(&se401->lock);
1214 if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1)
1215 & ~(PAGE_SIZE - 1))) {
1216 mutex_unlock(&se401->lock);
1219 pos = (unsigned long)se401->fbuf;
1221 page = vmalloc_to_pfn((void *)pos);
1222 if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
1223 mutex_unlock(&se401->lock);
1228 if (size > PAGE_SIZE)
1233 mutex_unlock(&se401->lock);
1238 static const struct v4l2_file_operations se401_fops = {
1239 .owner = THIS_MODULE,
1241 .release = se401_close,
1244 .ioctl = se401_ioctl,
1246 static struct video_device se401_template = {
1247 .name = "se401 USB camera",
1248 .fops = &se401_fops,
1249 .release = video_device_release_empty,
1254 /***************************/
1255 static int se401_init(struct usb_se401 *se401, int button)
1258 unsigned char cp[0x40];
1263 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1265 /* get camera descriptor */
1266 rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0,
1268 if (cp[1] != 0x41) {
1269 err("Wrong descriptor type");
1272 slen = snprintf(temp, 200, "ExtraFeatures: %d", cp[3]);
1274 se401->sizes = cp[4] + cp[5] * 256;
1275 se401->width = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1278 se401->height = kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);
1279 if (!se401->height) {
1280 kfree(se401->width);
1283 for (i = 0; i < se401->sizes; i++) {
1284 se401->width[i] = cp[6 + i * 4 + 0] + cp[6 + i*4 + 1] * 256;
1285 se401->height[i] = cp[6 + i * 4 + 2] + cp[6 + i * 4 + 3] * 256;
1287 slen += snprintf(temp + slen, 200 - slen, " Sizes:");
1288 for (i = 0; i < se401->sizes; i++) {
1289 slen += snprintf(temp + slen, 200 - slen,
1290 " %dx%d", se401->width[i], se401->height[i]);
1292 dev_info(&se401->dev->dev, "%s\n", temp);
1293 se401->maxframesize = se401->width[se401->sizes-1] *
1294 se401->height[se401->sizes - 1] * 3;
1296 rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp));
1297 se401->cwidth = cp[0]+cp[1]*256;
1298 rc = se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));
1299 se401->cheight = cp[0]+cp[1]*256;
1301 if (!(cp[2] & SE401_FORMAT_BAYER)) {
1302 err("Bayer format not supported!");
1305 /* set output mode (BAYER) */
1306 se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE,
1307 SE401_FORMAT_BAYER, NULL, 0);
1309 rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp));
1310 se401->brightness = cp[0]+cp[1]*256;
1311 /* some default values */
1312 se401->resetlevel = 0x2d;
1313 se401->rgain = 0x20;
1314 se401->ggain = 0x20;
1315 se401->bgain = 0x20;
1316 se401_set_exposure(se401, 20000);
1317 se401->palette = VIDEO_PALETTE_RGB24;
1321 se401->framecount = 0;
1322 se401->readcount = 0;
1324 /* Start interrupt transfers for snapshot button */
1326 se401->inturb = usb_alloc_urb(0, GFP_KERNEL);
1327 if (!se401->inturb) {
1328 dev_info(&se401->dev->dev,
1329 "Allocation of inturb failed\n");
1332 usb_fill_int_urb(se401->inturb, se401->dev,
1333 usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),
1334 &se401->button, sizeof(se401->button),
1339 if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {
1340 dev_info(&se401->dev->dev, "int urb burned down\n");
1344 se401->inturb = NULL;
1347 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);
1348 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);
1349 se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);
1350 se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);
1355 static int se401_probe(struct usb_interface *intf,
1356 const struct usb_device_id *id)
1358 struct usb_device *dev = interface_to_usbdev(intf);
1359 struct usb_interface_descriptor *interface;
1360 struct usb_se401 *se401;
1361 char *camera_name = NULL;
1364 /* We don't handle multi-config cameras */
1365 if (dev->descriptor.bNumConfigurations != 1)
1368 interface = &intf->cur_altsetting->desc;
1370 /* Is it an se401? */
1371 if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
1372 le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
1373 camera_name = "Endpoints/Aox SE401";
1374 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
1375 le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
1376 camera_name = "Philips PCVC665K";
1377 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1378 le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
1379 camera_name = "Kensington VideoCAM 67014";
1380 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1381 le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
1382 camera_name = "Kensington VideoCAM 6701(5/7)";
1383 } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
1384 le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
1385 camera_name = "Kensington VideoCAM 67016";
1390 /* Checking vendor/product should be enough, but what the hell */
1391 if (interface->bInterfaceClass != 0x00)
1393 if (interface->bInterfaceSubClass != 0x00)
1397 dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name);
1399 se401 = kzalloc(sizeof(*se401), GFP_KERNEL);
1400 if (se401 == NULL) {
1401 err("couldn't kmalloc se401 struct");
1406 se401->iface = interface->bInterfaceNumber;
1407 se401->camera_name = camera_name;
1409 dev_info(&intf->dev, "firmware version: %02x\n",
1410 le16_to_cpu(dev->descriptor.bcdDevice) & 255);
1412 if (se401_init(se401, button)) {
1417 memcpy(&se401->vdev, &se401_template, sizeof(se401_template));
1418 memcpy(se401->vdev.name, se401->camera_name,
1419 strlen(se401->camera_name));
1420 init_waitqueue_head(&se401->wq);
1421 mutex_init(&se401->lock);
1424 if (video_register_device(&se401->vdev,
1425 VFL_TYPE_GRABBER, video_nr) < 0) {
1427 err("video_register_device failed");
1430 dev_info(&intf->dev, "registered new video device: video%d\n",
1433 usb_set_intfdata(intf, se401);
1437 static void se401_disconnect(struct usb_interface *intf)
1439 struct usb_se401 *se401 = usb_get_intfdata(intf);
1441 usb_set_intfdata(intf, NULL);
1443 video_unregister_device(&se401->vdev);
1445 usb_se401_remove_disconnected(se401);
1447 se401->frame[0].grabstate = FRAME_ERROR;
1448 se401->frame[0].grabstate = FRAME_ERROR;
1450 se401->streaming = 0;
1452 wake_up_interruptible(&se401->wq);
1458 static struct usb_driver se401_driver = {
1460 .id_table = device_table,
1461 .probe = se401_probe,
1462 .disconnect = se401_disconnect,
1467 /****************************************************************************
1471 ***************************************************************************/
1473 static int __init usb_se401_init(void)
1475 printk(KERN_INFO "SE401 usb camera driver version %s registering\n",
1478 if (flickerless != 50 && flickerless != 60) {
1479 printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n");
1482 return usb_register(&se401_driver);
1485 static void __exit usb_se401_exit(void)
1487 usb_deregister(&se401_driver);
1488 printk(KERN_INFO "SE401 driver deregistered\frame");
1491 module_init(usb_se401_init);
1492 module_exit(usb_se401_exit);