📄 uvc_v4l2.c
字号:
return ret;}static int uvc_v4l2_release(struct inode *inode, struct file *file){ struct video_device *vdev = video_devdata(file); struct uvc_video_device *video = video_get_drvdata(vdev); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n"); /* Only free resources if this is a privileged handle. */ if (uvc_has_privileges(handle)) { uvc_video_enable(video, 0); mutex_lock(&video->queue.mutex); if (uvc_free_buffers(&video->queue) < 0) uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " "free buffers.\n"); mutex_unlock(&video->queue.mutex); } /* Release the file handle. */ uvc_dismiss_privileges(handle); kfree(handle); file->private_data = NULL; kref_put(&video->dev->kref, uvc_delete); return 0;}//chip,sensor,i2c read/writeint vmuvc_read_chip(struct uvc_video_device *video, __u16 a, __u16* v){ int result = 0; __u8 Buffer[ 4 ]; __u16 wLength; if(bExtensionUnit == 0) { return 0x800927; } Buffer[ 0 ] = 0x00; Buffer[ 1 ] = (__u8)( a & 0x00FF); Buffer[ 2 ] = (__u8)( a >> 8 ); Buffer[ 3 ] = 0; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_SET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if(result >= 0) { Buffer[ 0 ] = 0x00; Buffer[ 1 ] = (__u8)( a & 0x00FF); Buffer[ 2 ] = (__u8)( a >> 8 ); Buffer[ 3 ] = 0; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_GET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if (result >= 0) { *v = Buffer[ 3 ]; } else { *v = 0x0000; uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_chip\n"); } } else { *v = 0x0000; uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_chip\n"); } return result;}int vmuvc_write_chip(struct uvc_video_device *video, __u16 a , __u16 v){ int result = 0; __u8 Buffer[ 4 ]; __u16 wLength; if(bExtensionUnit == 0) { return 0x800927; } Buffer[ 0 ] = 0x20; Buffer[ 1 ] = (__u8)( a & 0x00FF); Buffer[ 2 ] = (__u8)( a >> 8 ); Buffer[ 3 ] = v; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_SET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if(result < 0) { uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_chip\n"); } return result;}int vmuvc_read_sensor(struct uvc_video_device *video, __u16 a, __u16* v){ int result = 0; __u8 Buffer[ 4 ]; __u16 wLength; if(bExtensionUnit == 0) { return 0x800927; } //address is byte, value is word Buffer[ 0 ] = 0x11; Buffer[ 1 ] = (__u8)( a ); Buffer[ 2 ] = 0; Buffer[ 3 ] = 0; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_SET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if(result >= 0) { Buffer[ 0 ] = 0x11; Buffer[ 1 ] = (__u8)( a ); Buffer[ 2 ] = 0; Buffer[ 3 ] = 0; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_GET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if ( result >= 0 ) { *v = (Buffer[ 3 ] << 8) | Buffer[2]; } else { *v = 0x0000; uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_sensor\n"); } } else { *v = 0x0000; uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_sensor\n"); } return result;}int vmuvc_write_sensor(struct uvc_video_device *video, __u16 a , __u16 v){ int result = 0; __u8 Buffer[ 4 ]; __u16 wLength; if(bExtensionUnit == 0) { return 0x800927; } //address is byte, value is word Buffer[ 0 ] = 0x31; Buffer[ 1 ] = (__u8)( a ); Buffer[ 2 ] = (__u8)( v & 0x00FF); Buffer[ 3 ] = (__u8)( v >> 8 ); wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_SET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if(result < 0) { uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_write_sensor\n"); } return result;}int vmuvc_read_i2c(struct uvc_video_device *video, __u8 ia, __u16 a, __u16* v){ int result = 0; __u8 Buffer[ 4 ]; __u16 wLength; if(bExtensionUnit == 0) { return 0x800927; } //address is byte, value is word Buffer[ 0 ] = ia & 0xFE; Buffer[ 1 ] = (__u8)( a ); Buffer[ 2 ] = (__u8)( a & 0x00FF); Buffer[ 3 ] = 0; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_SET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if(result >= 0) { Buffer[ 0 ] = ia & 0xFE; Buffer[ 1 ] = (__u8)( a ); Buffer[ 2 ] = (__u8)( a & 0x00FF); Buffer[ 3 ] = 0; wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_GET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if ( result < 0 ) { *v = 0x0000; uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_i2c\n"); } else { *v = Buffer[ 3 ]; } } else { *v = 0x0000; uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_read_i2c\n"); } return result;}int vmuvc_write_i2c(struct uvc_video_device *video, __u8 ia, __u16 a, __u16 v){ int result = 0; __u8 Buffer[ 4 ]; __u16 wLength; if(bExtensionUnit == 0) { return 0x800927; } //address is byte, value is word Buffer[ 0 ] = ia | 0x01; Buffer[ 1 ] = (__u8)( a ); Buffer[ 2 ] = (__u8)( a & 0x00FF); Buffer[ 3 ] = (__u8)( v ); wLength = sizeof( Buffer ); result = uvc_query_ctrl(video->dev, USBVC_SET_CUR, bExtUnitId, video->dev->intfnum, EU_REG_CONTROL, Buffer, wLength); if(result < 0) { uvc_trace(UVC_TRACE_CALLS, "[wlq-uVc] vmuvc_write_i2c\n"); } return result;}static int uvc_v4l2_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg){ struct video_device *vdev = video_devdata(file); struct uvc_video_device *video = video_get_drvdata(vdev); struct uvc_fh *handle = (struct uvc_fh *)file->private_data; int ret = 0; if (uvc_trace_param & UVC_TRACE_IOCTL) v4l_printk_ioctl(cmd); switch (cmd) { /* Query capabilities */ case VIDIOC_QUERYCAP: { struct v4l2_capability *cap = arg; memset(cap, 0, sizeof *cap); strncpy(cap->driver, "uvcvideo", sizeof cap->driver);#if 0 //[wlq] if (video->dev->udev->descriptor.idProduct) //[wlq] strncpy(cap->card, video->dev->udev->product, sizeof cap->card); else strncpy(cap->card, "USB Video Class device", sizeof cap->card);#endif strncpy(cap->bus_info, video->dev->udev->bus->bus_name, sizeof cap->bus_info); cap->version = DRIVER_VERSION_NUMBER; cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; } break; /* Get, Set & Query control */ case VIDIOC_QUERYCTRL: return uvc_query_v4l2_ctrl(video, (struct v4l2_queryctrl*)arg); case VIDIOC_G_CTRL: // [wlq] { struct v4l2_control *ctrl = (struct v4l2_control*)arg; struct v4l2_ext_control xctrl;#if 0 __u16 tValue = 0; printk(KERN_INFO "bType=%02x,addr=%04x,value=%04x\n",ctrl->bType,ctrl->uAddress,ctrl->uValue); if(ctrl->bType > 0) { if(((ctrl->bType & 0xF0) >> 4) == 1) { if((ctrl->bType & 0x0F) == 1) { vmuvc_read_chip(video, ctrl->uAddress, &tValue); ctrl->uValue = tValue; } else if((ctrl->bType & 0x0F) == 2) { vmuvc_write_chip(video, ctrl->uAddress, ctrl->uValue); } } else if(((ctrl->bType & 0xF0) >> 4) == 2) { if((ctrl->bType & 0x0F) == 1) { vmuvc_read_sensor(video, ctrl->uAddress, &tValue); ctrl->uValue = tValue; } else if((ctrl->bType & 0x0F) == 2) { vmuvc_write_sensor(video, ctrl->uAddress, ctrl->uValue); } } else if(((ctrl->bType & 0xF0) >> 4) == 3) { if((ctrl->bType & 0x0F) == 1) { vmuvc_read_i2c(video, 0, ctrl->uAddress, &tValue); ctrl->uValue = tValue; } else if((ctrl->bType & 0x0F) == 2) { vmuvc_write_i2c(video, 0, ctrl->uAddress, ctrl->uValue); } } //add extension unit control here. return 1; }#endif if( 0) { } else { memset(&xctrl, 0, sizeof xctrl); xctrl.id = ctrl->id; uvc_ctrl_begin(video); ret = uvc_ctrl_get(video, &xctrl); uvc_ctrl_rollback(video); if (ret >= 0) { ctrl->value = xctrl.value; } } } break; case VIDIOC_S_CTRL: { struct v4l2_control *ctrl = (struct v4l2_control*)arg; struct v4l2_ext_control xctrl; memset(&xctrl, 0, sizeof xctrl); xctrl.id = ctrl->id; xctrl.value = ctrl->value; uvc_ctrl_begin(video); ret = uvc_ctrl_set(video, &xctrl); if (ret < 0) { uvc_ctrl_rollback(video); return ret; } ret = uvc_ctrl_commit(video); } break; case VIDIOC_QUERYMENU: return uvc_v4l2_query_menu(video, (struct v4l2_querymenu*)arg); case VIDIOC_G_EXT_CTRLS: { struct v4l2_ext_controls *ctrls = (struct v4l2_ext_controls*)arg; struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; uvc_ctrl_begin(video); for (i = 0; i < ctrls->count; ++ctrl, ++i) { ret = uvc_ctrl_get(video, ctrl); if (ret < 0) { uvc_ctrl_rollback(video); ctrls->error_idx = i; return ret; } } ctrls->error_idx = 0; ret = uvc_ctrl_rollback(video); } break; case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: { struct v4l2_ext_controls *ctrls = (struct v4l2_ext_controls*)arg; struct v4l2_ext_control *ctrl = ctrls->controls; unsigned int i; ret = uvc_ctrl_begin(video); if (ret < 0) return ret; for (i = 0; i < ctrls->count; ++ctrl, ++i) { ret = uvc_ctrl_set(video, ctrl); if (ret < 0) { uvc_ctrl_rollback(video); ctrls->error_idx = i; return ret; } } ctrls->error_idx = 0; if (cmd == VIDIOC_S_EXT_CTRLS) ret = uvc_ctrl_commit(video); else ret = uvc_ctrl_rollback(video); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -