📄 et61x251_core.c
字号:
}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 et61x251_start_transfer(struct et61x251_device* cam){ struct usb_device *udev = cam->usbdev; struct urb* urb; const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, 864, 896, 920, 956, 980, 1000, 1022}; const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; s8 i, j; int err = 0; for (i = 0; i < ET61X251_URBS; i++) { cam->transfer_buffer[i] = kzalloc(ET61X251_ISO_PACKETS * psz, GFP_KERNEL); if (!cam->transfer_buffer[i]) { err = -ENOMEM; DBG(1, "Not enough memory"); goto free_buffers; } } for (i = 0; i < ET61X251_URBS; i++) { urb = usb_alloc_urb(ET61X251_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 = ET61X251_ISO_PACKETS; urb->complete = et61x251_urb_complete; urb->transfer_buffer = cam->transfer_buffer[i]; urb->transfer_buffer_length = psz * ET61X251_ISO_PACKETS; urb->interval = 1; for (j = 0; j < ET61X251_ISO_PACKETS; j++) { urb->iso_frame_desc[j].offset = psz * j; urb->iso_frame_desc[j].length = psz; } } err = et61x251_write_reg(cam, 0x01, 0x03); err = et61x251_write_reg(cam, 0x00, 0x03); err = et61x251_write_reg(cam, 0x08, 0x03); if (err) { err = -EIO; DBG(1, "I/O hardware error"); goto free_urbs; } err = usb_set_interface(udev, 0, ET61X251_ALTERNATE_SETTING); if (err) { DBG(1, "usb_set_interface() failed"); goto free_urbs; } cam->frame_current = NULL; for (i = 0; i < ET61X251_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 < ET61X251_URBS) && cam->urb[i]; i++) usb_free_urb(cam->urb[i]);free_buffers: for (i = 0; (i < ET61X251_URBS) && cam->transfer_buffer[i]; i++) kfree(cam->transfer_buffer[i]); return err;}static int et61x251_stop_transfer(struct et61x251_device* cam){ struct usb_device *udev = cam->usbdev; s8 i; int err = 0; if (cam->state & DEV_DISCONNECTED) return 0; for (i = ET61X251_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 int et61x251_stream_interrupt(struct et61x251_device* cam){ long timeout; cam->stream = STREAM_INTERRUPT; timeout = wait_event_timeout(cam->wait_stream, (cam->stream == STREAM_OFF) || (cam->state & DEV_DISCONNECTED), ET61X251_URB_TIMEOUT); if (cam->state & DEV_DISCONNECTED) return -ENODEV; else if (cam->stream != STREAM_OFF) { cam->state |= DEV_MISCONFIGURED; DBG(1, "URB timeout reached. The camera is misconfigured. To " "use it, close and open /dev/video%d again.", cam->v4ldev->minor); return -EIO; } return 0;}/*****************************************************************************/#ifdef CONFIG_VIDEO_ADV_DEBUGstatic u8 et61x251_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 et61x251_show_reg(struct class_device* cd, char* buf){ struct et61x251_device* cam; ssize_t count; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.reg); mutex_unlock(&et61x251_sysfs_lock); return count;}static ssize_tet61x251_store_reg(struct class_device* cd, const char* buf, size_t len){ struct et61x251_device* cam; u8 index; ssize_t count; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } index = et61x251_strtou8(buf, len, &count); if (index > 0x8e || !count) { mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } cam->sysfs.reg = index; DBG(2, "Moved ET61X[12]51 register index to 0x%02X", cam->sysfs.reg); DBG(3, "Written bytes: %zd", count); mutex_unlock(&et61x251_sysfs_lock); return count;}static ssize_t et61x251_show_val(struct class_device* cd, char* buf){ struct et61x251_device* cam; ssize_t count; int val; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } if ((val = et61x251_read_reg(cam, cam->sysfs.reg)) < 0) { mutex_unlock(&et61x251_sysfs_lock); return -EIO; } count = sprintf(buf, "%d\n", val); DBG(3, "Read bytes: %zd", count); mutex_unlock(&et61x251_sysfs_lock); return count;}static ssize_tet61x251_store_val(struct class_device* cd, const char* buf, size_t len){ struct et61x251_device* cam; u8 value; ssize_t count; int err; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } value = et61x251_strtou8(buf, len, &count); if (!count) { mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } err = et61x251_write_reg(cam, value, cam->sysfs.reg); if (err) { mutex_unlock(&et61x251_sysfs_lock); return -EIO; } DBG(2, "Written ET61X[12]51 reg. 0x%02X, val. 0x%02X", cam->sysfs.reg, value); DBG(3, "Written bytes: %zd", count); mutex_unlock(&et61x251_sysfs_lock); return count;}static ssize_t et61x251_show_i2c_reg(struct class_device* cd, char* buf){ struct et61x251_device* cam; ssize_t count; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg); DBG(3, "Read bytes: %zd", count); mutex_unlock(&et61x251_sysfs_lock); return count;}static ssize_tet61x251_store_i2c_reg(struct class_device* cd, const char* buf, size_t len){ struct et61x251_device* cam; u8 index; ssize_t count; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } index = et61x251_strtou8(buf, len, &count); if (!count) { mutex_unlock(&et61x251_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(&et61x251_sysfs_lock); return count;}static ssize_t et61x251_show_i2c_val(struct class_device* cd, char* buf){ struct et61x251_device* cam; ssize_t count; int val; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { mutex_unlock(&et61x251_sysfs_lock); return -ENOSYS; } if ((val = et61x251_i2c_read(cam, cam->sysfs.i2c_reg)) < 0) { mutex_unlock(&et61x251_sysfs_lock); return -EIO; } count = sprintf(buf, "%d\n", val); DBG(3, "Read bytes: %zd", count); mutex_unlock(&et61x251_sysfs_lock); return count;}static ssize_tet61x251_store_i2c_val(struct class_device* cd, const char* buf, size_t len){ struct et61x251_device* cam; u8 value; ssize_t count; int err; if (mutex_lock_interruptible(&et61x251_sysfs_lock)) return -ERESTARTSYS; cam = video_get_drvdata(to_video_device(cd)); if (!cam) { mutex_unlock(&et61x251_sysfs_lock); return -ENODEV; } if (!(cam->sensor.sysfs_ops & ET61X251_I2C_READ)) { mutex_unlock(&et61x251_sysfs_lock); return -ENOSYS; } value = et61x251_strtou8(buf, len, &count); if (!count) { mutex_unlock(&et61x251_sysfs_lock); return -EINVAL; } err = et61x251_i2c_write(cam, cam->sysfs.i2c_reg, value); if (err) { mutex_unlock(&et61x251_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(&et61x251_sysfs_lock); return count;}static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, et61x251_show_reg, et61x251_store_reg);static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR, et61x251_show_val, et61x251_store_val);static CLASS_DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR, et61x251_show_i2c_reg, et61x251_store_i2c_reg);static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, et61x251_show_i2c_val, et61x251_store_i2c_val);static void et61x251_create_sysfs(struct et61x251_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); 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); }}#endif /* CONFIG_VIDEO_ADV_DEBUG *//*****************************************************************************/static intet61x251_set_pix_format(struct et61x251_device* cam, struct v4l2_pix_format* pix){ int r, err = 0; if ((r = et61x251_read_reg(cam, 0x12)) < 0) err += r; if (pix->pixelformat == V4L2_PIX_FMT_ET61X251) err += et61x251_write_reg(cam, r & 0xfd, 0x12); else err += et61x251_write_reg(cam, r | 0x02, 0x12); return err ? -EIO : 0;}static intet61x251_set_compression(struct et61x251_device* cam, struct v4l2_jpegcompression* compression){ int r, err = 0; if ((r = et61x251_read_reg(cam, 0x12)) < 0) err += r; if (compression->quality == 0) err += et61x251_write_reg(cam, r & 0xfb, 0x12); else err += et61x251_write_reg(cam, r | 0x04, 0x12); return err ? -EIO : 0;}static int et61x251_set_scale(struct et61x251_device* cam, u8 scale){ int r = 0, err = 0; r = et61x251_read_reg(cam, 0x12); if (r < 0) err += r; if (scale == 1) err += et61x251_write_reg(cam, r & ~0x01, 0x12); else if (scale == 2) err += et61x251_write_reg(cam, r | 0x01, 0x12); if (err) return -EIO; PDBGG("Scaling factor: %u", scale); return 0;}static intet61x251_set_crop(struct et61x251_device* cam, struct v4l2_rect* rect){ struct et61x251_sensor* s = &cam->sensor; u16 fmw_sx = (u16)(rect->left - s->cropcap.bounds.left + s->active_pixel.left), fmw_sy = (u16)(rect->top - s->cropcap.bounds.top + s->active_pixel.top),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -