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

📄 vicam.c

📁 ep9315平台下USB驱动的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	n = usb_bulk_msg(cam->udev,			 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),			 cam->raw_image,			 512 * 242 + 128, &actual_length, 500);	if (n < 0) {		printk(KERN_ERR "Problem during bulk read of frame data: %d\n",		       n);	}	vicam_decode_color(cam->raw_image,			 cam->framebuf +			 framenum * VICAM_MAX_FRAME_SIZE );	cam->framebuf_size =	    320 * 240 * VICAM_BYTES_PER_PIXEL;	cam->framebuf_read_start = 0;	return;}static longvicam_read(struct video_device *dev, char *buf,		 unsigned long count, int noblock){	struct vicam_camera *cam = dev->priv;	DBG("read %d bytes.\n", (int) count);	if (!buf)		return -EINVAL;	if (!count)		return -EINVAL;	// This is some code that will hopefully allow us to do shell copies from	// the /dev/videoX to a file and have it actually work.	if (cam->framebuf_size != 0) {		if (cam->framebuf_read_start == cam->framebuf_size) {			cam->framebuf_size = cam->framebuf_read_start = 0;			return 0;		} else {			if (cam->framebuf_read_start + count <=			    cam->framebuf_size) {				// count does not exceed available bytes				copy_to_user(buf,					     (cam->framebuf) +					     cam->framebuf_read_start, count);				cam->framebuf_read_start += count;				return count;			} else {				count =				    cam->framebuf_size -				    cam->framebuf_read_start;				copy_to_user(buf,					     (cam->framebuf) +					     cam->framebuf_read_start, count);				cam->framebuf_read_start = cam->framebuf_size;				return count;			}		}	}	down_interruptible(&cam->busy_lock);	if (cam->needsDummyRead) {		read_frame(cam, 0);		cam->needsDummyRead = 0;	}	// read_frame twice because the camera doesn't seem to take the shutter speed for the first one.	read_frame(cam, 0);	if (count > cam->framebuf_size)		count = cam->framebuf_size;	copy_to_user(buf, cam->framebuf, count);	if (count != cam->framebuf_size)		cam->framebuf_read_start = count;	else		cam->framebuf_size = 0;	up(&cam->busy_lock);	return count;}static intvicam_mmap(struct video_device *dev, const char *adr, unsigned long size){	// TODO: allocate the raw frame buffer if necessary	unsigned long start = (unsigned long) adr;	unsigned long page, pos;	struct vicam_camera *cam = dev->priv;	if (!cam)		return -ENODEV;	DBG("vicam_mmap: %ld\n", size);	/* We let mmap allocate as much as it wants because Linux was adding 2048 bytes	 * to the size the application requested for mmap and it was screwing apps up.	 if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)	 return -EINVAL;	 */	/* make this _really_ smp-safe */	if (down_interruptible(&cam->busy_lock))		return -EINTR;	if (!cam->framebuf) {	/* we do lazy allocation */		cam->framebuf =		    usbvideo_rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);		if (!cam->framebuf) {			up(&cam->busy_lock);			return -ENOMEM;		}	}	pos = (unsigned long) (cam->framebuf);	while (size > 0) {		page = usbvideo_kvirt_to_pa(pos);		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) {			up(&cam->busy_lock);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	up(&cam->busy_lock);	return 0;}#ifdef CONFIG_PROC_FSstatic struct proc_dir_entry *vicam_proc_root = NULL;static intvicam_read_proc(char *page, char **start, off_t off,		      int count, int *eof, void *data){	char *out = page;	int len;	struct vicam_camera *cam = (struct vicam_camera *) data;	out +=	    sprintf(out, "Vicam-based WebCam Linux Driver.\n");	out += sprintf(out, "(c) 2002 Joe Burks (jburks@wavicle.org)\n");	out += sprintf(out, "vicam stats:\n");	out += sprintf(out, "    Shutter Speed: 1/%d\n", cam->shutter_speed);	out += sprintf(out, "             Gain: %d\n", cam->gain);	len = out - page;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0)			return 0;	} else		len = count;	*start = page + off;	return len;}static intvicam_write_proc(struct file *file, const char *buffer,		       unsigned long count, void *data){	char *in;	char *start;	struct vicam_camera *cam = (struct vicam_camera *) data;	in = kmalloc(count + 1, GFP_KERNEL);	if (!in)		return -ENOMEM;	in[count] = 0;		// I'm not sure buffer is gauranteed to be null terminated	// so I do this to make sure I have a null in there.	strncpy(in, buffer, count);	start = strstr(in, "gain=");	if (start	    && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))		cam->gain = simple_strtoul(start + 5, NULL, 10);	start = strstr(in, "shutter=");	if (start	    && (start == in || *(start - 1) == ' ' || *(start - 1) == ','))		cam->shutter_speed = simple_strtoul(start + 8, NULL, 10);	kfree(in);	return count;}voidvicam_create_proc_root(void){	vicam_proc_root = create_proc_entry("video/vicam", S_IFDIR, 0);	if (vicam_proc_root)		vicam_proc_root->owner = THIS_MODULE;	else		printk(KERN_ERR		       "could not create /proc entry for vicam!");}voidvicam_destroy_proc_root(void){	if (vicam_proc_root)		remove_proc_entry("video/vicam", 0);}voidvicam_create_proc_entry(void *ptr){	struct vicam_camera *cam = (struct vicam_camera *) ptr;	char name[7];	struct proc_dir_entry *ent;	DBG(KERN_INFO "vicam: creating proc entry\n");	if (!vicam_proc_root || !cam) {		printk(KERN_INFO		       "vicam: could not create proc entry, %s pointer is null.\n",		       (!cam ? "camera" : "root"));		return;	}	sprintf(name, "video%d", cam->vdev.minor);	ent =	    create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR,			      vicam_proc_root);	if (!ent)		return;	ent->data = cam;	ent->read_proc = vicam_read_proc;	ent->write_proc = vicam_write_proc;	ent->size = 512;	cam->proc_entry = ent;}voidvicam_destroy_proc_entry(void *ptr){	struct vicam_camera *cam = (struct vicam_camera *) ptr;	char name[7];	if (!cam || !cam->proc_entry)		return;	sprintf(name, "video%d", cam->vdev.minor);	remove_proc_entry(name, vicam_proc_root);	cam->proc_entry = NULL;}#endifintvicam_video_init(struct video_device *vdev){	// This would normally create the proc entry for this camera#ifdef CONFIG_PROC_FS	vicam_create_proc_entry(vdev->priv);#endif	return 0;}static longvicam_write(struct video_device *v, const char *buf, unsigned long count,		  int nonblock){	return -EINVAL;}static struct video_device vicam_template = {	owner:THIS_MODULE,	name:"ViCam-based USB Camera",	type:VID_TYPE_CAPTURE,	hardware:VID_HARDWARE_VICAM,	open:vicam_open,	close:vicam_close,	read:vicam_read,	write:vicam_write,	ioctl:vicam_ioctl,	mmap:vicam_mmap,	initialize:vicam_video_init,	minor:-1,};/* table of devices that work with this driver */static struct usb_device_id vicam_table[] = {	{USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},	{}			/* Terminating entry */};MODULE_DEVICE_TABLE(usb, vicam_table);static struct usb_driver vicam_driver = {	name:"vicam",	probe:vicam_probe,	disconnect:vicam_disconnect,	id_table:vicam_table};/** *	vicam_probe * *	Called by the usb core when a new device is connected that it thinks *	this driver might be interested in. */static void *vicam_probe(struct usb_device *dev, unsigned int ifnum,		  const struct usb_device_id *id){	int nas, bulkEndpoint = 0;	const struct usb_interface_descriptor *interface;	const struct usb_endpoint_descriptor *endpoint;	struct vicam_camera *cam;	/* See if the device offered us matches what we can accept */	if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||	    (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {		return NULL;	}	printk(KERN_INFO "ViCam based webcam connected\n");	nas = dev->actconfig->interface[ifnum].num_altsetting;	if (nas != 1) {		printk(KERN_WARNING		       "Expected only one alternate setting for this camera!\n");		return NULL;	}	interface = &dev->actconfig->interface[ifnum].altsetting[0];	DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",	       ifnum, (unsigned) (interface->bNumEndpoints));	endpoint = &interface->endpoint[0];	if ((endpoint->bEndpointAddress & 0x80) &&	    ((endpoint->bmAttributes & 3) == 0x02)) {		/* we found a bulk in endpoint */		bulkEndpoint = endpoint->bEndpointAddress;	} else {		printk(KERN_ERR		       "No bulk in endpoint was found ?! (this is bad)\n");	}	if ((cam =	     kmalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {		printk(KERN_WARNING		       "could not allocate kernel memory for vicam_camera struct\n");		return NULL;	}	memset(cam, 0, sizeof (struct vicam_camera));	cam->shutter_speed = 15;	init_MUTEX(&cam->busy_lock);	memcpy(&cam->vdev, &vicam_template,	       sizeof (vicam_template));	cam->vdev.priv = cam;	// sort of a reverse mapping for those functions that get vdev only	cam->udev = dev;	cam->bulkEndpoint = bulkEndpoint;	if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) == -1) {		kfree(cam);		printk(KERN_WARNING "video_register_device failed\n");		return NULL;	}	printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);	return cam;}static voidvicam_disconnect(struct usb_device *dev, void *ptr){	struct vicam_camera *cam = ptr;	video_unregister_device(&cam->vdev);#ifdef CONFIG_PROC_FS	vicam_destroy_proc_entry(cam);#endif	if (cam->raw_image)		kfree(cam->raw_image);	if (cam->framebuf)		usbvideo_rvfree(cam->framebuf,		       VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);	kfree(cam);	printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");}/* */static int __initusb_vicam_init(void){	DBG(KERN_INFO "ViCam-based WebCam driver startup\n");#ifdef CONFIG_PROC_FS	vicam_create_proc_root();#endif	if (usb_register(&vicam_driver) != 0)		printk(KERN_WARNING "usb_register failed!\n");	return 0;}static void __exitusb_vicam_exit(void){	DBG(KERN_INFO	       "ViCam-based WebCam driver shutdown\n");	usb_deregister(&vicam_driver);#ifdef CONFIG_PROC_FS	vicam_destroy_proc_root();#endif}module_init(usb_vicam_init);module_exit(usb_vicam_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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