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

📄 vicam.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* it's not the end of the world if	 * we fail to turn the camera off.	 */	set_camera_power(cam, 0);	kfree(cam->raw_image);	rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);	kfree(cam->cntrlbuf);	mutex_lock(&cam->cam_lock);	cam->open_count--;	open_count = cam->open_count;	udev = cam->udev;	mutex_unlock(&cam->cam_lock);	if (!open_count && !udev) {		kfree(cam);	}	return 0;}static void vicam_decode_color(const u8 *data, u8 *rgb){	/* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB	 * Copyright (C) 2002 Monroe Williams (monroe@pobox.com)	 */	int i, prevY, nextY;	prevY = 512;	nextY = 512;	data += VICAM_HEADER_SIZE;	for( i = 0; i < 240; i++, data += 512 ) {		const int y = ( i * 242 ) / 240;		int j, prevX, nextX;		int Y, Cr, Cb;		if ( y == 242 - 1 ) {			nextY = -512;		}		prevX = 1;		nextX = 1;		for ( j = 0; j < 320; j++, rgb += 3 ) {			const int x = ( j * 512 ) / 320;			const u8 * const src = &data[x];			if ( x == 512 - 1 ) {				nextX = -1;			}			Cr = ( src[prevX] - src[0] ) +				( src[nextX] - src[0] );			Cr /= 2;			Cb = ( src[prevY] - src[prevX + prevY] ) +				( src[prevY] - src[nextX + prevY] ) +				( src[nextY] - src[prevX + nextY] ) +				( src[nextY] - src[nextX + nextY] );			Cb /= 4;			Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );			if ( i & 1 ) {				int Ct = Cr;				Cr = Cb;				Cb = Ct;			}			if ( ( x ^ i ) & 1 ) {				Cr = -Cr;				Cb = -Cb;			}			rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +					500 ) / 900, 0, 255 );			rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -					  ( 813 * Cr ) ) +					  500 ) / 1000, 0, 255 );			rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +					500 ) / 1300, 0, 255 );			prevX = -1;		}		prevY = -512;	}}static voidread_frame(struct vicam_camera *cam, int framenum){	unsigned char *request = cam->cntrlbuf;	int realShutter;	int n;	int actual_length;	if (cam->needsDummyRead) {		cam->needsDummyRead = 0;		read_frame(cam, framenum);	}	memset(request, 0, 16);	request[0] = cam->gain;	// 0 = 0% gain, FF = 100% gain	request[1] = 0;	// 512x242 capture	request[2] = 0x90;	// the function of these two bytes	request[3] = 0x07;	// is not yet understood	if (cam->shutter_speed > 60) {		// Short exposure		realShutter =		    ((-15631900 / cam->shutter_speed) + 260533) / 1000;		request[4] = realShutter & 0xFF;		request[5] = (realShutter >> 8) & 0xFF;		request[6] = 0x03;		request[7] = 0x01;	} else {		// Long exposure		realShutter = 15600 / cam->shutter_speed - 1;		request[4] = 0;		request[5] = 0;		request[6] = realShutter & 0xFF;		request[7] = realShutter >> 8;	}	// Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0	request[8] = 0;	// bytes 9-15 do not seem to affect exposure or image quality	mutex_lock(&cam->cam_lock);	if (!cam->udev) {		goto done;	}	n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);	if (n < 0) {		printk(KERN_ERR		       " Problem sending frame capture control message");		goto done;	}	n = usb_bulk_msg(cam->udev,			 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),			 cam->raw_image,			 512 * 242 + 128, &actual_length, 10000);	if (n < 0) {		printk(KERN_ERR "Problem during bulk read of frame data: %d\n",		       n);	} done:	mutex_unlock(&cam->cam_lock);}static ssize_tvicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos ){	struct vicam_camera *cam = file->private_data;	DBG("read %d bytes.\n", (int) count);	if (*ppos >= VICAM_MAX_FRAME_SIZE) {		*ppos = 0;		return 0;	}	if (*ppos == 0) {		read_frame(cam, 0);		vicam_decode_color(cam->raw_image,				   cam->framebuf +				   0 * VICAM_MAX_FRAME_SIZE);	}	count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);	if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {		count = -EFAULT;	} else {		*ppos += count;	}	if (count == VICAM_MAX_FRAME_SIZE) {		*ppos = 0;	}	return count;}static intvicam_mmap(struct file *file, struct vm_area_struct *vma){	// TODO: allocate the raw frame buffer if necessary	unsigned long page, pos;	unsigned long start = vma->vm_start;	unsigned long size  = vma->vm_end-vma->vm_start;	struct vicam_camera *cam = file->private_data;	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;	 */	pos = (unsigned long)cam->framebuf;	while (size > 0) {		page = vmalloc_to_pfn((void *)pos);		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))			return -EAGAIN;		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	return 0;}static const struct file_operations vicam_fops = {	.owner		= THIS_MODULE,	.open		= vicam_open,	.release	= vicam_close,	.read		= vicam_read,	.mmap		= vicam_mmap,	.ioctl		= vicam_ioctl,	.compat_ioctl	= v4l_compat_ioctl32,	.llseek		= no_llseek,};static struct video_device vicam_template = {	.owner 		= THIS_MODULE,	.name 		= "ViCam-based USB Camera",	.type 		= VID_TYPE_CAPTURE,	.fops 		= &vicam_fops,	.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)},	{USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_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 *	@intf: the interface *	@id: the device id * *	Called by the usb core when a new device is connected that it thinks *	this driver might be interested in. */static intvicam_probe( struct usb_interface *intf, const struct usb_device_id *id){	struct usb_device *dev = interface_to_usbdev(intf);	int bulkEndpoint = 0;	const struct usb_host_interface *interface;	const struct usb_endpoint_descriptor *endpoint;	struct vicam_camera *cam;	printk(KERN_INFO "ViCam based webcam connected\n");	interface = intf->cur_altsetting;	DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",	       interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));	endpoint = &interface->endpoint[0].desc;	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 =	     kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {		printk(KERN_WARNING		       "could not allocate kernel memory for vicam_camera struct\n");		return -ENOMEM;	}	cam->shutter_speed = 15;	mutex_init(&cam->cam_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 -EIO;	}	printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);	usb_set_intfdata (intf, cam);	return 0;}static voidvicam_disconnect(struct usb_interface *intf){	int open_count;	struct vicam_camera *cam = usb_get_intfdata (intf);	usb_set_intfdata (intf, NULL);	/* we must unregister the device before taking its	 * cam_lock. This is because the video open call	 * holds the same lock as video unregister. if we	 * unregister inside of the cam_lock and open also	 * uses the cam_lock, we get deadlock.	 */	video_unregister_device(&cam->vdev);	/* stop the camera from being used */	mutex_lock(&cam->cam_lock);	/* mark the camera as gone */	cam->udev = NULL;	/* the only thing left to do is synchronize with	 * our close/release function on who should release	 * the camera memory. if there are any users using the	 * camera, it's their job. if there are no users,	 * it's ours.	 */	open_count = cam->open_count;	mutex_unlock(&cam->cam_lock);	if (!open_count) {		kfree(cam);	}	printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");}/* */static int __initusb_vicam_init(void){	int retval;	DBG(KERN_INFO "ViCam-based WebCam driver startup\n");	retval = usb_register(&vicam_driver);	if (retval)		printk(KERN_WARNING "usb_register failed!\n");	return retval;}static void __exitusb_vicam_exit(void){	DBG(KERN_INFO	       "ViCam-based WebCam driver shutdown\n");	usb_deregister(&vicam_driver);}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 + -