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

📄 meye.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
		break;	}	case VIDIOC_QUERYBUF: {		struct v4l2_buffer *buf = arg;		int index = buf->index;		if (index < 0 || index >= gbuffers)			return -EINVAL;		memset(buf, 0, sizeof(*buf));		buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		buf->index = index;		buf->bytesused = meye.grab_buffer[index].size;		buf->flags = V4L2_BUF_FLAG_MAPPED;		if (meye.grab_buffer[index].state == MEYE_BUF_USING)			buf->flags |= V4L2_BUF_FLAG_QUEUED;		if (meye.grab_buffer[index].state == MEYE_BUF_DONE)			buf->flags |= V4L2_BUF_FLAG_DONE;		buf->field = V4L2_FIELD_NONE;		buf->timestamp = meye.grab_buffer[index].timestamp;		buf->sequence = meye.grab_buffer[index].sequence;		buf->memory = V4L2_MEMORY_MMAP;		buf->m.offset = index * gbufsize;		buf->length = gbufsize;		break;	}	case VIDIOC_QBUF: {		struct v4l2_buffer *buf = arg;		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		if (buf->memory != V4L2_MEMORY_MMAP)			return -EINVAL;		if (buf->index < 0 || buf->index >= gbuffers)			return -EINVAL;		if (meye.grab_buffer[buf->index].state != MEYE_BUF_UNUSED)			return -EINVAL;		down(&meye.lock);		buf->flags |= V4L2_BUF_FLAG_QUEUED;		buf->flags &= ~V4L2_BUF_FLAG_DONE;		meye.grab_buffer[buf->index].state = MEYE_BUF_USING;		kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int));		up(&meye.lock);		break;	}	case VIDIOC_DQBUF: {		struct v4l2_buffer *buf = arg;		int reqnr;		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		if (buf->memory != V4L2_MEMORY_MMAP)			return -EINVAL;		down(&meye.lock);		if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) {			up(&meye.lock);			return -EAGAIN;		}		if (wait_event_interruptible(meye.proc_list,					     kfifo_len(meye.doneq) != 0) < 0) {			up(&meye.lock);			return -EINTR;		}		if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr,			       sizeof(int))) {			up(&meye.lock);			return -EBUSY;		}		if (meye.grab_buffer[reqnr].state != MEYE_BUF_DONE) {			up(&meye.lock);			return -EINVAL;		}		buf->index = reqnr;		buf->bytesused = meye.grab_buffer[reqnr].size;		buf->flags = V4L2_BUF_FLAG_MAPPED;		buf->field = V4L2_FIELD_NONE;		buf->timestamp = meye.grab_buffer[reqnr].timestamp;		buf->sequence = meye.grab_buffer[reqnr].sequence;		buf->memory = V4L2_MEMORY_MMAP;		buf->m.offset = reqnr * gbufsize;		buf->length = gbufsize;		meye.grab_buffer[reqnr].state = MEYE_BUF_UNUSED;		up(&meye.lock);		break;	}	case VIDIOC_STREAMON: {		down(&meye.lock);		switch (meye.mchip_mode) {		case MCHIP_HIC_MODE_CONT_OUT:			mchip_continuous_start();			break;		case MCHIP_HIC_MODE_CONT_COMP:			mchip_cont_compression_start();			break;		default:			up(&meye.lock);			return -EINVAL;		}		up(&meye.lock);		break;	}	case VIDIOC_STREAMOFF: {		int i;		down(&meye.lock);		mchip_hic_stop();		kfifo_reset(meye.grabq);		kfifo_reset(meye.doneq);		for (i = 0; i < MEYE_MAX_BUFNBRS; i++)			meye.grab_buffer[i].state = MEYE_BUF_UNUSED;		up(&meye.lock);		break;	}	/*	 * XXX what about private snapshot ioctls ?	 * Do they need to be converted to V4L2 ?	*/	default:		return -ENOIOCTLCMD;	}	return 0;}static int meye_ioctl(struct inode *inode, struct file *file,		     unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, meye_do_ioctl);}static unsigned int meye_poll(struct file *file, poll_table *wait){	unsigned int res = 0;	down(&meye.lock);	poll_wait(file, &meye.proc_list, wait);	if (kfifo_len(meye.doneq))		res = POLLIN | POLLRDNORM;	up(&meye.lock);	return res;}static void meye_vm_open(struct vm_area_struct *vma){	int idx = (int)vma->vm_private_data;	meye.vma_use_count[idx]++;}static void meye_vm_close(struct vm_area_struct *vma){	int idx = (int)vma->vm_private_data;	meye.vma_use_count[idx]--;}static struct vm_operations_struct meye_vm_ops = {	.open		= meye_vm_open,	.close		= meye_vm_close,};static int meye_mmap(struct file *file, struct vm_area_struct *vma){	unsigned long start = vma->vm_start;	unsigned long size = vma->vm_end - vma->vm_start;	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;	unsigned long page, pos;	down(&meye.lock);	if (size > gbuffers * gbufsize) {		up(&meye.lock);		return -EINVAL;	}	if (!meye.grab_fbuffer) {		int i;		/* lazy allocation */		meye.grab_fbuffer = rvmalloc(gbuffers*gbufsize);		if (!meye.grab_fbuffer) {			printk(KERN_ERR "meye: v4l framebuffer allocation failed\n");			up(&meye.lock);			return -ENOMEM;		}		for (i = 0; i < gbuffers; i++)			meye.vma_use_count[i] = 0;	}	pos = (unsigned long)meye.grab_fbuffer + offset;	while (size > 0) {		page = vmalloc_to_pfn((void *)pos);		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {			up(&meye.lock);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		if (size > PAGE_SIZE)			size -= PAGE_SIZE;		else			size = 0;	}	vma->vm_ops = &meye_vm_ops;	vma->vm_flags &= ~VM_IO;	/* not I/O memory */	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */	vma->vm_private_data = (void *) (offset / gbufsize);	meye_vm_open(vma);	up(&meye.lock);	return 0;}static struct file_operations meye_fops = {	.owner		= THIS_MODULE,	.open		= meye_open,	.release	= meye_release,	.mmap		= meye_mmap,	.ioctl		= meye_ioctl,	.poll		= meye_poll,	.llseek		= no_llseek,};static struct video_device meye_template = {	.owner		= THIS_MODULE,	.name		= "meye",	.type		= VID_TYPE_CAPTURE,	.hardware	= VID_HARDWARE_MEYE,	.fops		= &meye_fops,	.release	= video_device_release,	.minor		= -1,};#ifdef CONFIG_PMstatic int meye_suspend(struct pci_dev *pdev, pm_message_t state){	pci_save_state(pdev);	meye.pm_mchip_mode = meye.mchip_mode;	mchip_hic_stop();	mchip_set(MCHIP_MM_INTA, 0x0);	return 0;}static int meye_resume(struct pci_dev *pdev){	pci_restore_state(pdev);	pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);	mchip_delay(MCHIP_HIC_CMD, 0);	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);	msleep(1);	mchip_set(MCHIP_VRJ_SOFT_RESET, 1);	msleep(1);	mchip_set(MCHIP_MM_PCI_MODE, 5);	msleep(1);	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);	switch (meye.pm_mchip_mode) {	case MCHIP_HIC_MODE_CONT_OUT:		mchip_continuous_start();		break;	case MCHIP_HIC_MODE_CONT_COMP:		mchip_cont_compression_start();		break;	}	return 0;}#endifstatic int __devinit meye_probe(struct pci_dev *pcidev,				const struct pci_device_id *ent){	int ret = -EBUSY;	unsigned long mchip_adr;	u8 revision;	if (meye.mchip_dev != NULL) {		printk(KERN_ERR "meye: only one device allowed!\n");		goto outnotdev;	}	meye.mchip_dev = pcidev;	meye.video_dev = video_device_alloc();	if (!meye.video_dev) {		printk(KERN_ERR "meye: video_device_alloc() failed!\n");		goto outnotdev;	}	ret = -ENOMEM;	meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);	if (!meye.grab_temp) {		printk(KERN_ERR "meye: grab buffer allocation failed\n");		goto outvmalloc;	}	spin_lock_init(&meye.grabq_lock);	meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL,				 &meye.grabq_lock);	if (IS_ERR(meye.grabq)) {		printk(KERN_ERR "meye: fifo allocation failed\n");		goto outkfifoalloc1;	}	spin_lock_init(&meye.doneq_lock);	meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL,				 &meye.doneq_lock);	if (IS_ERR(meye.doneq)) {		printk(KERN_ERR "meye: fifo allocation failed\n");		goto outkfifoalloc2;	}	memcpy(meye.video_dev, &meye_template, sizeof(meye_template));	meye.video_dev->dev = &meye.mchip_dev->dev;	if ((ret = sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 1))) {		printk(KERN_ERR "meye: unable to power on the camera\n");		printk(KERN_ERR "meye: did you enable the camera in "				"sonypi using the module options ?\n");		goto outsonypienable;	}	ret = -EIO;	if ((ret = pci_enable_device(meye.mchip_dev))) {		printk(KERN_ERR "meye: pci_enable_device failed\n");		goto outenabledev;	}	mchip_adr = pci_resource_start(meye.mchip_dev,0);	if (!mchip_adr) {		printk(KERN_ERR "meye: mchip has no device base address\n");		goto outregions;	}	if (!request_mem_region(pci_resource_start(meye.mchip_dev, 0),				pci_resource_len(meye.mchip_dev, 0),				"meye")) {		printk(KERN_ERR "meye: request_mem_region failed\n");		goto outregions;	}	meye.mchip_mmregs = ioremap(mchip_adr, MCHIP_MM_REGS);	if (!meye.mchip_mmregs) {		printk(KERN_ERR "meye: ioremap failed\n");		goto outremap;	}	meye.mchip_irq = pcidev->irq;	if (request_irq(meye.mchip_irq, meye_irq,			SA_INTERRUPT | SA_SHIRQ, "meye", meye_irq)) {		printk(KERN_ERR "meye: request_irq failed\n");		goto outreqirq;	}	pci_read_config_byte(meye.mchip_dev, PCI_REVISION_ID, &revision);	pci_write_config_byte(meye.mchip_dev, PCI_CACHE_LINE_SIZE, 8);	pci_write_config_byte(meye.mchip_dev, PCI_LATENCY_TIMER, 64);	pci_set_master(meye.mchip_dev);	/* Ask the camera to perform a soft reset. */	pci_write_config_word(meye.mchip_dev, MCHIP_PCI_SOFTRESET_SET, 1);	mchip_delay(MCHIP_HIC_CMD, 0);	mchip_delay(MCHIP_HIC_STATUS, MCHIP_HIC_STATUS_IDLE);	msleep(1);	mchip_set(MCHIP_VRJ_SOFT_RESET, 1);	msleep(1);	mchip_set(MCHIP_MM_PCI_MODE, 5);	msleep(1);	mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);	if (video_register_device(meye.video_dev, VFL_TYPE_GRABBER,				  video_nr) < 0) {		printk(KERN_ERR "meye: video_register_device failed\n");		goto outvideoreg;	}	init_MUTEX(&meye.lock);	init_waitqueue_head(&meye.proc_list);	meye.picture.depth = 16;	meye.picture.palette = VIDEO_PALETTE_YUV422;	meye.picture.brightness = 32 << 10;	meye.picture.hue = 32 << 10;	meye.picture.colour = 32 << 10;	meye.picture.contrast = 32 << 10;	meye.picture.whiteness = 0;	meye.params.subsample = 0;	meye.params.quality = 8;	meye.params.sharpness = 32;	meye.params.agc = 48;	meye.params.picture = 0;	meye.params.framerate = 0;	sonypi_camera_command(SONYPI_COMMAND_SETCAMERABRIGHTNESS, 32);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERAHUE, 32);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERACOLOR, 32);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERACONTRAST, 32);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERASHARPNESS, 32);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERAPICTURE, 0);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERAAGC, 48);	printk(KERN_INFO "meye: Motion Eye Camera Driver v%s.\n",	       MEYE_DRIVER_VERSION);	printk(KERN_INFO "meye: mchip KL5A72002 rev. %d, base %lx, irq %d\n",	       revision, mchip_adr, meye.mchip_irq);	return 0;outvideoreg:	free_irq(meye.mchip_irq, meye_irq);outreqirq:	iounmap(meye.mchip_mmregs);outremap:	release_mem_region(pci_resource_start(meye.mchip_dev, 0),			   pci_resource_len(meye.mchip_dev, 0));outregions:	pci_disable_device(meye.mchip_dev);outenabledev:	sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);outsonypienable:	kfifo_free(meye.doneq);outkfifoalloc2:	kfifo_free(meye.grabq);outkfifoalloc1:	vfree(meye.grab_temp);outvmalloc:	video_device_release(meye.video_dev);outnotdev:	return ret;}static void __devexit meye_remove(struct pci_dev *pcidev){	video_unregister_device(meye.video_dev);	mchip_hic_stop();	mchip_dma_free();	/* disable interrupts */	mchip_set(MCHIP_MM_INTA, 0x0);	free_irq(meye.mchip_irq, meye_irq);	iounmap(meye.mchip_mmregs);	release_mem_region(pci_resource_start(meye.mchip_dev, 0),			   pci_resource_len(meye.mchip_dev, 0));	pci_disable_device(meye.mchip_dev);	sonypi_camera_command(SONYPI_COMMAND_SETCAMERA, 0);	kfifo_free(meye.doneq);	kfifo_free(meye.grabq);	vfree(meye.grab_temp);	if (meye.grab_fbuffer) {		rvfree(meye.grab_fbuffer, gbuffers*gbufsize);		meye.grab_fbuffer = NULL;	}	printk(KERN_INFO "meye: removed\n");}static struct pci_device_id meye_pci_tbl[] = {	{ PCI_VENDOR_ID_KAWASAKI, PCI_DEVICE_ID_MCHIP_KL5A72002,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ }};MODULE_DEVICE_TABLE(pci, meye_pci_tbl);static struct pci_driver meye_driver = {	.name		= "meye",	.id_table	= meye_pci_tbl,	.probe		= meye_probe,	.remove		= __devexit_p(meye_remove),#ifdef CONFIG_PM	.suspend	= meye_suspend,	.resume		= meye_resume,#endif};static int __init meye_init(void){	gbuffers = max(2, min((int)gbuffers, MEYE_MAX_BUFNBRS));	if (gbufsize < 0 || gbufsize > MEYE_MAX_BUFSIZE)		gbufsize = MEYE_MAX_BUFSIZE;	gbufsize = PAGE_ALIGN(gbufsize);	printk(KERN_INFO "meye: using %d buffers with %dk (%dk total)"			 "for capture\n",			 gbuffers,			 gbufsize / 1024, gbuffers * gbufsize / 1024);	return pci_register_driver(&meye_driver);}static void __exit meye_exit(void){	pci_unregister_driver(&meye_driver);}module_init(meye_init);module_exit(meye_exit);

⌨️ 快捷键说明

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