Loading drivers/media/video/se401.c +448 −428 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); MODULE_DESCRIPTION("SE401 USB Camera Driver"); MODULE_LICENSE("GPL"); module_param(flickerless, int, 0); MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); module_param(video_nr, int, 0); static struct usb_driver se401_driver; Loading Loading @@ -175,13 +176,20 @@ static unsigned short se401_get_feature(struct usb_se401 *se401, static int se401_send_pict(struct usb_se401 *se401) { se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */ se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */ se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */ se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */ se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ /* integration time low */ se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); /* integration time mid */ se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); /* integration time mid */ se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); /* reset level value */ se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); /* red color gain */ se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); /* green color gain */ se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); /* blue color gain */ se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); return 0; } Loading @@ -190,12 +198,10 @@ static void se401_set_exposure(struct usb_se401 *se401, int brightness) { int integration = brightness << 5; if (flickerless==50) { if (flickerless == 50) integration = integration-integration % 106667; } if (flickerless==60) { if (flickerless == 60) integration = integration-integration % 88889; } se401->brightness = integration >> 5; se401->expose_h = (integration >> 16) & 0xff; se401->expose_m = (integration >> 8) & 0xff; Loading @@ -205,11 +211,11 @@ static void se401_set_exposure(struct usb_se401 *se401, int brightness) static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) { p->brightness = se401->brightness; if (se401->enhance) { if (se401->enhance) p->whiteness = 32768; } else { else p->whiteness = 0; } p->colour = 65535; p->contrast = 65535; p->hue = se401->rgain << 10; Loading @@ -229,14 +235,13 @@ static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) se401->bgain = 0x40-(p->hue >> 10); se401->hue = p->hue; } if (p->brightness!=se401->brightness) { if (p->brightness != se401->brightness) se401_set_exposure(se401, p->brightness); } if (p->whiteness>=32768) { if (p->whiteness >= 32768) se401->enhance = 1; } else { else se401->enhance = 0; } se401_send_pict(se401); se401_send_pict(se401); return 0; Loading Loading @@ -300,17 +305,18 @@ static void se401_button_irq(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, urb->status); dbg("%s - urb shutting down with status: %d", __func__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __func__, urb->status); dbg("%s - nonzero urb status received: %d", __func__, urb->status); goto exit; } if (urb->actual_length >=2) { if (urb->actual_length >= 2) if (se401->button) se401->buttonpressed = 1; } exit: status = usb_submit_urb(urb, GFP_ATOMIC); if (status) Loading Loading @@ -339,37 +345,34 @@ static void se401_video_irq(struct urb *urb) se401->nullpackets = 0; switch (se401->scratch[se401->scratch_next].state) { case BUFFER_READY: case BUFFER_BUSY: { case BUFFER_BUSY: se401->dropped++; break; } case BUFFER_UNUSED: { memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); se401->scratch[se401->scratch_next].state=BUFFER_READY; se401->scratch[se401->scratch_next].offset=se401->bayeroffset; case BUFFER_UNUSED: memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); se401->scratch[se401->scratch_next].state = BUFFER_READY; se401->scratch[se401->scratch_next].offset = se401->bayeroffset; se401->scratch[se401->scratch_next].length = length; if (waitqueue_active(&se401->wq)) { if (waitqueue_active(&se401->wq)) wake_up_interruptible(&se401->wq); } se401->scratch_overflow = 0; se401->scratch_next++; if (se401->scratch_next >= SE401_NUMSCRATCH) se401->scratch_next = 0; break; } } se401->bayeroffset += length; if (se401->bayeroffset>=se401->cheight*se401->cwidth) { if (se401->bayeroffset >= se401->cheight * se401->cwidth) se401->bayeroffset = 0; } } else { se401->nullpackets++; if (se401->nullpackets > SE401_MAX_NULLPACKETS) { if (waitqueue_active(&se401->wq)) { if (se401->nullpackets > SE401_MAX_NULLPACKETS) if (waitqueue_active(&se401->wq)) wake_up_interruptible(&se401->wq); } } } /* Resubmit urb for new data */ urb->status = 0; Loading @@ -392,15 +395,18 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) 4 or 16 times subcapturing, if not we use uncompressed bayer data but this will result in cutouts of the maximum size.... */ while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height)) while (i < se401->sizes && !(se401->width[i] == width && se401->height[i] == height)) i++; while (i < se401->sizes) { if (se401->width[i]==width*2 && se401->height[i]==height*2) { if (se401->width[i] == width * 2 && se401->height[i] == height * 2) { sendheight = se401->height[i]; sendwidth = se401->width[i]; mode = 0x40; } if (se401->width[i]==width*4 && se401->height[i]==height*4) { if (se401->width[i] == width * 4 && se401->height[i] == height * 4) { sendheight = se401->height[i]; sendwidth = se401->width[i]; mode = 0x42; Loading @@ -412,15 +418,12 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); se401_set_feature(se401, SE401_OPERATINGMODE, mode); if (mode==0x03) { if (mode == 0x03) se401->format = FMT_BAYER; } else { else se401->format = FMT_JANGGU; } return; } /* In this function se401_send_pict is called several times, for some reason (depending on the state of the sensor and the phase of Loading @@ -436,12 +439,14 @@ static int se401_start_stream(struct usb_se401 *se401) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* Set picture settings */ se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ /* windowed + pix intg */ se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); se401_send_pict(se401); se401_send_size(se401, se401->cwidth, se401->cheight); se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); /* Do some memory allocation */ for (i = 0; i < SE401_NUMFRAMES; i++) { Loading Loading @@ -530,7 +535,8 @@ static int se401_stop_stream(struct usb_se401 *se401) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) { for (i = 0; i < SE401_NUMSBUF; i++) if (se401->urb[i]) { usb_kill_urb(se401->urb[i]); usb_free_urb(se401->urb[i]); se401->urb[i] = NULL; Loading Loading @@ -604,16 +610,16 @@ static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) /* First three are absolute, all others relative. * Format is rgb from right to left (mirrorred image), * we flip it to get bgr from left to right. */ if (frame->curlinepix < 3) { if (frame->curlinepix < 3) *(frame->curline-frame->curlinepix) = 1 + data * 4; } else { else *(frame->curline-frame->curlinepix) = *(frame->curline-frame->curlinepix + 3) + data * 4; } frame->curlinepix++; } static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) static inline void decode_JangGu_vlc(struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) { int pos = 0; int vlc_cod = 0; Loading @@ -630,9 +636,9 @@ static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *da if (bit) { vlc_size++; } else { if (!vlc_size) { if (!vlc_size) decode_JangGu_integrate(se401, 0); } else { else { vlc_cod = 2; vlc_data = 0; } Loading @@ -658,7 +664,8 @@ static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *da } } static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer) static inline void decode_JangGu(struct usb_se401 *se401, struct se401_scratch *buffer) { unsigned char *data = buffer->data; int len = buffer->length; Loading @@ -684,7 +691,8 @@ static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch packetlength = 0; if (se401->vlcdatapos >= 4) { bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8); pix_exp = se401->vlcdata[1] + ((se401->vlcdata[0] & 0x3f) << 8); frameinfo = se401->vlcdata[0] & 0xc0; packetlength = ((bit_exp + 47) >> 4) << 1; if (packetlength > 1024) { Loading @@ -696,7 +704,8 @@ static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch } } if (packetlength && se401->vlcdatapos >= packetlength) { decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); se401->frame[se401->curframe].curpix += pix_exp * 3; datapos += size-(se401->vlcdatapos-packetlength); se401->vlcdatapos = 0; Loading @@ -707,29 +716,26 @@ static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch se401->framecount++; se401->readcount++; } if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); } } else { } else se401->error++; } se401->frame[se401->curframe].curpix = 0; datapos = len; } } else { } else datapos += size; } } } static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer) static inline void decode_bayer(struct usb_se401 *se401, struct se401_scratch *buffer) { unsigned char *data = buffer->data; int len = buffer->length; int offset = buffer->offset; int datasize = se401->cwidth * se401->cheight; struct se401_frame *frame = &se401->frame[se401->curframe]; unsigned char *framedata = frame->data, *curline, *nextline; int width = se401->cwidth; int blineoffset = 0, bline; Loading @@ -737,9 +743,9 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * if (frame->curpix == 0) { if (frame->grabstate==FRAME_READY) { if (frame->grabstate == FRAME_READY) frame->grabstate = FRAME_GRABBING; } frame->curline = framedata + linelength; frame->curlinepix = 0; } Loading @@ -752,9 +758,9 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * } /* Check if we have to much data */ if (frame->curpix+len > datasize) { if (frame->curpix + len > datasize) len = datasize-frame->curpix; } if (se401->cheight % 4) blineoffset = 1; bline = frame->curpix / se401->cwidth+blineoffset; Loading @@ -780,8 +786,8 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * if (nextline >= framedata+datasize*3) nextline = curline; } if ((bline&1)) { if ((frame->curlinepix&1)) { if (bline & 1) { if (frame->curlinepix & 1) { *(curline + 2) = *data; *(curline - 1) = *data; *(nextline + 2) = *data; Loading @@ -795,7 +801,7 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * *(nextline - 2) = *data; } } else { if ((frame->curlinepix&1)) { if (frame->curlinepix & 1) { *(curline + 1) = (*(curline + 1) + *data) / 2; *(curline - 2) = Loading Loading @@ -836,8 +842,10 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * frame->grabstate = FRAME_DONE; se401->framecount++; se401->readcount++; if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { se401->curframe = (se401->curframe+1) & (SE401_NUMFRAMES-1); } } } Loading @@ -850,14 +858,12 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) while (se401->streaming && (se401->frame[framenr].grabstate == FRAME_READY || se401->frame[framenr].grabstate == FRAME_GRABBING)) { if(!se401->frame[framenr].curpix) { if (!se401->frame[framenr].curpix) errors++; } wait_interruptible( se401->scratch[se401->scratch_use].state != BUFFER_READY, &se401->wq, &wait ); &se401->wq, &wait); if (se401->nullpackets > SE401_MAX_NULLPACKETS) { se401->nullpackets = 0; dev_info(&se401->dev->dev, Loading @@ -865,17 +871,21 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) se401_stop_stream(se401); se401_start_stream(se401); } else { if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { if (se401->scratch[se401->scratch_use].state != BUFFER_READY) { se401->frame[framenr].grabstate = FRAME_ERROR; return -EIO; } se401->scratch[se401->scratch_use].state = BUFFER_BUSY; if (se401->format==FMT_JANGGU) { decode_JangGu(se401, &se401->scratch[se401->scratch_use]); } else { decode_bayer(se401, &se401->scratch[se401->scratch_use]); } se401->scratch[se401->scratch_use].state=BUFFER_UNUSED; if (se401->format == FMT_JANGGU) decode_JangGu(se401, &se401->scratch[se401->scratch_use]); else decode_bayer(se401, &se401->scratch[se401->scratch_use]); se401->scratch[se401->scratch_use].state = BUFFER_UNUSED; se401->scratch_use++; if (se401->scratch_use >= SE401_NUMSCRATCH) se401->scratch_use = 0; Loading @@ -891,7 +901,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) if (se401->frame[framenr].grabstate == FRAME_DONE) if (se401->enhance) enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); enhance_picture(se401->frame[framenr].data, se401->cheight * se401->cwidth * 3); return 0; } Loading @@ -908,9 +919,10 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) se401->urb[i] = NULL; kfree(se401->sbuf[i].data); } for (i=0; i<SE401_NUMSCRATCH; i++) { for (i = 0; i < SE401_NUMSCRATCH; i++) kfree(se401->scratch[i].data); } if (se401->inturb) { usb_kill_urb(se401->inturb); usb_free_urb(se401->inturb); Loading Loading @@ -1199,7 +1211,8 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) mutex_unlock(&se401->lock); return -EIO; } if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { mutex_unlock(&se401->lock); return -EINVAL; } Loading Loading @@ -1250,7 +1263,8 @@ static int se401_init(struct usb_se401 *se401, int button) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* get camera descriptor */ rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); if (cp[1] != 0x41) { err("Wrong descriptor type"); return 1; Loading @@ -1276,7 +1290,8 @@ static int se401_init(struct usb_se401 *se401, int button) " %dx%d", se401->width[i], se401->height[i]); } dev_info(&se401->dev->dev, "%s\n", temp); se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; se401->maxframesize = se401->width[se401->sizes-1] * se401->height[se401->sizes - 1] * 3; rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); se401->cwidth = cp[0]+cp[1]*256; Loading @@ -1288,7 +1303,8 @@ static int se401_init(struct usb_se401 *se401, int button) return 1; } /* set output mode (BAYER) */ se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); se401->brightness = cp[0]+cp[1]*256; Loading Loading @@ -1380,7 +1396,8 @@ static int se401_probe(struct usb_interface *intf, /* We found one */ dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { se401 = kzalloc(sizeof(*se401), GFP_KERNEL); if (se401 == NULL) { err("couldn't kmalloc se401 struct"); return -ENOMEM; } Loading @@ -1398,12 +1415,14 @@ static int se401_probe(struct usb_interface *intf, } memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); init_waitqueue_head(&se401->wq); mutex_init(&se401->lock); wmb(); if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { kfree(se401); err("video_register_device failed"); return -EIO; Loading @@ -1422,9 +1441,9 @@ static void se401_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (se401) { video_unregister_device(&se401->vdev); if (!se401->user){ if (!se401->user) usb_se401_remove_disconnected(se401); } else { else { se401->frame[0].grabstate = FRAME_ERROR; se401->frame[0].grabstate = FRAME_ERROR; Loading Loading @@ -1453,7 +1472,8 @@ static struct usb_driver se401_driver = { static int __init usb_se401_init(void) { printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); if (flickerless) if (flickerless != 50 && flickerless != 60) { printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); Loading drivers/media/video/se401.h +4 −3 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ #ifndef __LINUX_se401_H #define __LINUX_se401_H #include <asm/uaccess.h> #include <linux/uaccess.h> #include <linux/videodev.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> Loading @@ -12,7 +12,8 @@ #ifdef se401_DEBUG # define PDEBUG(level, fmt, args...) \ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) if (debug >= level) \ info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) #else # define PDEBUG(level, fmt, args...) do {} while (0) #endif Loading Loading
drivers/media/video/se401.c +448 −428 Original line number Diff line number Diff line Loading @@ -53,7 +53,8 @@ MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); MODULE_DESCRIPTION("SE401 USB Camera Driver"); MODULE_LICENSE("GPL"); module_param(flickerless, int, 0); MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); MODULE_PARM_DESC(flickerless, "Net frequency to adjust exposure time to (0/50/60)"); module_param(video_nr, int, 0); static struct usb_driver se401_driver; Loading Loading @@ -175,13 +176,20 @@ static unsigned short se401_get_feature(struct usb_se401 *se401, static int se401_send_pict(struct usb_se401 *se401) { se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l);/* integration time low */ se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m);/* integration time mid */ se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h);/* integration time mid */ se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel);/* reset level value */ se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain);/* red color gain */ se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain);/* green color gain */ se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain);/* blue color gain */ /* integration time low */ se401_set_feature(se401, HV7131_REG_TITL, se401->expose_l); /* integration time mid */ se401_set_feature(se401, HV7131_REG_TITM, se401->expose_m); /* integration time mid */ se401_set_feature(se401, HV7131_REG_TITU, se401->expose_h); /* reset level value */ se401_set_feature(se401, HV7131_REG_ARLV, se401->resetlevel); /* red color gain */ se401_set_feature(se401, HV7131_REG_ARCG, se401->rgain); /* green color gain */ se401_set_feature(se401, HV7131_REG_AGCG, se401->ggain); /* blue color gain */ se401_set_feature(se401, HV7131_REG_ABCG, se401->bgain); return 0; } Loading @@ -190,12 +198,10 @@ static void se401_set_exposure(struct usb_se401 *se401, int brightness) { int integration = brightness << 5; if (flickerless==50) { if (flickerless == 50) integration = integration-integration % 106667; } if (flickerless==60) { if (flickerless == 60) integration = integration-integration % 88889; } se401->brightness = integration >> 5; se401->expose_h = (integration >> 16) & 0xff; se401->expose_m = (integration >> 8) & 0xff; Loading @@ -205,11 +211,11 @@ static void se401_set_exposure(struct usb_se401 *se401, int brightness) static int se401_get_pict(struct usb_se401 *se401, struct video_picture *p) { p->brightness = se401->brightness; if (se401->enhance) { if (se401->enhance) p->whiteness = 32768; } else { else p->whiteness = 0; } p->colour = 65535; p->contrast = 65535; p->hue = se401->rgain << 10; Loading @@ -229,14 +235,13 @@ static int se401_set_pict(struct usb_se401 *se401, struct video_picture *p) se401->bgain = 0x40-(p->hue >> 10); se401->hue = p->hue; } if (p->brightness!=se401->brightness) { if (p->brightness != se401->brightness) se401_set_exposure(se401, p->brightness); } if (p->whiteness>=32768) { if (p->whiteness >= 32768) se401->enhance = 1; } else { else se401->enhance = 0; } se401_send_pict(se401); se401_send_pict(se401); return 0; Loading Loading @@ -300,17 +305,18 @@ static void se401_button_irq(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __func__, urb->status); dbg("%s - urb shutting down with status: %d", __func__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __func__, urb->status); dbg("%s - nonzero urb status received: %d", __func__, urb->status); goto exit; } if (urb->actual_length >=2) { if (urb->actual_length >= 2) if (se401->button) se401->buttonpressed = 1; } exit: status = usb_submit_urb(urb, GFP_ATOMIC); if (status) Loading Loading @@ -339,37 +345,34 @@ static void se401_video_irq(struct urb *urb) se401->nullpackets = 0; switch (se401->scratch[se401->scratch_next].state) { case BUFFER_READY: case BUFFER_BUSY: { case BUFFER_BUSY: se401->dropped++; break; } case BUFFER_UNUSED: { memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); se401->scratch[se401->scratch_next].state=BUFFER_READY; se401->scratch[se401->scratch_next].offset=se401->bayeroffset; case BUFFER_UNUSED: memcpy(se401->scratch[se401->scratch_next].data, (unsigned char *)urb->transfer_buffer, length); se401->scratch[se401->scratch_next].state = BUFFER_READY; se401->scratch[se401->scratch_next].offset = se401->bayeroffset; se401->scratch[se401->scratch_next].length = length; if (waitqueue_active(&se401->wq)) { if (waitqueue_active(&se401->wq)) wake_up_interruptible(&se401->wq); } se401->scratch_overflow = 0; se401->scratch_next++; if (se401->scratch_next >= SE401_NUMSCRATCH) se401->scratch_next = 0; break; } } se401->bayeroffset += length; if (se401->bayeroffset>=se401->cheight*se401->cwidth) { if (se401->bayeroffset >= se401->cheight * se401->cwidth) se401->bayeroffset = 0; } } else { se401->nullpackets++; if (se401->nullpackets > SE401_MAX_NULLPACKETS) { if (waitqueue_active(&se401->wq)) { if (se401->nullpackets > SE401_MAX_NULLPACKETS) if (waitqueue_active(&se401->wq)) wake_up_interruptible(&se401->wq); } } } /* Resubmit urb for new data */ urb->status = 0; Loading @@ -392,15 +395,18 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) 4 or 16 times subcapturing, if not we use uncompressed bayer data but this will result in cutouts of the maximum size.... */ while (i<se401->sizes && !(se401->width[i]==width && se401->height[i]==height)) while (i < se401->sizes && !(se401->width[i] == width && se401->height[i] == height)) i++; while (i < se401->sizes) { if (se401->width[i]==width*2 && se401->height[i]==height*2) { if (se401->width[i] == width * 2 && se401->height[i] == height * 2) { sendheight = se401->height[i]; sendwidth = se401->width[i]; mode = 0x40; } if (se401->width[i]==width*4 && se401->height[i]==height*4) { if (se401->width[i] == width * 4 && se401->height[i] == height * 4) { sendheight = se401->height[i]; sendwidth = se401->width[i]; mode = 0x42; Loading @@ -412,15 +418,12 @@ static void se401_send_size(struct usb_se401 *se401, int width, int height) se401_sndctrl(1, se401, SE401_REQ_SET_HEIGHT, sendheight, NULL, 0); se401_set_feature(se401, SE401_OPERATINGMODE, mode); if (mode==0x03) { if (mode == 0x03) se401->format = FMT_BAYER; } else { else se401->format = FMT_JANGGU; } return; } /* In this function se401_send_pict is called several times, for some reason (depending on the state of the sensor and the phase of Loading @@ -436,12 +439,14 @@ static int se401_start_stream(struct usb_se401 *se401) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* Set picture settings */ se401_set_feature(se401, HV7131_REG_MODE_B, 0x05);/*windowed + pix intg */ /* windowed + pix intg */ se401_set_feature(se401, HV7131_REG_MODE_B, 0x05); se401_send_pict(se401); se401_send_size(se401, se401->cwidth, se401->cheight); se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_START_CONTINUOUS_CAPTURE, 0, NULL, 0); /* Do some memory allocation */ for (i = 0; i < SE401_NUMFRAMES; i++) { Loading Loading @@ -530,7 +535,8 @@ static int se401_stop_stream(struct usb_se401 *se401) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0); for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) { for (i = 0; i < SE401_NUMSBUF; i++) if (se401->urb[i]) { usb_kill_urb(se401->urb[i]); usb_free_urb(se401->urb[i]); se401->urb[i] = NULL; Loading Loading @@ -604,16 +610,16 @@ static inline void decode_JangGu_integrate(struct usb_se401 *se401, int data) /* First three are absolute, all others relative. * Format is rgb from right to left (mirrorred image), * we flip it to get bgr from left to right. */ if (frame->curlinepix < 3) { if (frame->curlinepix < 3) *(frame->curline-frame->curlinepix) = 1 + data * 4; } else { else *(frame->curline-frame->curlinepix) = *(frame->curline-frame->curlinepix + 3) + data * 4; } frame->curlinepix++; } static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) static inline void decode_JangGu_vlc(struct usb_se401 *se401, unsigned char *data, int bit_exp, int packetlength) { int pos = 0; int vlc_cod = 0; Loading @@ -630,9 +636,9 @@ static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *da if (bit) { vlc_size++; } else { if (!vlc_size) { if (!vlc_size) decode_JangGu_integrate(se401, 0); } else { else { vlc_cod = 2; vlc_data = 0; } Loading @@ -658,7 +664,8 @@ static inline void decode_JangGu_vlc (struct usb_se401 *se401, unsigned char *da } } static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch *buffer) static inline void decode_JangGu(struct usb_se401 *se401, struct se401_scratch *buffer) { unsigned char *data = buffer->data; int len = buffer->length; Loading @@ -684,7 +691,8 @@ static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch packetlength = 0; if (se401->vlcdatapos >= 4) { bit_exp = se401->vlcdata[3] + (se401->vlcdata[2] << 8); pix_exp=se401->vlcdata[1]+((se401->vlcdata[0]&0x3f)<<8); pix_exp = se401->vlcdata[1] + ((se401->vlcdata[0] & 0x3f) << 8); frameinfo = se401->vlcdata[0] & 0xc0; packetlength = ((bit_exp + 47) >> 4) << 1; if (packetlength > 1024) { Loading @@ -696,7 +704,8 @@ static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch } } if (packetlength && se401->vlcdatapos >= packetlength) { decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); decode_JangGu_vlc(se401, se401->vlcdata, bit_exp, packetlength); se401->frame[se401->curframe].curpix += pix_exp * 3; datapos += size-(se401->vlcdatapos-packetlength); se401->vlcdatapos = 0; Loading @@ -707,29 +716,26 @@ static inline void decode_JangGu (struct usb_se401 *se401, struct se401_scratch se401->framecount++; se401->readcount++; } if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) se401->curframe = (se401->curframe + 1) & (SE401_NUMFRAMES - 1); } } else { } else se401->error++; } se401->frame[se401->curframe].curpix = 0; datapos = len; } } else { } else datapos += size; } } } static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch *buffer) static inline void decode_bayer(struct usb_se401 *se401, struct se401_scratch *buffer) { unsigned char *data = buffer->data; int len = buffer->length; int offset = buffer->offset; int datasize = se401->cwidth * se401->cheight; struct se401_frame *frame = &se401->frame[se401->curframe]; unsigned char *framedata = frame->data, *curline, *nextline; int width = se401->cwidth; int blineoffset = 0, bline; Loading @@ -737,9 +743,9 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * if (frame->curpix == 0) { if (frame->grabstate==FRAME_READY) { if (frame->grabstate == FRAME_READY) frame->grabstate = FRAME_GRABBING; } frame->curline = framedata + linelength; frame->curlinepix = 0; } Loading @@ -752,9 +758,9 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * } /* Check if we have to much data */ if (frame->curpix+len > datasize) { if (frame->curpix + len > datasize) len = datasize-frame->curpix; } if (se401->cheight % 4) blineoffset = 1; bline = frame->curpix / se401->cwidth+blineoffset; Loading @@ -780,8 +786,8 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * if (nextline >= framedata+datasize*3) nextline = curline; } if ((bline&1)) { if ((frame->curlinepix&1)) { if (bline & 1) { if (frame->curlinepix & 1) { *(curline + 2) = *data; *(curline - 1) = *data; *(nextline + 2) = *data; Loading @@ -795,7 +801,7 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * *(nextline - 2) = *data; } } else { if ((frame->curlinepix&1)) { if (frame->curlinepix & 1) { *(curline + 1) = (*(curline + 1) + *data) / 2; *(curline - 2) = Loading Loading @@ -836,8 +842,10 @@ static inline void decode_bayer (struct usb_se401 *se401, struct se401_scratch * frame->grabstate = FRAME_DONE; se401->framecount++; se401->readcount++; if (se401->frame[(se401->curframe+1)&(SE401_NUMFRAMES-1)].grabstate==FRAME_READY) { se401->curframe=(se401->curframe+1) & (SE401_NUMFRAMES-1); if (se401->frame[(se401->curframe + 1) & (SE401_NUMFRAMES - 1)].grabstate == FRAME_READY) { se401->curframe = (se401->curframe+1) & (SE401_NUMFRAMES-1); } } } Loading @@ -850,14 +858,12 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) while (se401->streaming && (se401->frame[framenr].grabstate == FRAME_READY || se401->frame[framenr].grabstate == FRAME_GRABBING)) { if(!se401->frame[framenr].curpix) { if (!se401->frame[framenr].curpix) errors++; } wait_interruptible( se401->scratch[se401->scratch_use].state != BUFFER_READY, &se401->wq, &wait ); &se401->wq, &wait); if (se401->nullpackets > SE401_MAX_NULLPACKETS) { se401->nullpackets = 0; dev_info(&se401->dev->dev, Loading @@ -865,17 +871,21 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) se401_stop_stream(se401); se401_start_stream(se401); } else { if (se401->scratch[se401->scratch_use].state!=BUFFER_READY) { if (se401->scratch[se401->scratch_use].state != BUFFER_READY) { se401->frame[framenr].grabstate = FRAME_ERROR; return -EIO; } se401->scratch[se401->scratch_use].state = BUFFER_BUSY; if (se401->format==FMT_JANGGU) { decode_JangGu(se401, &se401->scratch[se401->scratch_use]); } else { decode_bayer(se401, &se401->scratch[se401->scratch_use]); } se401->scratch[se401->scratch_use].state=BUFFER_UNUSED; if (se401->format == FMT_JANGGU) decode_JangGu(se401, &se401->scratch[se401->scratch_use]); else decode_bayer(se401, &se401->scratch[se401->scratch_use]); se401->scratch[se401->scratch_use].state = BUFFER_UNUSED; se401->scratch_use++; if (se401->scratch_use >= SE401_NUMSCRATCH) se401->scratch_use = 0; Loading @@ -891,7 +901,8 @@ static int se401_newframe(struct usb_se401 *se401, int framenr) if (se401->frame[framenr].grabstate == FRAME_DONE) if (se401->enhance) enhance_picture(se401->frame[framenr].data, se401->cheight*se401->cwidth*3); enhance_picture(se401->frame[framenr].data, se401->cheight * se401->cwidth * 3); return 0; } Loading @@ -908,9 +919,10 @@ static void usb_se401_remove_disconnected (struct usb_se401 *se401) se401->urb[i] = NULL; kfree(se401->sbuf[i].data); } for (i=0; i<SE401_NUMSCRATCH; i++) { for (i = 0; i < SE401_NUMSCRATCH; i++) kfree(se401->scratch[i].data); } if (se401->inturb) { usb_kill_urb(se401->inturb); usb_free_urb(se401->inturb); Loading Loading @@ -1199,7 +1211,8 @@ static int se401_mmap(struct file *file, struct vm_area_struct *vma) mutex_unlock(&se401->lock); return -EIO; } if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) { mutex_unlock(&se401->lock); return -EINVAL; } Loading Loading @@ -1250,7 +1263,8 @@ static int se401_init(struct usb_se401 *se401, int button) se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0); /* get camera descriptor */ rc=se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); rc = se401_sndctrl(0, se401, SE401_REQ_GET_CAMERA_DESCRIPTOR, 0, cp, sizeof(cp)); if (cp[1] != 0x41) { err("Wrong descriptor type"); return 1; Loading @@ -1276,7 +1290,8 @@ static int se401_init(struct usb_se401 *se401, int button) " %dx%d", se401->width[i], se401->height[i]); } dev_info(&se401->dev->dev, "%s\n", temp); se401->maxframesize=se401->width[se401->sizes-1]*se401->height[se401->sizes-1]*3; se401->maxframesize = se401->width[se401->sizes-1] * se401->height[se401->sizes - 1] * 3; rc = se401_sndctrl(0, se401, SE401_REQ_GET_WIDTH, 0, cp, sizeof(cp)); se401->cwidth = cp[0]+cp[1]*256; Loading @@ -1288,7 +1303,8 @@ static int se401_init(struct usb_se401 *se401, int button) return 1; } /* set output mode (BAYER) */ se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); se401_sndctrl(1, se401, SE401_REQ_SET_OUTPUT_MODE, SE401_FORMAT_BAYER, NULL, 0); rc = se401_sndctrl(0, se401, SE401_REQ_GET_BRT, 0, cp, sizeof(cp)); se401->brightness = cp[0]+cp[1]*256; Loading Loading @@ -1380,7 +1396,8 @@ static int se401_probe(struct usb_interface *intf, /* We found one */ dev_info(&intf->dev, "SE401 camera found: %s\n", camera_name); if ((se401 = kzalloc(sizeof(*se401), GFP_KERNEL)) == NULL) { se401 = kzalloc(sizeof(*se401), GFP_KERNEL); if (se401 == NULL) { err("couldn't kmalloc se401 struct"); return -ENOMEM; } Loading @@ -1398,12 +1415,14 @@ static int se401_probe(struct usb_interface *intf, } memcpy(&se401->vdev, &se401_template, sizeof(se401_template)); memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name)); init_waitqueue_head(&se401->wq); mutex_init(&se401->lock); wmb(); if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) < 0) { kfree(se401); err("video_register_device failed"); return -EIO; Loading @@ -1422,9 +1441,9 @@ static void se401_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); if (se401) { video_unregister_device(&se401->vdev); if (!se401->user){ if (!se401->user) usb_se401_remove_disconnected(se401); } else { else { se401->frame[0].grabstate = FRAME_ERROR; se401->frame[0].grabstate = FRAME_ERROR; Loading Loading @@ -1453,7 +1472,8 @@ static struct usb_driver se401_driver = { static int __init usb_se401_init(void) { printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); printk(KERN_INFO "SE401 usb camera driver version %s registering\n", version); if (flickerless) if (flickerless != 50 && flickerless != 60) { printk(KERN_ERR "Invallid flickerless value, use 0, 50 or 60.\n"); Loading
drivers/media/video/se401.h +4 −3 Original line number Diff line number Diff line Loading @@ -2,7 +2,7 @@ #ifndef __LINUX_se401_H #define __LINUX_se401_H #include <asm/uaccess.h> #include <linux/uaccess.h> #include <linux/videodev.h> #include <media/v4l2-common.h> #include <media/v4l2-ioctl.h> Loading @@ -12,7 +12,8 @@ #ifdef se401_DEBUG # define PDEBUG(level, fmt, args...) \ if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) if (debug >= level) \ info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) #else # define PDEBUG(level, fmt, args...) do {} while (0) #endif Loading