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

📄 sn9c102_core.c

📁 linux下sn9c102芯片的数码相机的驱动程序。
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!count) {		up(&sn9c102_sysfs_lock);		return -EINVAL;	}	err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);	if (err) {		up(&sn9c102_sysfs_lock);		return -EIO;	}	DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",	    cam->sysfs.i2c_reg, value)	DBG(3, "Written bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;}static ssize_tsn9c102_store_green(struct class_device* cd, const char* buf, size_t len){	struct sn9c102_device* cam;	enum sn9c102_bridge bridge;	ssize_t res = 0;	u8 value;	ssize_t count;	if (down_interruptible(&sn9c102_sysfs_lock))		return -ERESTARTSYS;	cam = video_get_drvdata(to_video_device(cd));	if (!cam) {		up(&sn9c102_sysfs_lock);		return -ENODEV;	}	bridge = cam->bridge;	up(&sn9c102_sysfs_lock);	value = sn9c102_strtou8(buf, len, &count);	if (!count)		return -EINVAL;	switch (bridge) {	case BRIDGE_SN9C101:	case BRIDGE_SN9C102:		if (value > 0x0f)			return -EINVAL;		if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0)			res = sn9c102_store_val(cd, buf, len);		break;	case BRIDGE_SN9C103:		if (value > 0x7f)			return -EINVAL;		if ((res = sn9c102_store_reg(cd, "0x04", 4)) >= 0)			res = sn9c102_store_val(cd, buf, len);		break;	}	return res;}static ssize_tsn9c102_store_blue(struct class_device* cd, const char* buf, size_t len){	ssize_t res = 0;	u8 value;	ssize_t count;	value = sn9c102_strtou8(buf, len, &count);	if (!count || value > 0x7f)		return -EINVAL;	if ((res = sn9c102_store_reg(cd, "0x06", 4)) >= 0)		res = sn9c102_store_val(cd, buf, len);	return res;}static ssize_tsn9c102_store_red(struct class_device* cd, const char* buf, size_t len){	ssize_t res = 0;	u8 value;	ssize_t count;	value = sn9c102_strtou8(buf, len, &count);	if (!count || value > 0x7f)		return -EINVAL;	if ((res = sn9c102_store_reg(cd, "0x05", 4)) >= 0)		res = sn9c102_store_val(cd, buf, len);	return res;}static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf){	struct sn9c102_device* cam;	ssize_t count;	cam = video_get_drvdata(to_video_device(cd));	if (!cam)		return -ENODEV;	count = sizeof(cam->sysfs.frame_header);	memcpy(buf, cam->sysfs.frame_header, count);	DBG(3, "Frame header, read bytes: %zd", count)	return count;} static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,                         sn9c102_show_reg, sn9c102_store_reg);static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,                         sn9c102_show_val, sn9c102_store_val);static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,                         sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,                         sn9c102_show_i2c_val, sn9c102_store_i2c_val);static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,                         sn9c102_show_frame_header, NULL);static void sn9c102_create_sysfs(struct sn9c102_device* cam){	struct video_device *v4ldev = cam->v4ldev;	video_device_create_file(v4ldev, &class_device_attr_reg);	video_device_create_file(v4ldev, &class_device_attr_val);	video_device_create_file(v4ldev, &class_device_attr_frame_header);	if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)		video_device_create_file(v4ldev, &class_device_attr_green);	else if (cam->bridge == BRIDGE_SN9C103) {		video_device_create_file(v4ldev, &class_device_attr_blue);		video_device_create_file(v4ldev, &class_device_attr_red);	}	if (cam->sensor->sysfs_ops) {		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);		video_device_create_file(v4ldev, &class_device_attr_i2c_val);	}}/*****************************************************************************/static intsn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix){	int err = 0;	if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)		err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18);	else		err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18);	return err ? -EIO : 0;}static intsn9c102_set_compression(struct sn9c102_device* cam,                        struct v4l2_jpegcompression* compression){	int err = 0;	if (compression->quality == 0)		err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01, 0x17);	else if (compression->quality == 1)		err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe, 0x17);	return err ? -EIO : 0;}static int sn9c102_set_scale(struct sn9c102_device* cam, u8 scale){	u8 r = 0;	int err = 0;	if (scale == 1)		r = cam->reg[0x18] & 0xcf;	else if (scale == 2) {		r = cam->reg[0x18] & 0xcf;		r |= 0x10;	} else if (scale == 4)		r = cam->reg[0x18] | 0x20;	err += sn9c102_write_reg(cam, r, 0x18);	if (err)		return -EIO;	PDBGG("Scaling factor: %u", scale)	return 0;}static int sn9c102_set_crop(struct sn9c102_device* cam, struct v4l2_rect* rect){	struct sn9c102_sensor* s = cam->sensor;	u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),	   v_start = (u8)(rect->top - s->cropcap.bounds.top),	   h_size = (u8)(rect->width / 16),	   v_size = (u8)(rect->height / 16);	int err = 0;	err += sn9c102_write_reg(cam, h_start, 0x12);	err += sn9c102_write_reg(cam, v_start, 0x13);	err += sn9c102_write_reg(cam, h_size, 0x15);	err += sn9c102_write_reg(cam, v_size, 0x16);	if (err)		return -EIO;	PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "	      "%u %u %u %u", h_start, v_start, h_size, v_size)	return 0;}static int sn9c102_init(struct sn9c102_device* cam){	struct sn9c102_sensor* s = cam->sensor;	struct v4l2_control ctrl;	struct v4l2_queryctrl *qctrl;	struct v4l2_rect* rect;	u8 i = 0, n = 0;	int err = 0;	if (!(cam->state & DEV_INITIALIZED)) {		init_waitqueue_head(&cam->open);		qctrl = s->qctrl;		rect = &(s->cropcap.defrect);	} else { /* use current values */		qctrl = s->_qctrl;		rect = &(s->_rect);	}	err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);	err += sn9c102_set_crop(cam, rect);	if (err)		return err;	if (s->init) {		err = s->init(cam);		if (err) {			DBG(3, "Sensor initialization failed")			return err;		}	}	if (!(cam->state & DEV_INITIALIZED))		cam->compression.quality =  cam->reg[0x17] & 0x01 ? 0 : 1;	else		err += sn9c102_set_compression(cam, &cam->compression);	err += sn9c102_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_SN9C10X)		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) {		n = sizeof(s->qctrl) / sizeof(s->qctrl[0]);		for (i = 0; i < n; 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)) {		init_MUTEX(&cam->fileop_sem);		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 sn9c102_release_resources(struct sn9c102_device* cam){	down(&sn9c102_sysfs_lock);	DBG(2, "V4L2 device /dev/video%d deregistered", cam->v4ldev->minor)	video_set_drvdata(cam->v4ldev, NULL);	video_unregister_device(cam->v4ldev);	up(&sn9c102_sysfs_lock);	kfree(cam->control_buffer);}/*****************************************************************************/static int sn9c102_open(struct inode* inode, struct file* filp){	struct sn9c102_device* cam;	int err = 0;	/*	   This is the only safe way to prevent race conditions with	   disconnect	*/	if (!down_read_trylock(&sn9c102_disconnect))		return -ERESTARTSYS;	cam = video_get_drvdata(video_devdata(filp));	if (down_interruptible(&cam->dev_sem)) {		up_read(&sn9c102_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;		}		up(&cam->dev_sem);		err = wait_event_interruptible_exclusive(cam->open,		                                  cam->state & DEV_DISCONNECTED		                                         || !cam->users);		if (err) {			up_read(&sn9c102_disconnect);			return err;		}		if (cam->state & DEV_DISCONNECTED) {			up_read(&sn9c102_disconnect);			return -ENODEV;		}		down(&cam->dev_sem);	}	if (cam->state & DEV_MISCONFIGURED) {		err = sn9c102_init(cam);		if (err) {			DBG(1, "Initialization failed again. "			       "I will retry on next open().")			goto out;		}		cam->state &= ~DEV_MISCONFIGURED;	}	if ((err = sn9c102_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;	sn9c102_empty_framequeues(cam);	DBG(3, "Video device /dev/video%d is open", cam->v4ldev->minor)out:	up(&cam->dev_sem);	up_read(&sn9c102_disconnect);	return err;}static int sn9c102_release(struct inode* inode, struct file* filp){	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));	down(&cam->dev_sem); /* prevent disconnect() to be called */	sn9c102_stop_transfer(cam);	sn9c102_release_buffers(cam);	if (cam->state & DEV_DISCONNECTED) {		sn9c102_release_resources(cam);		up(&cam->dev_sem);		kfree(cam);		return 0;	}	cam->users--;	wake_up_interruptible_nr(&cam->open, 1);	DBG(3, "Video device /dev/video%d closed", cam->v4ldev->minor)	up(&cam->dev_sem);	return 0;}static ssize_tsn9c102_read(struct file* filp, char __user * buf, size_t count, loff_t* f_pos){	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));	struct sn9c102_frame_t* f, * i;	unsigned long lock_flags;	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;	}	if (cam->io == IO_MMAP) {		DBG(3, "Close and open the device again to choose "		       "the read method")		up(&cam->fileop_sem);		return -EINVAL;	}	if (cam->io == IO_NONE) {		if (!sn9c102_request_buffers(cam,cam->nreadbuffers, IO_READ)) {			DBG(1, "read() failed, not enough memory")			up(&cam->fileop_sem);			return -ENOMEM;		}		cam->io = IO_READ;		cam->stream = STREAM_ON;		sn9c102_queue_unusedframes(cam);	}	if (!count) {		up(&cam->fileop_sem);		return 0;	}	if (list_empty(&cam->outqueue)) {		if (filp->f_flags & O_NONBLOCK) {			up(&cam->fileop_sem);			return -EAGAIN;		}		err = wait_event_interruptible		      ( cam->wait_frame, 		        (!list_empty(&cam->outqueue)) ||		        (cam->state & DEV_DISCONNECTED) ||			(cam->state & DEV_MISCONFIGURED) );		if (err) {			up(&cam->fileop_sem);			return err;		}		if (cam->state & DEV_DISCONNECTED) {			up(&cam->fileop_sem);			return -ENODEV;		}		if (cam->state & DEV_MISCONFIGURED) {			up(&cam->fileop_sem);			return -EIO;		}	}	f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);	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);	sn9c102_queue_unusedframes(cam);	if (count > f->buf.bytesused)		count = f->buf.bytesused;	if (copy_to_user(buf, f->bufmem, count)) {		up(&cam->fileop_sem);		return -EFAULT;	}	*f_pos += count;	PDBGG("Frame #%lu, bytes read: %zu", (unsigned long)f->buf.index,count)	up(&cam->fileop_sem);	return count;}static unsigned int sn9c102_poll(struct file *filp, poll_table *wait){	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));	unsigned int mask = 0;	if (down_interruptible(&cam->fileop_sem))		return POLLERR;

⌨️ 快捷键说明

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