欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

sn9c102_core.c

优龙2410linux2.6.8内核源代码
C
第 1 页 / 共 4 页
字号:
		return 0;	}	case VIDIOC_G_FMT:	{		struct v4l2_format format;		struct v4l2_pix_format* pfmt = &(cam->sensor->pix_format);		if (copy_from_user(&format, arg, sizeof(format)))			return -EFAULT;		if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		pfmt->bytesperline = (pfmt->width * pfmt->priv) / 8;		pfmt->sizeimage = pfmt->height * pfmt->bytesperline;		pfmt->field = V4L2_FIELD_NONE;		memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));		if (copy_to_user(arg, &format, sizeof(format)))			return -EFAULT;		return 0;	}	case VIDIOC_TRY_FMT:	case VIDIOC_S_FMT:	{		struct sn9c102_sensor* s = cam->sensor;		struct v4l2_format format;		struct v4l2_pix_format* pix;		struct v4l2_pix_format* pfmt = &(s->pix_format);		struct v4l2_rect* bounds = &(s->cropcap.bounds);		struct v4l2_rect rect;		u8 scale;		const enum sn9c102_stream_state stream = cam->stream;		const u32 nbuffers = cam->nbuffers;		u32 i;		int err = 0;		if (copy_from_user(&format, arg, sizeof(format)))			return -EFAULT;		pix = &(format.fmt.pix);		if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		memcpy(&rect, &(s->_rect), sizeof(rect));		{ /* calculate the scaling factor */			u32 a, b;			a = rect.width * rect.height;			b = pix->width * pix->height;			scale = b ? (u8)((a / b) <= 1 ? 1 : ((a / b) == 3 ? 2 :			            ((a / b) > 4 ? 4 : (a / b)))) : 1;		}		rect.width = scale * pix->width;		rect.height = scale * pix->height;		if (rect.width < 16)			rect.width = 16;		if (rect.height < 16)			rect.height = 16;		if (rect.width > bounds->left + bounds->width - rect.left)			rect.width = bounds->left+bounds->width - rect.left;		if (rect.height > bounds->top + bounds->height - rect.top)			rect.height = bounds->top + bounds->height - rect.top;		rect.width &= ~15L;		rect.height &= ~15L;		pix->width = rect.width / scale;		pix->height = rect.height / scale;		pix->pixelformat = pfmt->pixelformat;		pix->priv = pfmt->priv; /* bpp */		pix->colorspace = pfmt->colorspace;		pix->bytesperline = (pix->width * pix->priv) / 8;		pix->sizeimage = pix->height * pix->bytesperline;		pix->field = V4L2_FIELD_NONE;		if (cmd == VIDIOC_TRY_FMT)			return 0;		for (i = 0; i < cam->nbuffers; i++)			if (cam->frame[i].vma_use_count) {				DBG(3, "VIDIOC_S_FMT failed. "				       "Unmap the buffers first.")				return -EINVAL;			}		if (cam->stream == STREAM_ON) {			cam->stream = STREAM_INTERRUPT;			err = wait_event_interruptible			      ( cam->wait_stream, 			        (cam->stream == STREAM_OFF) ||			        (cam->state & DEV_DISCONNECTED) );			if (err) {				cam->state |= DEV_MISCONFIGURED;				DBG(1, "The camera is misconfigured. To use "				       "it, close and open /dev/video%d "				       "again.", cam->v4ldev->minor)				return err;			}			if (cam->state & DEV_DISCONNECTED)				return -ENODEV;		}		if (copy_to_user(arg, &format, sizeof(format))) {			cam->stream = stream;			return -EFAULT;		}		sn9c102_release_buffers(cam);		err = sn9c102_set_crop(cam, &rect);		if (s->set_crop)			err += s->set_crop(cam, &rect);		err += sn9c102_set_scale(cam, scale);		if (err) { /* atomic, no rollback in ioctl() */			cam->state |= DEV_MISCONFIGURED;			DBG(1, "VIDIOC_S_FMT failed because of hardware "			       "problems. To use the camera, close and open "			       "/dev/video%d again.", cam->v4ldev->minor)			return err;		}		memcpy(pfmt, pix, sizeof(*pix));		memcpy(&(s->_rect), &rect, sizeof(rect));		if (nbuffers != sn9c102_request_buffers(cam, nbuffers)) {			cam->state |= DEV_MISCONFIGURED;			DBG(1, "VIDIOC_S_FMT failed because of not enough "			       "memory. To use the camera, close and open "			       "/dev/video%d again.", cam->v4ldev->minor)			return -ENOMEM;		}		cam->stream = stream;		return 0;	}	case VIDIOC_REQBUFS:	{		struct v4l2_requestbuffers rb;		u32 i;		int err;		if (copy_from_user(&rb, arg, sizeof(rb)))			return -EFAULT;		if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||		    rb.memory != V4L2_MEMORY_MMAP)			return -EINVAL;		if (cam->io == IO_READ) {			DBG(3, "Close and open the device again to choose "			       "the mmap I/O method")			return -EINVAL;		}		for (i = 0; i < cam->nbuffers; i++)			if (cam->frame[i].vma_use_count) {				DBG(3, "VIDIOC_REQBUFS failed. "				       "Previous buffers are still mapped.")				return -EINVAL;			}		if (cam->stream == STREAM_ON) {			cam->stream = STREAM_INTERRUPT;			err = wait_event_interruptible			      ( cam->wait_stream, 			        (cam->stream == STREAM_OFF) ||			        (cam->state & DEV_DISCONNECTED) );			if (err) {				cam->state |= DEV_MISCONFIGURED;				DBG(1, "The camera is misconfigured. To use "				       "it, close and open /dev/video%d "				       "again.", cam->v4ldev->minor)				return err;			}			if (cam->state & DEV_DISCONNECTED)				return -ENODEV;		}		sn9c102_empty_framequeues(cam);		sn9c102_release_buffers(cam);		if (rb.count)			rb.count = sn9c102_request_buffers(cam, rb.count);		if (copy_to_user(arg, &rb, sizeof(rb))) {			sn9c102_release_buffers(cam);			cam->io = IO_NONE;			return -EFAULT;		}		cam->io = rb.count ? IO_MMAP : IO_NONE;		return 0;	}	case VIDIOC_QUERYBUF:	{		struct v4l2_buffer b;		if (copy_from_user(&b, arg, sizeof(b)))			return -EFAULT;		if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||		    b.index >= cam->nbuffers || cam->io != IO_MMAP)			return -EINVAL;		memcpy(&b, &cam->frame[b.index].buf, sizeof(b));		if (cam->frame[b.index].vma_use_count)			b.flags |= V4L2_BUF_FLAG_MAPPED;		if (cam->frame[b.index].state == F_DONE)			b.flags |= V4L2_BUF_FLAG_DONE;		else if (cam->frame[b.index].state != F_UNUSED)			b.flags |= V4L2_BUF_FLAG_QUEUED;		if (copy_to_user(arg, &b, sizeof(b)))			return -EFAULT;		return 0;	}	case VIDIOC_QBUF:	{		struct v4l2_buffer b;		unsigned long lock_flags;		if (copy_from_user(&b, arg, sizeof(b)))			return -EFAULT;		if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||		    b.index >= cam->nbuffers || cam->io != IO_MMAP)			return -EINVAL;		if (cam->frame[b.index].state != F_UNUSED)			return -EINVAL;		cam->frame[b.index].state = F_QUEUED;		spin_lock_irqsave(&cam->queue_lock, lock_flags);		list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);		PDBGG("Frame #%lu queued", (unsigned long)b.index)		return 0;	}	case VIDIOC_DQBUF:	{		struct v4l2_buffer b;		struct sn9c102_frame_t *f;		unsigned long lock_flags;		int err = 0;		if (copy_from_user(&b, arg, sizeof(b)))			return -EFAULT;		if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io!= IO_MMAP)			return -EINVAL;		if (list_empty(&cam->outqueue)) {			if (cam->stream == STREAM_OFF)				return -EINVAL;			if (filp->f_flags & O_NONBLOCK)				return -EAGAIN;			err = wait_event_interruptible			      ( cam->wait_frame, 			        (!list_empty(&cam->outqueue)) ||			        (cam->state & DEV_DISCONNECTED) );			if (err)				return err;			if (cam->state & DEV_DISCONNECTED)				return -ENODEV;		}		spin_lock_irqsave(&cam->queue_lock, lock_flags);		f = list_entry(cam->outqueue.next, struct sn9c102_frame_t,		               frame);		list_del(&cam->outqueue);		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);		f->state = F_UNUSED;		memcpy(&b, &f->buf, sizeof(b));		if (f->vma_use_count)			b.flags |= V4L2_BUF_FLAG_MAPPED;		if (copy_to_user(arg, &b, sizeof(b)))			return -EFAULT;		PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index)		return 0;	}	case VIDIOC_STREAMON:	{		int type;		if (copy_from_user(&type, arg, sizeof(type)))			return -EFAULT;		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)			return -EINVAL;		if (list_empty(&cam->inqueue))			return -EINVAL;		cam->stream = STREAM_ON;		DBG(3, "Stream on")		return 0;	}	case VIDIOC_STREAMOFF:	{		int type, err;		if (copy_from_user(&type, arg, sizeof(type)))			return -EFAULT;		if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)			return -EINVAL;		if (cam->stream == STREAM_ON) {			cam->stream = STREAM_INTERRUPT;			err = wait_event_interruptible			      ( cam->wait_stream, 			        (cam->stream == STREAM_OFF) ||			        (cam->state & DEV_DISCONNECTED) );			if (err) {				cam->state |= DEV_MISCONFIGURED;				DBG(1, "The camera is misconfigured. To use "				       "it, close and open /dev/video%d "				       "again.", cam->v4ldev->minor)				return err;			}			if (cam->state & DEV_DISCONNECTED)				return -ENODEV;		}		sn9c102_empty_framequeues(cam);		DBG(3, "Stream off")		return 0;	}	case VIDIOC_G_STD:	case VIDIOC_S_STD:	case VIDIOC_QUERYSTD:	case VIDIOC_ENUMSTD:	case VIDIOC_QUERYMENU:	case VIDIOC_G_PARM:	case VIDIOC_S_PARM:		return -EINVAL;	default:		return -EINVAL;	}}static int sn9c102_ioctl(struct inode* inode, struct file* filp,                         unsigned int cmd, unsigned long arg){	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));	int err = 0;	if (down_interruptible(&cam->fileop_sem))		return -ERESTARTSYS;	if (cam->state & DEV_DISCONNECTED) {		DBG(1, "Device not present")		up(&cam->fileop_sem);		return -ENODEV;	}	if (cam->state & DEV_MISCONFIGURED) {		DBG(1, "The camera is misconfigured. Close and open it again.")		up(&cam->fileop_sem);		return -EIO;	}	err = sn9c102_v4l2_ioctl(inode, filp, cmd, (void __user *)arg);	up(&cam->fileop_sem);	return err;}static struct file_operations sn9c102_fops = {	.owner =   THIS_MODULE,	.open =    sn9c102_open,	.release = sn9c102_release,	.ioctl =   sn9c102_ioctl,	.read =    sn9c102_read,	.poll =    sn9c102_poll,	.mmap =    sn9c102_mmap,	.llseek =  no_llseek,};/*****************************************************************************//* It exists a single interface only. We do not need to validate anything. */static intsn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id){	struct usb_device *udev = interface_to_usbdev(intf);	struct sn9c102_device* cam;	static unsigned int dev_nr = 0;	unsigned int i, n;	int err = 0, r;	n = sizeof(sn9c102_id_table)/sizeof(sn9c102_id_table[0]);	for (i = 0; i < n-1; i++)		if (udev->descriptor.idVendor==sn9c102_id_table[i].idVendor &&		    udev->descriptor.idProduct==sn9c102_id_table[i].idProduct)			break;	if (i == n-1)		return -ENODEV;	if (!(cam = kmalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))		return -ENOMEM;	memset(cam, 0, sizeof(*cam));	cam->usbdev = udev;	memcpy(&cam->dev, &udev->dev, sizeof(struct device));	if (!(cam->control_buffer = kmalloc(8, GFP_KERNEL))) {		DBG(1, "kmalloc() failed")		err = -ENOMEM;		goto fail;	}	memset(cam->control_buffer, 0, 8);	if (!(cam->v4ldev = video_device_alloc())) {		DBG(1, "video_device_alloc() failed")		err = -ENOMEM;		goto fail;	}	init_MUTEX(&cam->dev_sem);	r = sn9c102_read_reg(cam, 0x00);	if (r < 0 || r != 0x10) {		DBG(1, "Sorry, this is not a SN9C10[12] based camera "		       "(vid/pid 0x%04X/0x%04X)",		    sn9c102_id_table[i].idVendor,sn9c102_id_table[i].idProduct)		err = -ENODEV;		goto fail;	}	DBG(2, "SN9C10[12] PC Camera Controller detected "	       "(vid/pid 0x%04X/0x%04X)",	    sn9c102_id_table[i].idVendor, sn9c102_id_table[i].idProduct)	for  (i = 0; sn9c102_sensor_table[i]; i++) {		err = sn9c102_sensor_table[i](cam);		if (!err)			break;	}	if (!err && cam->sensor) {		DBG(2, "%s image sensor detected", cam->sensor->name)		DBG(3, "Support for %s maintained by %s",		    cam->sensor->name, cam->sensor->maintainer)	} else {		DBG(1, "No supported image sensor detected")		err = -ENODEV;		goto fail;	}	if (sn9c102_init(cam)) {		DBG(1, "Initialization failed. I will retry on open().")		cam->state |= DEV_MISCONFIGURED;	}	strcpy(cam->v4ldev->name, "SN9C10[12] PC Camera");	cam->v4ldev->owner = THIS_MODULE;	cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;	cam->v4ldev->hardware = VID_HARDWARE_SN9C102;	cam->v4ldev->fops = &sn9c102_fops;	cam->v4ldev->minor = video_nr[dev_nr];	cam->v4ldev->release = video_device_release;	video_set_drvdata(cam->v4ldev, cam);	down(&cam->dev_sem);	err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,	                            video_nr[dev_nr]);	if (err) {		DBG(1, "V4L2 device registration failed")		if (err == -ENFILE && video_nr[dev_nr] == -1)			DBG(1, "Free /dev/videoX node not found")		video_nr[dev_nr] = -1;		dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;		up(&cam->dev_sem);		goto fail;	}	DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor)	sn9c102_create_sysfs(cam);	usb_set_intfdata(intf, cam);	up(&cam->dev_sem);	return 0;fail:	if (cam) {		kfree(cam->control_buffer);		if (cam->v4ldev)			video_device_release(cam->v4ldev);		kfree(cam);	}	return err;}static void sn9c102_usb_disconnect(struct usb_interface* intf){	struct sn9c102_device* cam = usb_get_intfdata(intf);	if (!cam)		return;	down_write(&sn9c102_disconnect);	down(&cam->dev_sem); 	DBG(2, "Disconnecting %s...", cam->v4ldev->name)	wake_up_interruptible_all(&cam->open);	if (cam->users) {		DBG(2, "Device /dev/video%d is open! Deregistration and "		       "memory deallocation are deferred on close.",		    cam->v4ldev->minor)		cam->state |= DEV_MISCONFIGURED;		sn9c102_stop_transfer(cam);		cam->state |= DEV_DISCONNECTED;		wake_up_interruptible(&cam->wait_frame);		wake_up_interruptible(&cam->wait_stream);	} else {		cam->state |= DEV_DISCONNECTED;		sn9c102_release_resources(cam);	}	up(&cam->dev_sem);	if (!cam->users)		kfree(cam);	up_write(&sn9c102_disconnect);}static struct usb_driver sn9c102_usb_driver = {	.owner =      THIS_MODULE,	.name =       "sn9c102",	.id_table =   sn9c102_id_table,	.probe =      sn9c102_usb_probe,	.disconnect = sn9c102_usb_disconnect,};/*****************************************************************************/static int __init sn9c102_module_init(void){	int err = 0;	KDBG(2, SN9C102_MODULE_NAME " v" SN9C102_MODULE_VERSION)	KDBG(3, SN9C102_MODULE_AUTHOR)	if ((err = usb_register(&sn9c102_usb_driver)))		KDBG(1, "usb_register() failed")	return err;}static void __exit sn9c102_module_exit(void){	usb_deregister(&sn9c102_usb_driver);}module_init(sn9c102_module_init);module_exit(sn9c102_module_exit);

⌨️ 快捷键说明

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