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

sn9c102_core.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 4 页
字号:
				goto end_of_frame; /* (1) */			else {				DBG(3, "SOF before expected EOF after %lu "				       "bytes of image data", 				    (unsigned long)((*f)->buf.bytesused))				goto start_of_frame;			}		}	}resubmit_urb:	urb->dev = cam->usbdev;	err = usb_submit_urb(urb, GFP_ATOMIC);	if (err < 0 && err != -EPERM) {		cam->state |= DEV_MISCONFIGURED;		DBG(1, "usb_submit_urb() failed")	}	wake_up_interruptible(&cam->wait_frame);}static int sn9c102_start_transfer(struct sn9c102_device* cam){	struct usb_device *udev = cam->usbdev;	struct urb* urb;	const unsigned int wMaxPacketSize[] = {0, 128, 256, 384, 512,                                               680, 800, 900, 1023};	const unsigned int psz = wMaxPacketSize[SN9C102_ALTERNATE_SETTING];	s8 i, j;	int err = 0;	for (i = 0; i < SN9C102_URBS; i++) {		cam->transfer_buffer[i] = kmalloc(SN9C102_ISO_PACKETS * psz,		                                  GFP_KERNEL);		if (!cam->transfer_buffer[i]) {			err = -ENOMEM;			DBG(1, "Not enough memory")			goto free_buffers;		}	}	for (i = 0; i < SN9C102_URBS; i++) {		urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);		cam->urb[i] = urb;		if (!urb) {			err = -ENOMEM;			DBG(1, "usb_alloc_urb() failed")			goto free_urbs;		}		urb->dev = udev;		urb->context = cam;		urb->pipe = usb_rcvisocpipe(udev, 1);		urb->transfer_flags = URB_ISO_ASAP;		urb->number_of_packets = SN9C102_ISO_PACKETS;		urb->complete = sn9c102_urb_complete;		urb->transfer_buffer = cam->transfer_buffer[i];		urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;		urb->interval = 1;		for (j = 0; j < SN9C102_ISO_PACKETS; j++) {			urb->iso_frame_desc[j].offset = psz * j;			urb->iso_frame_desc[j].length = psz;		}	}	/* Enable video */	if (!(cam->reg[0x01] & 0x04)) {		err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);		if (err) {			err = -EIO;			DBG(1, "I/O hardware error")			goto free_urbs;		}	}	err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);	if (err) {		DBG(1, "usb_set_interface() failed")		goto free_urbs;	}	cam->frame_current = NULL;	for (i = 0; i < SN9C102_URBS; i++) {		err = usb_submit_urb(cam->urb[i], GFP_KERNEL);		if (err) {			for (j = i-1; j >= 0; j--)				usb_kill_urb(cam->urb[j]);			DBG(1, "usb_submit_urb() failed, error %d", err)			goto free_urbs;		}	}	return 0;free_urbs:	for (i = 0; (i < SN9C102_URBS) &&  cam->urb[i]; i++)		usb_free_urb(cam->urb[i]);free_buffers:	for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)		kfree(cam->transfer_buffer[i]);	return err;}static int sn9c102_stop_transfer(struct sn9c102_device* cam){	struct usb_device *udev = cam->usbdev;	s8 i;	int err = 0;	if (cam->state & DEV_DISCONNECTED)		return 0;	for (i = SN9C102_URBS-1; i >= 0; i--) {		usb_kill_urb(cam->urb[i]);		usb_free_urb(cam->urb[i]);		kfree(cam->transfer_buffer[i]);	}	err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */	if (err)		DBG(3, "usb_set_interface() failed")	return err;}/*****************************************************************************/static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count){	char str[5];	char* endp;	unsigned long val;	if (len < 4) {		strncpy(str, buff, len);		str[len+1] = '\0';	} else {		strncpy(str, buff, 4);		str[4] = '\0';	}	val = simple_strtoul(str, &endp, 0);	*count = 0;	if (val <= 0xff)		*count = (ssize_t)(endp - str);	if ((*count) && (len == *count+1) && (buff[*count] == '\n'))		*count += 1;	return (u8)val;}/*   NOTE 1: being inside one of the following methods implies that the v4l           device exists for sure (see kobjects and reference counters)   NOTE 2: buffers are PAGE_SIZE long*/static ssize_t sn9c102_show_reg(struct class_device* cd, char* buf){	struct sn9c102_device* cam;	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;	}	count = sprintf(buf, "%u\n", cam->sysfs.reg);	up(&sn9c102_sysfs_lock);	return count;} static ssize_t sn9c102_store_reg(struct class_device* cd, const char* buf, size_t len){	struct sn9c102_device* cam;	u8 index;	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;	}	index = sn9c102_strtou8(buf, len, &count);	if (index > 0x1f || !count) {		up(&sn9c102_sysfs_lock);		return -EINVAL;	}	cam->sysfs.reg = index;	DBG(2, "Moved SN9C10X register index to 0x%02X", cam->sysfs.reg)	DBG(3, "Written bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;}static ssize_t sn9c102_show_val(struct class_device* cd, char* buf){	struct sn9c102_device* cam;	ssize_t count;	int val;	if (down_interruptible(&sn9c102_sysfs_lock))		return -ERESTARTSYS;	cam = video_get_drvdata(to_video_device(cd));	if (!cam) {		up(&sn9c102_sysfs_lock);		return -ENODEV;	}	if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) {		up(&sn9c102_sysfs_lock);		return -EIO;	}	count = sprintf(buf, "%d\n", val);	DBG(3, "Read bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;} static ssize_tsn9c102_store_val(struct class_device* cd, const char* buf, size_t len){	struct sn9c102_device* cam;	u8 value;	ssize_t count;	int err;	if (down_interruptible(&sn9c102_sysfs_lock))		return -ERESTARTSYS;	cam = video_get_drvdata(to_video_device(cd));	if (!cam) {		up(&sn9c102_sysfs_lock);		return -ENODEV;	}	value = sn9c102_strtou8(buf, len, &count);	if (!count) {		up(&sn9c102_sysfs_lock);		return -EINVAL;	}	err = sn9c102_write_reg(cam, value, cam->sysfs.reg);	if (err) {		up(&sn9c102_sysfs_lock);		return -EIO;	}	DBG(2, "Written SN9C10X reg. 0x%02X, val. 0x%02X",	    cam->sysfs.reg, value)	DBG(3, "Written bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;}static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf){	struct sn9c102_device* cam;	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;	}	count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);	DBG(3, "Read bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;} static ssize_t sn9c102_store_i2c_reg(struct class_device* cd, const char* buf, size_t len){	struct sn9c102_device* cam;	u8 index;	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;	}	index = sn9c102_strtou8(buf, len, &count);	if (!count) {		up(&sn9c102_sysfs_lock);		return -EINVAL;	}	cam->sysfs.i2c_reg = index;	DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg)	DBG(3, "Written bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;}static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf){	struct sn9c102_device* cam;	ssize_t count;	int val;	if (down_interruptible(&sn9c102_sysfs_lock))		return -ERESTARTSYS;	cam = video_get_drvdata(to_video_device(cd));	if (!cam) {		up(&sn9c102_sysfs_lock);		return -ENODEV;	}	if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) {		up(&sn9c102_sysfs_lock);		return -EIO;	}	count = sprintf(buf, "%d\n", val);	DBG(3, "Read bytes: %zd", count)	up(&sn9c102_sysfs_lock);	return count;} static ssize_tsn9c102_store_i2c_val(struct class_device* cd, const char* buf, size_t len){	struct sn9c102_device* cam;	u8 value;	ssize_t count;	int err;	if (down_interruptible(&sn9c102_sysfs_lock))		return -ERESTARTSYS;	cam = video_get_drvdata(to_video_device(cd));	if (!cam) {		up(&sn9c102_sysfs_lock);		return -ENODEV;	}	value = sn9c102_strtou8(buf, len, &count);	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){	ssize_t res = 0;	u8 value;	ssize_t count;	value = sn9c102_strtou8(buf, len, &count);	if (!count || value > 0x0f)		return -EINVAL;	if ((res = sn9c102_store_reg(cd, "0x11", 4)) >= 0)		res = sn9c102_store_val(cd, buf, len);	return res;}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 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_green);	if (cam->sensor->slave_write_id && cam->sensor->slave_read_id) {		video_device_create_file(v4ldev, &class_device_attr_i2c_reg);		video_device_create_file(v4ldev, &class_device_attr_i2c_val);	}}/*****************************************************************************/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),	   ae_strx = 0x00,	   ae_stry = 0x00,	   ae_endx = h_size / 2,	   ae_endy = v_size / 2;	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);	err += sn9c102_write_reg(cam, ae_strx, 0x1c);	err += sn9c102_write_reg(cam, ae_stry, 0x1d);	err += sn9c102_write_reg(cam, ae_endx, 0x1e);	err += sn9c102_write_reg(cam, ae_endy, 0x1f);	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 (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 control failed")					return err;				}			}	}	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);		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);

⌨️ 快捷键说明

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