sn9c102_core.c
字号:
#ifdef CONFIG_VIDEO_ADV_DEBUGstatic u16 sn9c102_strtou16(const char* buff, size_t len, ssize_t* count){ char str[7]; char* endp; unsigned long val; if (len < 6) { strncpy(str, buff, len); str[len] = '\0'; } else { strncpy(str, buff, 6); str[6] = '\0'; } val = simple_strtoul(str, &endp, 0); *count = 0; if (val <= 0xffff) *count = (ssize_t)(endp - str); if ((*count) && (len == *count+1) && (buff[*count] == '\n')) *count += 1; return (u16)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 device* cd, struct device_attribute *attr, char* buf){ struct sn9c102_device* cam; ssize_t count; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.reg); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_tsn9c102_store_reg(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ struct sn9c102_device* cam; u16 index; ssize_t count; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } index = sn9c102_strtou16(buf, len, &count); if (index >= ARRAY_SIZE(cam->reg) || !count) { mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } cam->sysfs.reg = index; DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg); DBG(3, "Written bytes: %zd", count); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_t sn9c102_show_val(struct device* cd, struct device_attribute *attr, char* buf){ struct sn9c102_device* cam; ssize_t count; int val; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if ((val = sn9c102_read_reg(cam, cam->sysfs.reg)) < 0) { mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } count = sprintf(buf, "%d\n", val); DBG(3, "Read bytes: %zd, value: %d", count, val); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_tsn9c102_store_val(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ struct sn9c102_device* cam; u16 value; ssize_t count; int err; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } value = sn9c102_strtou16(buf, len, &count); if (!count) { mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } err = sn9c102_write_reg(cam, value, cam->sysfs.reg); if (err) { mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X", cam->sysfs.reg, value); DBG(3, "Written bytes: %zd", count); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_t sn9c102_show_i2c_reg(struct device* cd, struct device_attribute *attr, char* buf){ struct sn9c102_device* cam; ssize_t count; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); DBG(3, "Read bytes: %zd", count); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_tsn9c102_store_i2c_reg(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ struct sn9c102_device* cam; u16 index; ssize_t count; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } index = sn9c102_strtou16(buf, len, &count); if (!count) { mutex_unlock(&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); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_t sn9c102_show_i2c_val(struct device* cd, struct device_attribute *attr, char* buf){ struct sn9c102_device* cam; ssize_t count; int val; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) { mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } if ((val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { mutex_unlock(&sn9c102_sysfs_lock); return -EIO; } count = sprintf(buf, "%d\n", val); DBG(3, "Read bytes: %zd, value: %d", count, val); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_tsn9c102_store_i2c_val(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ struct sn9c102_device* cam; u16 value; ssize_t count; int err; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) { mutex_unlock(&sn9c102_sysfs_lock); return -ENOSYS; } value = sn9c102_strtou16(buf, len, &count); if (!count) { mutex_unlock(&sn9c102_sysfs_lock); return -EINVAL; } err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value); if (err) { mutex_unlock(&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); mutex_unlock(&sn9c102_sysfs_lock); return count;}static ssize_tsn9c102_store_green(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ struct sn9c102_device* cam; enum sn9c102_bridge bridge; ssize_t res = 0; u16 value; ssize_t count; if (mutex_lock_interruptible(&sn9c102_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); if (!cam) { mutex_unlock(&sn9c102_sysfs_lock); return -ENODEV; } bridge = cam->bridge; mutex_unlock(&sn9c102_sysfs_lock); value = sn9c102_strtou16(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, attr, "0x11", 4)) >= 0) res = sn9c102_store_val(cd, attr, buf, len); break; case BRIDGE_SN9C103: case BRIDGE_SN9C105: case BRIDGE_SN9C120: if (value > 0x7f) return -EINVAL; if ((res = sn9c102_store_reg(cd, attr, "0x07", 4)) >= 0) res = sn9c102_store_val(cd, attr, buf, len); break; } return res;}static ssize_tsn9c102_store_blue(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ ssize_t res = 0; u16 value; ssize_t count; value = sn9c102_strtou16(buf, len, &count); if (!count || value > 0x7f) return -EINVAL; if ((res = sn9c102_store_reg(cd, attr, "0x06", 4)) >= 0) res = sn9c102_store_val(cd, attr, buf, len); return res;}static ssize_tsn9c102_store_red(struct device* cd, struct device_attribute *attr, const char* buf, size_t len){ ssize_t res = 0; u16 value; ssize_t count; value = sn9c102_strtou16(buf, len, &count); if (!count || value > 0x7f) return -EINVAL; if ((res = sn9c102_store_reg(cd, attr, "0x05", 4)) >= 0) res = sn9c102_store_val(cd, attr, buf, len); return res;}static ssize_t sn9c102_show_frame_header(struct device* cd, struct device_attribute *attr, char* buf){ struct sn9c102_device* cam; ssize_t count; cam = video_get_drvdata(container_of(cd, struct video_device, dev)); 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 DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, sn9c102_show_i2c_val, sn9c102_store_i2c_val);static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);static int sn9c102_create_sysfs(struct sn9c102_device* cam){ struct device *dev = &(cam->v4ldev->dev); int err = 0; if ((err = device_create_file(dev, &dev_attr_reg))) goto err_out; if ((err = device_create_file(dev, &dev_attr_val))) goto err_reg; if ((err = device_create_file(dev, &dev_attr_frame_header))) goto err_val; if (cam->sensor.sysfs_ops) { if ((err = device_create_file(dev, &dev_attr_i2c_reg))) goto err_frame_header; if ((err = device_create_file(dev, &dev_attr_i2c_val))) goto err_i2c_reg; } if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) { if ((err = device_create_file(dev, &dev_attr_green))) goto err_i2c_val; } else { if ((err = device_create_file(dev, &dev_attr_blue))) goto err_i2c_val; if ((err = device_create_file(dev, &dev_attr_red))) goto err_blue; } return 0;err_blue: device_remove_file(dev, &dev_attr_blue);err_i2c_val: if (cam->sensor.sysfs_ops) device_remove_file(dev, &dev_attr_i2c_val);err_i2c_reg: if (cam->sensor.sysfs_ops) device_remove_file(dev, &dev_attr_i2c_reg);err_frame_header: device_remove_file(dev, &dev_attr_frame_header);err_val: device_remove_file(dev, &dev_attr_val);err_reg: device_remove_file(dev, &dev_attr_reg);err_out: return err;}#endif /* CONFIG_VIDEO_ADV_DEBUG *//*****************************************************************************/static intsn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix){ int err = 0; if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X || pix->pixelformat == V4L2_PIX_FMT_JPEG) { switch (cam->bridge) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); break; } } else { switch (cam->bridge) { case BRIDGE_SN9C101: case BRIDGE_SN9C102: case BRIDGE_SN9C103: err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18); break; case BRIDGE_SN9C105: case BRIDGE_SN9C120: err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18); break; } } return err ? -EIO : 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -