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

📄 se401.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		b->minheight = se401->height[0];		return 0;	}	case VIDIOCGCHAN:	{		struct video_channel *v = arg;		if (v->channel != 0)			return -EINVAL;		v->flags = 0;		v->tuners = 0;		v->type = VIDEO_TYPE_CAMERA;		strcpy(v->name, "Camera");		return 0;	}	case VIDIOCSCHAN:	{		struct video_channel *v = arg;		if (v->channel != 0)			return -EINVAL;		return 0;	}        case VIDIOCGPICT:        {		struct video_picture *p = arg;		se401_get_pict(se401, p);		return 0;	}	case VIDIOCSPICT:	{		struct video_picture *p = arg;		if (se401_set_pict(se401, p))			return -EINVAL;		return 0;	}	case VIDIOCSWIN:	{		struct video_window *vw = arg;		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 = arg;		vw->x = 0;               /* FIXME */		vw->y = 0;		vw->chromakey = 0;		vw->flags = 0;		vw->clipcount = 0;		vw->width = se401->cwidth;		vw->height = se401->cheight;		return 0;	}	case VIDIOCGMBUF:	{		struct video_mbuf *vm = arg;		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;		return 0;	}	case VIDIOCMCAPTURE:	{		struct video_mmap *vm = arg;		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 = arg;		int ret=0;		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 = arg;		memset(vb, 0, sizeof(*vb));		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 int se401_ioctl(struct inode *inode, struct file *file,		       unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, se401_do_ioctl);}static ssize_t se401_read(struct file *file, char __user *buf,		     size_t count, loff_t *ppos){	int realcount=count, ret=0;	struct video_device *dev = file->private_data;	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 file *file, struct vm_area_struct *vma){	struct video_device *dev = file->private_data;	struct usb_se401 *se401 = (struct usb_se401 *)dev;	unsigned long start = vma->vm_start;	unsigned long size  = vma->vm_end-vma->vm_start;	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 = vmalloc_to_pfn((void *)pos);		if (remap_pfn_range(vma, 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 file_operations se401_fops = {	.owner =	THIS_MODULE,        .open =         se401_open,        .release =      se401_close,        .read =         se401_read,        .mmap =         se401_mmap,	.ioctl =        se401_ioctl,	.llseek =       no_llseek,};static struct video_device se401_template = {	.owner =	THIS_MODULE,        .name =         "se401 USB camera",        .type =         VID_TYPE_CAPTURE,        .hardware =     VID_HARDWARE_SE401,	.fops =         &se401_fops,};/***************************/static int se401_init(struct usb_se401 *se401, int button){        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);	if (!se401->width)		return 1;	se401->height=kmalloc(se401->sizes*sizeof(int), GFP_KERNEL);	if (!se401->height) {		kfree(se401->width);		return 1;	}	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 */	if (button) {		se401->inturb=usb_alloc_urb(0, GFP_KERNEL);		if (!se401->inturb) {			info("Allocation of inturb failed");			return 1;		}		usb_fill_int_urb(se401->inturb, se401->dev,		    usb_rcvintpipe(se401->dev, SE401_BUTTON_ENDPOINT),		    &se401->button, sizeof(se401->button),		    se401_button_irq,		    se401,		    8		);		if (usb_submit_urb(se401->inturb, GFP_KERNEL)) {			info("int urb burned down");			return 1;		}	} else		se401->inturb=NULL;        /* 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;}static int se401_probe(struct usb_interface *intf,	const struct usb_device_id *id){	struct usb_device *dev = interface_to_usbdev(intf);        struct usb_interface_descriptor *interface;        struct usb_se401 *se401;        char *camera_name=NULL;	int button=1;        /* We don't handle multi-config cameras */        if (dev->descriptor.bNumConfigurations != 1)                return -ENODEV;        interface = &intf->cur_altsetting->desc;        /* Is it an se401? */        if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&            le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {                camera_name="Endpoints/Aox SE401";        } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&            le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {                camera_name="Philips PCVC665K";        } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&	    le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {		camera_name="Kensington VideoCAM 67014";        } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&	    le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {		camera_name="Kensington VideoCAM 6701(5/7)";        } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&	    le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {		camera_name="Kensington VideoCAM 67016";		button=0;	} else		return -ENODEV;        /* Checking vendor/product should be enough, but what the hell */        if (interface->bInterfaceClass != 0x00)		return -ENODEV;        if (interface->bInterfaceSubClass != 0x00)		return -ENODEV;        /* 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 -ENOMEM;        }        memset(se401, 0, sizeof(*se401));        se401->dev = dev;        se401->iface = interface->bInterfaceNumber;        se401->camera_name = camera_name;	info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);        if (se401_init(se401, button)) {		kfree(se401);		return -EIO;	}	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 -EIO;	}	info("registered new video device: video%d", se401->vdev.minor);	usb_set_intfdata (intf, se401);        return 0;}static void se401_disconnect(struct usb_interface *intf){	struct usb_se401 *se401 = usb_get_intfdata (intf);	usb_set_intfdata (intf, NULL);	if (se401) {		video_unregister_device(&se401->vdev);		if (!se401->user){			usb_se401_remove_disconnected(se401);		} else {			se401->frame[0].grabstate = FRAME_ERROR;			se401->frame[0].grabstate = FRAME_ERROR;			se401->streaming = 0;			wake_up_interruptible(&se401->wq);			se401->removed = 1;		}	}}static struct usb_driver se401_driver = {	.owner		= THIS_MODULE,        .name		= "se401",        .id_table	= device_table,	.probe		= se401_probe,        .disconnect	= se401_disconnect,};/**************************************************************************** * *  Module routines * ***************************************************************************/static int __init usb_se401_init(void){	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;	}	return usb_register(&se401_driver);}static void __exit usb_se401_exit(void){	usb_deregister(&se401_driver);	info("SE401 driver deregistered");}module_init(usb_se401_init);module_exit(usb_se401_exit);

⌨️ 快捷键说明

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