⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 se401.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        if (!se401->dev)                return -EIO;        switch (cmd) {	case VIDIOCGCAP:	{		struct video_capability b;		strcpy(b.name, se401->camera_name);		b.type = VID_TYPE_CAPTURE;		b.channels = 1;		b.audios = 0;		b.maxwidth = se401->width[se401->sizes-1];		b.maxheight = se401->height[se401->sizes-1];		b.minwidth = se401->width[0];		b.minheight = se401->height[0];		if (copy_to_user(arg, &b, sizeof(b)))			return -EFAULT;		return 0;	}	case VIDIOCGCHAN:	{		struct video_channel v;		if (copy_from_user(&v, arg, sizeof(v)))			return -EFAULT;		if (v.channel != 0)			return -EINVAL;		v.flags = 0;		v.tuners = 0;		v.type = VIDEO_TYPE_CAMERA;		strcpy(v.name, "Camera");		if (copy_to_user(arg, &v, sizeof(v)))			return -EFAULT;		return 0;	}	case VIDIOCSCHAN:	{		int v;		if (copy_from_user(&v, arg, sizeof(v)))			return -EFAULT;		if (v != 0)			return -EINVAL;		return 0;	}        case VIDIOCGPICT:        {		struct video_picture p;		se401_get_pict(se401, &p);		if (copy_to_user(arg, &p, sizeof(p)))			return -EFAULT;		return 0;	}	case VIDIOCSPICT:	{		struct video_picture p;		if (copy_from_user(&p, arg, sizeof(p)))			return -EFAULT;		if (se401_set_pict(se401, &p))			return -EINVAL;		return 0;	}	case VIDIOCSWIN:	{		struct video_window vw;		if (copy_from_user(&vw, arg, sizeof(vw)))			return -EFAULT;		if (vw.flags)			return -EINVAL;		if (vw.clipcount)			return -EINVAL;		if (se401_set_size(se401, vw.width, vw.height))			return -EINVAL;		return 0;        }	case VIDIOCGWIN:	{		struct video_window vw;		vw.x = 0;               /* FIXME */		vw.y = 0;		vw.chromakey = 0;		vw.flags = 0;		vw.clipcount = 0;		vw.width = se401->cwidth;		vw.height = se401->cheight;		if (copy_to_user(arg, &vw, sizeof(vw)))			return -EFAULT;		return 0;	}	case VIDIOCGMBUF:	{		struct video_mbuf vm;		int i;		memset(&vm, 0, sizeof(vm));		vm.size = SE401_NUMFRAMES * se401->maxframesize;		vm.frames = SE401_NUMFRAMES;		for (i=0; i<SE401_NUMFRAMES; i++)			vm.offsets[i] = se401->maxframesize * i;		if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))		return -EFAULT;		return 0;	}	case VIDIOCMCAPTURE:	{		struct video_mmap vm;		if (copy_from_user(&vm, arg, sizeof(vm)))		return -EFAULT;		if (vm.format != VIDEO_PALETTE_RGB24)			return -EINVAL;		if (vm.frame >= SE401_NUMFRAMES)			return -EINVAL;		if (se401->frame[vm.frame].grabstate != FRAME_UNUSED)			return -EBUSY;		/* Is this according to the v4l spec??? */		if (se401_set_size(se401, vm.width, vm.height))			return -EINVAL;		se401->frame[vm.frame].grabstate=FRAME_READY;		if (!se401->streaming)			se401_start_stream(se401);		/* Set the picture properties */		if (se401->framecount==0)			se401_send_pict(se401);		/* Calibrate the reset level after a few frames. */		if (se401->framecount%20==1)			se401_auto_resetlevel(se401);		return 0;	}	case VIDIOCSYNC:	{		int frame, ret=0;		if (copy_from_user((void *)&frame, arg, sizeof(int)))			return -EFAULT;		if(frame <0 || frame >= SE401_NUMFRAMES)			return -EINVAL;		ret=se401_newframe(se401, frame);		se401->frame[frame].grabstate=FRAME_UNUSED;		return ret;	}	case VIDIOCGFBUF:	{		struct video_buffer vb;		memset(&vb, 0, sizeof(vb));		vb.base = NULL; /* frame buffer not supported, not used */		if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))			return -EFAULT;		return 0;	}	case VIDIOCKEY:		return 0;	case VIDIOCCAPTURE:		return -EINVAL;	case VIDIOCSFBUF:		return -EINVAL;	case VIDIOCGTUNER:	case VIDIOCSTUNER:		return -EINVAL;	case VIDIOCGFREQ:	case VIDIOCSFREQ:		return -EINVAL;	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		return -EINVAL;        default:                return -ENOIOCTLCMD;        } /* end switch */        return 0;}static long se401_read(struct video_device *dev, char *buf, unsigned long count, int noblock){	int realcount=count, ret=0;	struct usb_se401 *se401 = (struct usb_se401 *)dev;	if (se401->dev == NULL)		return -EIO;	if (realcount > se401->cwidth*se401->cheight*3)		realcount=se401->cwidth*se401->cheight*3;	/* Shouldn't happen: */	if (se401->frame[0].grabstate==FRAME_GRABBING)		return -EBUSY;	se401->frame[0].grabstate=FRAME_READY;	se401->frame[1].grabstate=FRAME_UNUSED;	se401->curframe=0;	if (!se401->streaming)		se401_start_stream(se401);	/* Set the picture properties */	if (se401->framecount==0)		se401_send_pict(se401);	/* Calibrate the reset level after a few frames. */	if (se401->framecount%20==1)		se401_auto_resetlevel(se401);	ret=se401_newframe(se401, 0);	se401->frame[0].grabstate=FRAME_UNUSED;	if (ret)		return ret;		if (copy_to_user(buf, se401->frame[0].data, realcount))		return -EFAULT;	return realcount;}static int se401_mmap(struct video_device *dev, const char *adr,        unsigned long size){	struct usb_se401 *se401 = (struct usb_se401 *)dev;	unsigned long start = (unsigned long)adr;	unsigned long page, pos;	down(&se401->lock);	if (se401->dev == NULL) {		up(&se401->lock);		return -EIO;	}	if (size > (((SE401_NUMFRAMES * se401->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {		up(&se401->lock);		return -EINVAL;	}	pos = (unsigned long)se401->fbuf;	while (size > 0) {		page = kvirt_to_pa(pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {			up(&se401->lock);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	up(&se401->lock);        return 0;}static struct video_device se401_template = {        name:           "se401 USB camera",        type:           VID_TYPE_CAPTURE,        hardware:       VID_HARDWARE_SE401,        open:           se401_open,        close:          se401_close,        read:           se401_read,        write:          se401_write,        ioctl:          se401_ioctl,        mmap:           se401_mmap,        initialize:     se401_init_done,};/***************************/static int se401_init(struct usb_se401 *se401){        int i=0, rc;        unsigned char cp[0x40];	char temp[200];	/* led on */        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));	if (cp[1]!=0x41) {		err("Wrong descriptor type");		return 1;	}	sprintf (temp, "ExtraFeatures: %d", cp[3]);	se401->sizes=cp[4]+cp[5]*256;	se401->width=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);	se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);	for (i=0; i<se401->sizes; i++) {		    se401->width[i]=cp[6+i*4+0]+cp[6+i*4+1]*256;		    se401->height[i]=cp[6+i*4+2]+cp[6+i*4+3]*256;	}	sprintf (temp, "%s Sizes:", temp);	for (i=0; i<se401->sizes; i++) {		sprintf(temp, "%s %dx%d", temp, se401->width[i], se401->height[i]);	}	info("%s", temp);	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;	rc=se401_sndctrl(0, se401, SE401_REQ_GET_HEIGHT, 0, cp, sizeof(cp));	se401->cheight=cp[0]+cp[1]*256;	if (!cp[2] && SE401_FORMAT_BAYER) {		err("Bayer format not supported!");		return 1;	}	/* set output mode (BAYER) */        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;	/* some default values */	se401->resetlevel=0x2d;	se401->rgain=0x20;	se401->ggain=0x20;	se401->bgain=0x20;	se401_set_exposure(se401, 20000);	se401->palette=VIDEO_PALETTE_RGB24;	se401->enhance=1;	se401->dropped=0;	se401->error=0;	se401->framecount=0;	se401->readcount=0;	/* Start interrupt transfers for snapshot button */	se401->inturb=usb_alloc_urb(0);	if (!se401->inturb) {		info("Allocation of inturb failed");		return 1;	}	FILL_INT_URB(se401->inturb, se401->dev,	    usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),	    &se401->button, sizeof(se401->button),	    se401_button_irq,	    se401,	    HZ/10	);	if (usb_submit_urb(se401->inturb)) {		info("int urb burned down");		return 1;	}        /* Flash the led */        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 1, NULL, 0);        se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 1, NULL, 0);        se401_sndctrl(1, se401, SE401_REQ_CAMERA_POWER, 0, NULL, 0);	se401_sndctrl(1, se401, SE401_REQ_LED_CONTROL, 0, NULL, 0);        return 0;}#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)static void* se401_probe(struct usb_device *dev, unsigned int ifnum)#elsestatic void* __devinit se401_probe(struct usb_device *dev, unsigned int ifnum,	const struct usb_device_id *id)#endif{        struct usb_interface_descriptor *interface;        struct usb_se401 *se401;        char *camera_name=NULL;        /* We don't handle multi-config cameras */        if (dev->descriptor.bNumConfigurations != 1)                return NULL;        interface = &dev->actconfig->interface[ifnum].altsetting[0];        /* Is it an se401? */        if (dev->descriptor.idVendor == 0x03e8 &&            dev->descriptor.idProduct == 0x0004) {                camera_name="Endpoints/Aox SE401";        } else if (dev->descriptor.idVendor == 0x0471 &&            dev->descriptor.idProduct == 0x030b) {                camera_name="Philips PCVC665K";        } else if (dev->descriptor.idVendor == 0x047d &&	    dev->descriptor.idProduct == 0x5001) {		camera_name="Kensington VideoCAM 67014";        } else if (dev->descriptor.idVendor == 0x047d &&	    dev->descriptor.idProduct == 0x5002) {		camera_name="Kensington VideoCAM 6701(5/7)";        } else if (dev->descriptor.idVendor == 0x047d &&	    dev->descriptor.idProduct == 0x5003) {		camera_name="Kensington VideoCAM 67016";	} else		return NULL;        /* Checking vendor/product should be enough, but what the hell */        if (interface->bInterfaceClass != 0x00)                return NULL;        if (interface->bInterfaceSubClass != 0x00)                return NULL;        /* We found one */        info("SE401 camera found: %s", camera_name);        if ((se401 = kmalloc(sizeof(*se401), GFP_KERNEL)) == NULL) {                err("couldn't kmalloc se401 struct");                return NULL;        }        memset(se401, 0, sizeof(*se401));        se401->dev = dev;        se401->iface = interface->bInterfaceNumber;        se401->camera_name = camera_name;	info("firmware version: %02x", dev->descriptor.bcdDevice & 255);        if (se401_init(se401)) {		kfree(se401);		return NULL;	}	memcpy(&se401->vdev, &se401_template, sizeof(se401_template));	memcpy(se401->vdev.name, se401->camera_name, strlen(se401->camera_name));	init_waitqueue_head(&se401->wq);	init_MUTEX(&se401->lock);	wmb();	if (video_register_device(&se401->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {		kfree(se401);		err("video_register_device failed");		return NULL;	}	info("registered new video device: video%d", se401->vdev.minor);        return se401;}static void se401_disconnect(struct usb_device *dev, void *ptr){	struct usb_se401 *se401 = (struct usb_se401 *) ptr;	lock_kernel();	/* We don't want people trying to open up the device */	if (!se401->user){		video_unregister_device(&se401->vdev);		usb_se401_remove_disconnected(se401);	} else {		se401->removed = 1;	}	unlock_kernel();}static inline void usb_se401_remove_disconnected (struct usb_se401 *se401){	int i;        se401->dev = NULL;        se401->frame[0].grabstate = FRAME_ERROR;        se401->frame[1].grabstate = FRAME_ERROR;	se401->streaming = 0;	wake_up_interruptible(&se401->wq);	for (i=0; i<SE401_NUMSBUF; i++) if (se401->urb[i]) {		se401->urb[i]->next = NULL;		usb_unlink_urb(se401->urb[i]);		usb_free_urb(se401->urb[i]);		se401->urb[i] = NULL;		kfree(se401->sbuf[i].data);	}	for (i=0; i<SE401_NUMSCRATCH; i++) if (se401->scratch[i].data) {		kfree(se401->scratch[i].data);	}	if (se401->inturb) {		usb_unlink_urb(se401->inturb);		usb_free_urb(se401->inturb);	}        info("%s disconnected", se401->camera_name);#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	destroy_proc_se401_cam(se401);#endif        /* Free the memory */	kfree(se401->width);	kfree(se401->height);	kfree(se401);}static struct usb_driver se401_driver = {        name:		"se401",#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 3, 0)        id_table:	device_table,#endif	probe:		se401_probe,        disconnect:	se401_disconnect};/**************************************************************************** * *  Module routines * ***************************************************************************/static int __init usb_se401_init(void){#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	proc_se401_create();#endif	info("SE401 usb camera driver version %s registering", version);	if (flickerless)		if (flickerless!=50 && flickerless!=60) {			info("Invallid flickerless value, use 0, 50 or 60.");			return -1;	}	if (usb_register(&se401_driver) < 0)		return -1;	return 0;}static void __exit usb_se401_exit(void){	usb_deregister(&se401_driver);	info("SE401 driver deregistered");#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)	proc_se401_destroy();#endif}module_init(usb_se401_init);module_exit(usb_se401_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -