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

📄 et61x251_core.c

📁 V4l driver for DVB HD
💻 C
📖 第 1 页 / 共 5 页
字号:
	    fmw_length = (u16)(rect->width),	    fmw_height = (u16)(rect->height);	int err = 0;	err += et61x251_write_reg(cam, fmw_sx & 0xff, 0x69);	err += et61x251_write_reg(cam, fmw_sy & 0xff, 0x6a);	err += et61x251_write_reg(cam, fmw_length & 0xff, 0x6b);	err += et61x251_write_reg(cam, fmw_height & 0xff, 0x6c);	err += et61x251_write_reg(cam, (fmw_sx >> 8) | ((fmw_sy & 0x300) >> 6)				       | ((fmw_length & 0x300) >> 4)				       | ((fmw_height & 0x300) >> 2), 0x6d);	if (err)		return -EIO;	PDBGG("fmw_sx, fmw_sy, fmw_length, fmw_height: %u %u %u %u",	      fmw_sx, fmw_sy, fmw_length, fmw_height);	return 0;}static int et61x251_init(struct et61x251_device* cam){	struct et61x251_sensor* s = &cam->sensor;	struct v4l2_control ctrl;	struct v4l2_queryctrl *qctrl;	struct v4l2_rect* rect;	u8 i = 0;	int err = 0;	if (!(cam->state & DEV_INITIALIZED)) {		init_waitqueue_head(&cam->open);		qctrl = s->qctrl;		rect = &(s->cropcap.defrect);		cam->compression.quality = ET61X251_COMPRESSION_QUALITY;	} else { /* use current values */		qctrl = s->_qctrl;		rect = &(s->_rect);	}	err += et61x251_set_scale(cam, rect->width / s->pix_format.width);	err += et61x251_set_crop(cam, rect);	if (err)		return err;	if (s->init) {		err = s->init(cam);		if (err) {			DBG(3, "Sensor initialization failed");			return err;		}	}	err += et61x251_set_compression(cam, &cam->compression);	err += et61x251_set_pix_format(cam, &s->pix_format);	if (s->set_pix_format)		err += s->set_pix_format(cam, &s->pix_format);	if (err)		return err;	if (s->pix_format.pixelformat == V4L2_PIX_FMT_ET61X251)		DBG(3, "Compressed video format is active, quality %d",		    cam->compression.quality);	else		DBG(3, "Uncompressed video format is active");	if (s->set_crop)		if ((err = s->set_crop(cam, rect))) {			DBG(3, "set_crop() failed");			return err;		}	if (s->set_ctrl) {		for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)			if (s->qctrl[i].id != 0 &&			    !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {				ctrl.id = s->qctrl[i].id;				ctrl.value = qctrl[i].default_value;				err = s->set_ctrl(cam, &ctrl);				if (err) {					DBG(3, "Set %s control failed",					    s->qctrl[i].name);					return err;				}				DBG(3, "Image sensor supports '%s' control",				    s->qctrl[i].name);			}	}	if (!(cam->state & DEV_INITIALIZED)) {		mutex_init(&cam->fileop_mutex);		spin_lock_init(&cam->queue_lock);		init_waitqueue_head(&cam->wait_frame);		init_waitqueue_head(&cam->wait_stream);		cam->nreadbuffers = 2;		memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));		memcpy(&(s->_rect), &(s->cropcap.defrect),		       sizeof(struct v4l2_rect));		cam->state |= DEV_INITIALIZED;	}	DBG(2, "Initialization succeeded");	return 0;}static void et61x251_release_resources(struct et61x251_device* cam){	mutex_lock(&et61x251_sysfs_lock);	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor);	video_set_drvdata(cam->v4ldev, NULL);	video_unregister_device(cam->v4ldev);	usb_put_dev(cam->usbdev);	mutex_unlock(&et61x251_sysfs_lock);	kfree(cam->control_buffer);}/*****************************************************************************/static int et61x251_open(struct inode* inode, struct file* filp){	struct et61x251_device* cam;	int err = 0;	/*	   This is the only safe way to prevent race conditions with	   disconnect	*/	if (!down_read_trylock(&et61x251_disconnect))		return -ERESTARTSYS;	cam = video_get_drvdata(video_devdata(filp));	if (mutex_lock_interruptible(&cam->dev_mutex)) {		up_read(&et61x251_disconnect);		return -ERESTARTSYS;	}	if (cam->users) {		DBG(2, "Device /dev/video%d is busy...", cam->v4ldev->minor);		if ((filp->f_flags & O_NONBLOCK) ||		    (filp->f_flags & O_NDELAY)) {			err = -EWOULDBLOCK;			goto out;		}		mutex_unlock(&cam->dev_mutex);		err = wait_event_interruptible_exclusive(cam->open,						  cam->state & DEV_DISCONNECTED							 || !cam->users);		if (err) {			up_read(&et61x251_disconnect);			return err;		}		if (cam->state & DEV_DISCONNECTED) {			up_read(&et61x251_disconnect);			return -ENODEV;		}		mutex_lock(&cam->dev_mutex);	}	if (cam->state & DEV_MISCONFIGURED) {		err = et61x251_init(cam);		if (err) {			DBG(1, "Initialization failed again. "			       "I will retry on next open().");			goto out;		}		cam->state &= ~DEV_MISCONFIGURED;	}	if ((err = et61x251_start_transfer(cam)))		goto out;	filp->private_data = cam;	cam->users++;	cam->io = IO_NONE;	cam->stream = STREAM_OFF;	cam->nbuffers = 0;	cam->frame_count = 0;	et61x251_empty_framequeues(cam);	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor);out:	mutex_unlock(&cam->dev_mutex);	up_read(&et61x251_disconnect);	return err;}static int et61x251_release(struct inode* inode, struct file* filp){	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));	mutex_lock(&cam->dev_mutex); /* prevent disconnect() to be called */	et61x251_stop_transfer(cam);	et61x251_release_buffers(cam);	if (cam->state & DEV_DISCONNECTED) {		et61x251_release_resources(cam);		mutex_unlock(&cam->dev_mutex);		kfree(cam);		return 0;	}	cam->users--;	wake_up_interruptible_nr(&cam->open, 1);	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor);	mutex_unlock(&cam->dev_mutex);	return 0;}static ssize_tet61x251_read(struct file* filp, char __user * buf,	      size_t count, loff_t* f_pos){	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));	struct et61x251_frame_t* f, * i;	unsigned long lock_flags;	long timeout;	int err = 0;	if (mutex_lock_interruptible(&cam->fileop_mutex))		return -ERESTARTSYS;	if (cam->state & DEV_DISCONNECTED) {		DBG(1, "Device not present");		mutex_unlock(&cam->fileop_mutex);		return -ENODEV;	}	if (cam->state & DEV_MISCONFIGURED) {		DBG(1, "The camera is misconfigured. Close and open it "		       "again.");		mutex_unlock(&cam->fileop_mutex);		return -EIO;	}	if (cam->io == IO_MMAP) {		DBG(3, "Close and open the device again to choose the read "		       "method");		mutex_unlock(&cam->fileop_mutex);		return -EINVAL;	}	if (cam->io == IO_NONE) {		if (!et61x251_request_buffers(cam, cam->nreadbuffers,					      IO_READ)) {			DBG(1, "read() failed, not enough memory");			mutex_unlock(&cam->fileop_mutex);			return -ENOMEM;		}		cam->io = IO_READ;		cam->stream = STREAM_ON;	}	if (list_empty(&cam->inqueue)) {		if (!list_empty(&cam->outqueue))			et61x251_empty_framequeues(cam);		et61x251_queue_unusedframes(cam);	}	if (!count) {		mutex_unlock(&cam->fileop_mutex);		return 0;	}	if (list_empty(&cam->outqueue)) {		if (filp->f_flags & O_NONBLOCK) {			mutex_unlock(&cam->fileop_mutex);			return -EAGAIN;		}		timeout = wait_event_interruptible_timeout			  ( cam->wait_frame,			    (!list_empty(&cam->outqueue)) ||			    (cam->state & DEV_DISCONNECTED) ||			    (cam->state & DEV_MISCONFIGURED),			    cam->module_param.frame_timeout *			    1000 * msecs_to_jiffies(1) );		if (timeout < 0) {			mutex_unlock(&cam->fileop_mutex);			return timeout;		}		if (cam->state & DEV_DISCONNECTED) {			mutex_unlock(&cam->fileop_mutex);			return -ENODEV;		}		if (!timeout || (cam->state & DEV_MISCONFIGURED)) {			mutex_unlock(&cam->fileop_mutex);			return -EIO;		}	}	f = list_entry(cam->outqueue.prev, struct et61x251_frame_t, frame);	if (count > f->buf.bytesused)		count = f->buf.bytesused;	if (copy_to_user(buf, f->bufmem, count)) {		err = -EFAULT;		goto exit;	}	*f_pos += count;exit:	spin_lock_irqsave(&cam->queue_lock, lock_flags);	list_for_each_entry(i, &cam->outqueue, frame)		i->state = F_UNUSED;	INIT_LIST_HEAD(&cam->outqueue);	spin_unlock_irqrestore(&cam->queue_lock, lock_flags);	et61x251_queue_unusedframes(cam);	PDBGG("Frame #%lu, bytes read: %zu",	      (unsigned long)f->buf.index, count);	mutex_unlock(&cam->fileop_mutex);	return err ? err : count;}static unsigned int et61x251_poll(struct file *filp, poll_table *wait){	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));	struct et61x251_frame_t* f;	unsigned long lock_flags;	unsigned int mask = 0;	if (mutex_lock_interruptible(&cam->fileop_mutex))		return POLLERR;	if (cam->state & DEV_DISCONNECTED) {		DBG(1, "Device not present");		goto error;	}	if (cam->state & DEV_MISCONFIGURED) {		DBG(1, "The camera is misconfigured. Close and open it "		       "again.");		goto error;	}	if (cam->io == IO_NONE) {		if (!et61x251_request_buffers(cam, cam->nreadbuffers,					      IO_READ)) {			DBG(1, "poll() failed, not enough memory");			goto error;		}		cam->io = IO_READ;		cam->stream = STREAM_ON;	}	if (cam->io == IO_READ) {		spin_lock_irqsave(&cam->queue_lock, lock_flags);		list_for_each_entry(f, &cam->outqueue, frame)			f->state = F_UNUSED;		INIT_LIST_HEAD(&cam->outqueue);		spin_unlock_irqrestore(&cam->queue_lock, lock_flags);		et61x251_queue_unusedframes(cam);	}	poll_wait(filp, &cam->wait_frame, wait);	if (!list_empty(&cam->outqueue))		mask |= POLLIN | POLLRDNORM;	mutex_unlock(&cam->fileop_mutex);	return mask;error:	mutex_unlock(&cam->fileop_mutex);	return POLLERR;}static void et61x251_vm_open(struct vm_area_struct* vma){	struct et61x251_frame_t* f = vma->vm_private_data;	f->vma_use_count++;}static void et61x251_vm_close(struct vm_area_struct* vma){	/* NOTE: buffers are not freed here */	struct et61x251_frame_t* f = vma->vm_private_data;	f->vma_use_count--;}static struct vm_operations_struct et61x251_vm_ops = {	.open = et61x251_vm_open,	.close = et61x251_vm_close,};static int et61x251_mmap(struct file* filp, struct vm_area_struct *vma){	struct et61x251_device* cam = video_get_drvdata(video_devdata(filp));	unsigned long size = vma->vm_end - vma->vm_start,		      start = vma->vm_start;	void *pos;	u32 i;	if (mutex_lock_interruptible(&cam->fileop_mutex))		return -ERESTARTSYS;	if (cam->state & DEV_DISCONNECTED) {		DBG(1, "Device not present");		mutex_unlock(&cam->fileop_mutex);		return -ENODEV;	}	if (cam->state & DEV_MISCONFIGURED) {		DBG(1, "The camera is misconfigured. Close and open it "		       "again.");		mutex_unlock(&cam->fileop_mutex);		return -EIO;	}	if (cam->io != IO_MMAP || !(vma->vm_flags & VM_WRITE) ||	    size != PAGE_ALIGN(cam->frame[0].buf.length)) {		mutex_unlock(&cam->fileop_mutex);		return -EINVAL;	}	for (i = 0; i < cam->nbuffers; i++) {		if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)			break;	}	if (i == cam->nbuffers) {		mutex_unlock(&cam->fileop_mutex);		return -EINVAL;	}	vma->vm_flags |= VM_IO;	vma->vm_flags |= VM_RESERVED;	pos = cam->frame[i].bufmem;	while (size > 0) { /* size is page-aligned */		if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {			mutex_unlock(&cam->fileop_mutex);			return -EAGAIN;		}		start += PAGE_SIZE;		pos += PAGE_SIZE;		size -= PAGE_SIZE;	}	vma->vm_ops = &et61x251_vm_ops;	vma->vm_private_data = &cam->frame[i];	et61x251_vm_open(vma);	mutex_unlock(&cam->fileop_mutex);	return 0;}/*****************************************************************************/static intet61x251_vidioc_querycap(struct et61x251_device* cam, void __user * arg){	struct v4l2_capability cap = {		.driver = "et61x251",		.version = ET61X251_MODULE_VERSION_CODE,		.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |				V4L2_CAP_STREAMING,	};	strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));	if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)		strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,			sizeof(cap.bus_info));	if (copy_to_user(arg, &cap, sizeof(cap)))		return -EFAULT;	return 0;}static intet61x251_vidioc_enuminput(struct et61x251_device* cam, void __user * arg){	struct v4l2_input i;	if (copy_from_user(&i, arg, sizeof(i)))		return -EFAULT;	if (i.index)		return -EINVAL;	memset(&i, 0, sizeof(i));	strcpy(i.name, "Camera");	i.type = V4L2_INPUT_TYPE_CAMERA;	if (copy_to_user(arg, &i, sizeof(i)))		return -EFAULT;	return 0;}static intet61x251_vidioc_g_input(struct et61x251_device* cam, void __user * arg){	int index = 0;	if (copy_to_user(arg, &index, sizeof(index)))		return -EFAULT;	return 0;

⌨️ 快捷键说明

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