vicam.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 927 行 · 第 1/2 页

C
927
字号
	/* Why does se401.c have a usbdevice check here? */	/* If device is unplugged while open, I guess we only may unregister now */	return 0;}static int vicam_v4l_read(struct file *file, char *user_buf,			  size_t buflen, loff_t *ppos){	struct video_device *vdev = file->private_data;	//struct usb_vicam *vicam = (struct usb_vicam *)vdev;	dbg("vicam_v4l_read(%d)", buflen);	if (!vdev || !buf)		return -EFAULT;	if (copy_to_user(user_buf, buf2, buflen))		return -EFAULT;	return buflen;}static int vicam_v4l_do_ioctl(struct inode *inode, struct file *file,			      unsigned int cmd, void *arg){	struct video_device *vdev = file->private_data;	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 = arg;		ret = vicam_get_capability(vicam,b);		dbg("name %s",b->name);		break;	}	case VIDIOCGFBUF:	{		struct video_buffer *vb = arg;		info("vicam_v4l_ioctl - VIDIOCGBUF - query frame buffer param");		/* frame buffer not supported, not used */		memset(vb, 0, sizeof(*vb));		ret = 0;		break;	}	case VIDIOCGWIN:	{		struct video_window *vw = arg;		ret = vicam_get_window(vicam, vw);		break;	}	case VIDIOCSWIN:	{		struct video_window *vw = arg;		ret = vicam_set_window(vicam, vw);		break;	}	case VIDIOCGCHAN:	{		struct video_channel *v = arg;		ret = vicam_get_channel(vicam,v);		break;	}	case VIDIOCSCHAN:	{		struct video_channel *v = arg;		ret = vicam_set_channel(vicam,v);		break; 	}	case VIDIOCGPICT:	{		struct video_picture *p = arg;		ret = vicam_get_picture(vicam,p);		break;	}	case VIDIOCSPICT:	{		struct video_picture *p = arg;		ret = vicam_set_picture(vicam,p);		break;	}	case VIDIOCGMBUF:	{		struct video_mbuf *vm = arg;		ret = vicam_get_mmapbuffer(vicam,vm);		break;	}	case VIDIOCMCAPTURE:	{		struct video_mmap *vm = arg;		ret = vicam_mmap_capture(vicam,vm);		break;	}	case VIDIOCSYNC:	{		int *frame = arg;		ret = vicam_sync_frame(vicam,*frame);		break;	}	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_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, vicam_v4l_do_ioctl);}static int vicam_v4l_mmap(struct file *file, struct vm_area_struct *vma){	struct video_device *vdev = file->private_data;	struct usb_vicam *vicam = (struct usb_vicam *)vdev;	unsigned long start = vma->vm_start;	unsigned long size  = vma->vm_end-vma->vm_start;	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(vma, 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_template - important */static struct file_operations vicam_fops = {	owner:		THIS_MODULE,	open:		vicam_v4l_open,	release:       	vicam_v4l_close,	read:		vicam_v4l_read,	mmap:		vicam_v4l_mmap,	ioctl:		vicam_v4l_ioctl,	llseek:         no_llseek,};static struct video_device vicam_template = {	owner:		THIS_MODULE,	name:		"vicam USB camera",	type:		VID_TYPE_CAPTURE,	hardware:	VID_HARDWARE_SE401, /* need to ask for own id */	fops:           &vicam_fops,};/****************************************************************************** * *  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, GFP_ATOMIC))			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(KERN_DEBUG "Submiting urb: %d\n", usb_submit_urb(vicam->readurb, GFP_KERNEL));	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->readurb = usb_alloc_urb(0, GFP_KERNEL);	if (!vicam->readurb) {		kfree(vicam);		return NULL;	}	vicam->udev = udev;	vicam->camera_name = camera_name;	vicam->win.brightness = 128;	vicam->win.contrast = 10;	/* FIXME */	if (vicam_init(vicam)) {		usb_free_urb(vicam->readurb);		kfree(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");		usb_free_urb(vicam->readurb);		kfree(vicam);		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;	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 */		usb_free_urb(vicam->readurb);		kfree(vicam);		vicam = NULL;	}}/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver vicam_driver = {	owner:		THIS_MODULE,	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 + =
减小字号Ctrl + -
显示快捷键?