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

📄 vicam.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}static void vicam_v4l_close(struct video_device *vdev){	struct usb_vicam *vicam = (struct usb_vicam *)vdev;	dbg("vicam_v4l_close");		down(&vicam->sem);#ifdef BLINKING	info ("led off");	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);//	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0); Leave it on#endif	rvfree(vicam->fbuf, vicam->maxframesize * VICAM_NUMFRAMES);	vicam->fbuf = 0;	vicam->open_count=0;	up(&vicam->sem);	/* Why does se401.c have a usbdevice check here? */	/* If device is unplugged while open, I guess we only may unregister now */	MOD_DEC_USE_COUNT;}static long vicam_v4l_read(struct video_device *vdev, char *user_buf, unsigned long buflen, int noblock){	//struct usb_vicam *vicam = (struct usb_vicam *)vdev;	dbg("vicam_v4l_read(%ld)", buflen);	if (!vdev || !buf)		return -EFAULT;	if (copy_to_user(user_buf, buf2, buflen))		return -EFAULT;	return buflen;}static long vicam_v4l_write(struct video_device *dev, const char *buf, unsigned long count, int noblock){	info("vicam_v4l_write");	return -EINVAL;}static int vicam_v4l_ioctl(struct video_device *vdev, unsigned int cmd, void *arg){	struct usb_vicam *vicam = (struct usb_vicam *)vdev;	int ret = -EL3RST;	if (!vicam->udev)		return -EIO;	down(&vicam->sem);	switch (cmd) {	case VIDIOCGCAP:	{		struct video_capability b;		ret = vicam_get_capability(vicam,&b);		dbg("name %s",b.name);		if (copy_to_user(arg, &b, sizeof(b)))			ret = -EFAULT;	}	case VIDIOCGFBUF:	{		struct video_buffer vb;		info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");		/* frame buffer not supported, not used */		memset(&vb, 0, sizeof(vb));		vb.base = NULL;				/* FIXME - VIDIOCGFBUF - why the void */		if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))			ret = -EFAULT;		ret = 0;	}	case VIDIOCGWIN:	{		struct video_window vw;		ret = vicam_get_window(vicam, &vw);		if (copy_to_user(arg, &vw, sizeof(vw)))			ret = -EFAULT;	}	case VIDIOCSWIN:	{		struct video_window vw;		if (copy_from_user(&vw, arg, sizeof(vw)))			ret = -EFAULT;		else			ret = vicam_set_window(vicam, &vw);		return ret;	}	case VIDIOCGCHAN:	{		struct video_channel v;		if (copy_from_user(&v, arg, sizeof(v)))			ret = -EFAULT;		else {			ret = vicam_get_channel(vicam,&v);			if (copy_to_user(arg, &v, sizeof(v)))				ret = -EFAULT;		}	}	case VIDIOCSCHAN:	{		struct video_channel v;		if (copy_from_user(&v, arg, sizeof(v)))			ret = -EFAULT;		else			ret = vicam_set_channel(vicam,&v); 	}	case VIDIOCGPICT:	{		struct video_picture p;		ret = vicam_get_picture(vicam, &p);		if (copy_to_user(arg, &p, sizeof(p)))			ret = -EFAULT;	}	case VIDIOCSPICT:	{		struct video_picture p;		if (copy_from_user(&p, arg, sizeof(p)))			ret = -EFAULT;		else			ret = vicam_set_picture(vicam, &p);	}	case VIDIOCGMBUF:	{		struct video_mbuf vm;		ret = vicam_get_mmapbuffer(vicam,&vm);		/* FIXME - VIDIOCGMBUF - why the void */		if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))			ret = -EFAULT;	}	case VIDIOCMCAPTURE:	{		struct video_mmap vm;		ret = vicam_mmap_capture(vicam, &vm);		/* FIXME: This is probably not right */	}	case VIDIOCSYNC:	{		int frame;		/* FIXME - VIDIOCSYNC - why the void */		if (copy_from_user((void *)&frame, arg, sizeof(int)))			ret = -EFAULT;		else			ret = vicam_sync_frame(vicam,frame);	}	case VIDIOCKEY:		ret = 0; 	case VIDIOCCAPTURE:	case VIDIOCSFBUF:	case VIDIOCGTUNER:	case VIDIOCSTUNER:	case VIDIOCGFREQ:	case VIDIOCSFREQ:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:	case VIDIOCGUNIT:		ret = -EINVAL;	default:	{		info("vicam_v4l_ioctl - %ui",cmd);		ret = -ENOIOCTLCMD;	}	} /* end switch */	up(&vicam->sem);        return ret;}static int vicam_v4l_mmap(struct video_device *dev, const char *adr, unsigned long size){	struct usb_vicam *vicam = (struct usb_vicam *)dev;	unsigned long start = (unsigned long)adr;	unsigned long page, pos;	down(&vicam->sem);		if (vicam->udev == NULL) {		up(&vicam->sem);		return -EIO;	}#if 0	if (size > (((VICAM_NUMFRAMES * vicam->maxframesize) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) {		up(&vicam->sem);		return -EINVAL;	}#endif	pos = (unsigned long)vicam->fbuf;	while (size > 0) {		page = kvirt_to_pa(pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {			up(&vicam->sem);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	up(&vicam->sem);        return 0;}/* FIXME - vicam_v4l_init */static int vicam_v4l_init(struct video_device *dev){	/* stick proc fs stuff in here if wanted */	dbg("vicam_v4l_init");	return 0;}/* FIXME - vicam_template - important */static struct video_device vicam_template = {	name:		"vicam USB camera",	type:		VID_TYPE_CAPTURE,	hardware:	VID_HARDWARE_SE401, /* need to ask for own id */	open:		vicam_v4l_open,	close:		vicam_v4l_close,	read:		vicam_v4l_read,	write:		vicam_v4l_write,	ioctl:		vicam_v4l_ioctl,	mmap:		vicam_v4l_mmap,	initialize:	vicam_v4l_init,};/****************************************************************************** * *  Some Routines * ******************************************************************************//*Flash the ledvicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);info ("led on");vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);info ("led off");vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x00, NULL, 0);vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x00, NULL, 0);*/static void vicam_bulk(struct urb *urb){	struct usb_vicam *vicam = urb->context;	/*	if (!vicam || !vicam->dev || !vicam->used)		return;	*/	if (urb->status)		printk("vicam%d: nonzero read/write bulk status received: %d",			0, urb->status);	urb->actual_length = 0;	urb->dev = vicam->udev;	memcpy(buf2, buf+64, 0x1e480);	if (vicam->fbuf)		memcpy(vicam->fbuf, buf+64, 0x1e480);	if (!change_pending) {		if (usb_submit_urb(urb))			dbg("failed resubmitting read urb");	} else {		change_pending = 0;		wake_up_interruptible(&vicam->wait);	}}static int vicam_parameters(struct usb_vicam *vicam){	unsigned char req[0x10];	unsigned int shutter;	shutter = 10;	switch (vicam->win.width) {	case 512:	default:		memcpy(req, s512x242bw, 0x10);		break;	case 256:		memcpy(req, s256x242bw, 0x10);		break;	case 128:		memcpy(req, s128x122bw, 0x10);		break;	}	mdelay(10);	vicam_sndctrl(1, vicam, VICAM_REQ_CAMERA_POWER, 0x01, NULL, 0);	info ("led on");	vicam_sndctrl(1, vicam, VICAM_REQ_LED_CONTROL, 0x01, NULL, 0);	mdelay(10);	shutter = vicam->win.contrast / 256;	if (shutter == 0)		shutter = 1;	printk("vicam_parameters: brightness %d, shutter %d\n", vicam->win.brightness, shutter );	req[0] = vicam->win.brightness /256;	shutter = 15600/shutter - 1;	req[6] = shutter & 0xff;	req[7] = (shutter >> 8) & 0xff;	vicam_sndctrl(1, vicam, VICAM_REQ_CAPTURE, 0x80, req, 0x10);	mdelay(10);	vicam_sndctrl(0, vicam, VICAM_REQ_GET_SOMETHIN, 0, buf, 0x10);	mdelay(10);	return 0;}static int vicam_init(struct usb_vicam *vicam){	int width[] = {128, 256, 512};	int height[] = {122, 242, 242};	dbg("vicam_init");	buf = kmalloc(0x1e480, GFP_KERNEL);	buf2 = kmalloc(0x1e480, GFP_KERNEL);	if ((!buf) || (!buf2)) {		printk("Not enough memory for vicam!\n");		goto error;	}	/* do we do aspect correction in kernel or not? */	vicam->sizes = 3;	vicam->width = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);	vicam->height = kmalloc(vicam->sizes*sizeof(int), GFP_KERNEL);	memcpy(vicam->width, &width, sizeof(width));	memcpy(vicam->height, &height, sizeof(height));	vicam->maxframesize = vicam->width[vicam->sizes-1] * vicam->height[vicam->sizes-1];	/* Download firmware to camera */	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware1, sizeof(firmware1));	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex1, sizeof(findex1));	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, firmware2, sizeof(firmware2));	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, findex2, sizeof(findex2));	vicam_sndctrl(1, vicam, VICAM_REQ_VENDOR, 0, fsetup, sizeof(fsetup));	vicam_parameters(vicam);	FILL_BULK_URB(&vicam->readurb, vicam->udev, usb_rcvbulkpipe(vicam->udev, 0x81),		      buf, 0x1e480, vicam_bulk, vicam);	printk("Submiting urb: %d\n", usb_submit_urb(&vicam->readurb));	return 0;error:	if (buf)		kfree(buf);	if (buf2)		kfree(buf2);	return 1;}static void * __devinit vicam_probe(struct usb_device *udev, unsigned int ifnum,	const struct usb_device_id *id){	struct usb_vicam *vicam;	char *camera_name=NULL;	dbg("vicam_probe");	/* See if the device offered us matches what we can accept */	if ((udev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||	    (udev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {		return NULL;	}		camera_name="3Com HomeConnect USB";	info("ViCAM camera found: %s", camera_name);		vicam = kmalloc (sizeof(struct usb_vicam), GFP_KERNEL);	if (vicam == NULL) {		err ("couldn't kmalloc vicam struct");		return NULL;	}	memset(vicam, 0, sizeof(*vicam));		vicam->udev = udev;	vicam->camera_name = camera_name;	vicam->win.brightness = 128;	vicam->win.contrast = 10;	/* FIXME */	if (vicam_init(vicam))		return NULL;	memcpy(&vicam->vdev, &vicam_template, sizeof(vicam_template));	memcpy(vicam->vdev.name, vicam->camera_name, strlen(vicam->camera_name));		if (video_register_device(&vicam->vdev, VFL_TYPE_GRABBER, video_nr) == -1) {		err("video_register_device");		return NULL;	}	info("registered new video device: video%d", vicam->vdev.minor);		init_MUTEX (&vicam->sem);	init_waitqueue_head(&vicam->wait);		return vicam;}/* FIXME - vicam_disconnect - important */static void vicam_disconnect(struct usb_device *udev, void *ptr){	struct usb_vicam *vicam;	vicam = (struct usb_vicam *) ptr;	if (!vicam->open_count)		video_unregister_device(&vicam->vdev);	vicam->udev = NULL;/*	vicam->frame[0].grabstate = FRAME_ERROR;	vicam->frame[1].grabstate = FRAME_ERROR;*/	/* Free buffers and shit */	info("%s disconnected", vicam->camera_name);	synchronize(vicam);	if (!vicam->open_count) {		/* Other random junk */		kfree(vicam);		vicam = NULL;	}}/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver vicam_driver = {	name:		"vicam",	probe:		vicam_probe,	disconnect:	vicam_disconnect,	id_table:	vicam_table,};/****************************************************************************** * *  Module Routines * ******************************************************************************/MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");/* Module paramaters */MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");static int __init usb_vicam_init(void){	int result;	printk("VICAM: initializing\n");	/* register this driver with the USB subsystem */	result = usb_register(&vicam_driver);	if (result < 0) {		err("usb_register failed for the "__FILE__" driver. Error number %d",		    result);		return -1;	}	info(DRIVER_VERSION " " DRIVER_AUTHOR);	info(DRIVER_DESC);	return 0;}static void __exit usb_vicam_exit(void){	/* deregister this driver with the USB subsystem */	usb_deregister(&vicam_driver);}module_init(usb_vicam_init);module_exit(usb_vicam_exit);

⌨️ 快捷键说明

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