8.初始化uvc控制
8.1 重要结构体
struct uvc_control { //uvc控制 struct uvc_entity *entity; //uvc实体 struct uvc_control_info info; //uvc控制信息 __u8 index; //索引值 __u8 dirty:1, loaded:1, modified:1, cached:1, initialized:1; //初始化标志 __u8 *uvc_data; //uvc控制数据 };
int uvc_ctrl_init_device(struct uvc_device *dev) { struct uvc_entity *entity; unsigned int i; /* Walk the entities list and instantiate controls */ list_for_each_entry(entity, &dev->entities, list) { //遍历uvc设备实体entities链表 struct uvc_control *ctrl; //uvc控制 unsigned int bControlSize = 0, ncontrols = 0; __u8 *bmControls = NULL; if (UVC_ENTITY_TYPE(entity) == UVC_VC_EXTENSION_UNIT) { //扩展Unit bmControls = entity->extension.bmControls; //控制位图 bControlSize = entity->extension.bControlSize; //控制位域大小 } else if (UVC_ENTITY_TYPE(entity) == UVC_VC_PROCESSING_UNIT) { //处理Unit bmControls = entity->processing.bmControls; //控制位图 bControlSize = entity->processing.bControlSize; //控制位域大小 } else if (UVC_ENTITY_TYPE(entity) == UVC_ITT_CAMERA) { //输入Terminal Camera bmControls = entity->camera.bmControls; //控制位图 bControlSize = entity->camera.bControlSize; //控制位域大小 } /* Remove bogus/blacklisted controls 移除假的/黑名单控制组件*/ uvc_ctrl_prune_entity(dev, entity); /* Count supported controls and allocate the controls array */ for (i = 0; i < bControlSize; ++i) ncontrols += hweight8(bmControls[i]); //统计控制组件个数 if (ncontrols == 0) continue; entity->controls = kzalloc(ncontrols * sizeof(*ctrl),GFP_KERNEL); //分配ncontrols个uvc控制内存 if (entity->controls == NULL) return -ENOMEM; entity->ncontrols = ncontrols; //设置uvc控制个数 /* Initialize all supported controls */ ctrl = entity->controls; //指向uvc控制数组 for (i = 0; i < bControlSize * 8; ++i) { if (uvc_test_bit(bmControls, i) == 0) //跳过控制位域没设置1的 continue; ctrl->entity = entity; //捆绑uvc实体和uvc控制 ctrl->index = i; //设置控制位域索引 uvc_ctrl_init_ctrl(dev, ctrl); //9初始化uvc控件 ctrl++; //uvc控制 指向下一个uvc控制数组项 } } return 0; }9初始化uvc控件
9.1 相关结构体
9.1.1 uvc控制信息
struct uvc_control_info { //uvc控制信息 struct list_head mappings; //uvc控制位图链表头 __u8 entity[16]; __u8 index; /* Bit index in bmControls */ __u8 selector; __u16 size; __u32 flags; };9.1.2 uvc控制位图
struct uvc_control_mapping { //uvc控制位图 struct list_head list; //链表 struct uvc_control_info *ctrl; //uvc控制信息 __u32 id; __u8 name[32]; __u8 entity[16]; __u8 selector; __u8 size; __u8 offset; enum v4l2_ctrl_type v4l2_type; //v4l2控制类型 __u32 data_type; struct uvc_menu_info *menu_info; //uvc菜单信息 __u32 menu_count; //uvc菜单个数 __s32 (*get) (struct uvc_control_mapping *mapping, __u8 query,const __u8 *data); void (*set) (struct uvc_control_mapping *mapping, __s32 value,__u8 *data); };
static void uvc_ctrl_init_ctrl(struct uvc_device *dev, struct uvc_control *ctrl) { const struct uvc_control_info *info = uvc_ctrls; //指向全局静态uvc控制信息数组 const struct uvc_control_info *iend = info + ARRAY_SIZE(uvc_ctrls); //指向数组末端 const struct uvc_control_mapping *mapping = uvc_ctrl_mappings; //指向全局静态uvc控制位图数组 const struct uvc_control_mapping *mend = mapping + ARRAY_SIZE(uvc_ctrl_mappings); //指向数组末端 if (UVC_ENTITY_TYPE(ctrl->entity) == UVC_VC_EXTENSION_UNIT) //ctrl->entity->type为扩展Unit(延后扩展Unit的初始化到当它第一次使用) return; for (; info < iend; ++info) { //遍历整个uvc控制信息数据 if (uvc_entity_match_guid(ctrl->entity, info->entity) && ctrl->index == info->index) { //匹配条件 uvc_ctrl_add_info(dev, ctrl, info); //添加uvc控制信息 break; } } if (!ctrl->initialized) //已经给初始化 return; for (; mapping < mend; ++mapping) { //遍历整个uvc控制位图数组 if (uvc_entity_match_guid(ctrl->entity, mapping->entity) && ctrl->info.selector == mapping->selector) //匹配条件 __uvc_ctrl_add_mapping(dev, ctrl, mapping); //添加控制位图 } }
9.2.1 全局静态uvc控制信息数组uvc-ctrls
static struct uvc_control_info uvc_ctrls[] = { { //背光控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BRIGHTNESS_CONTROL, .index = 0, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //对比度控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_CONTRAST_CONTROL, .index = 1, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //色度控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_HUE_CONTROL, .index = 2, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { //饱和度控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_SATURATION_CONTROL, .index = 3, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //锐度控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_SHARPNESS_CONTROL, .index = 4, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //gamma设置 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_GAMMA_CONTROL, .index = 5, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //白平衡温度控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, .index = 6, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { //白平衡组件 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, .index = 7, .size = 4, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { //背光补偿 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, .index = 8, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //增益 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_GAIN_CONTROL, .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //电源线频率 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, .index = 10, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { //自动色度调节 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_HUE_AUTO_CONTROL, .index = 11, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { //白平衡色温自动调节 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, .index = 12, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { //白平衡自动调节 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, .index = 13, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { //数字多功能控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_DIGITAL_MULTIPLIER_CONTROL, .index = 14, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //数字多功能限制控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL, .index = 15, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { //模拟视频标准控制 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL, .index = 16, .size = 1, .flags = UVC_CONTROL_GET_CUR, }, { //模拟视频锁存状态 .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_ANALOG_LOCK_STATUS_CONTROL, .index = 17, .size = 1, .flags = UVC_CONTROL_GET_CUR, }, { //扫描模式 .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_SCANNING_MODE_CONTROL, .index = 0, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_RESTORE, }, { //。。。 .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_AE_MODE_CONTROL, .index = 1, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_GET_DEF | UVC_CONTROL_GET_RES| UVC_CONTROL_RESTORE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_AE_PRIORITY_CONTROL, .index = 2, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_RESTORE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, .index = 3, .size = 4, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL, .index = 4, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_RESTORE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, .index = 5, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_RELATIVE_CONTROL, .index = 6, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES| UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, .index = 7, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_IRIS_RELATIVE_CONTROL, .index = 8, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, .index = 9, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, .index = 10, .size = 3, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES| UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, .index = 11, .size = 8, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_RELATIVE_CONTROL, .index = 12, .size = 4, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN| UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES| UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ROLL_ABSOLUTE_CONTROL, .index = 13, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_RANGE| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ROLL_RELATIVE_CONTROL, .index = 14, .size = 2, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF | UVC_CONTROL_AUTO_UPDATE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_AUTO_CONTROL, .index = 17, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_GET_DEF | UVC_CONTROL_RESTORE, }, { .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PRIVACY_CONTROL, .index = 18, .size = 1, .flags = UVC_CONTROL_SET_CUR | UVC_CONTROL_GET_CUR| UVC_CONTROL_RESTORE | UVC_CONTROL_AUTO_UPDATE, }, };
9.2.2 全局静态uvc控制位图数组(uvc_ctrl_mappings)
static struct uvc_control_mapping uvc_ctrl_mappings[] = { { .id = V4L2_CID_BRIGHTNESS, .name = "Brightness", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BRIGHTNESS_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, }, { .id = V4L2_CID_CONTRAST, .name = "Contrast", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_CONTRAST_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_HUE, .name = "Hue", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_HUE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, }, { .id = V4L2_CID_SATURATION, .name = "Saturation", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_SATURATION_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_SHARPNESS, .name = "Sharpness", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_SHARPNESS_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_GAMMA, .name = "Gamma", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_GAMMA_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_BACKLIGHT_COMPENSATION, .name = "Backlight Compensation", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_BACKLIGHT_COMPENSATION_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_GAIN, .name = "Gain", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_GAIN_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_POWER_LINE_FREQUENCY, .name = "Power Line Frequency", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_POWER_LINE_FREQUENCY_CONTROL, .size = 2, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_ENUM, .menu_info = power_line_frequency_controls, .menu_count = ARRAY_SIZE(power_line_frequency_controls), }, { .id = V4L2_CID_HUE_AUTO, .name = "Hue, Auto", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_HUE_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_EXPOSURE_AUTO, .name = "Exposure, Auto", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_AE_MODE_CONTROL, .size = 4, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_MENU, .data_type = UVC_CTRL_DATA_TYPE_BITMASK, .menu_info = exposure_auto_controls, .menu_count = ARRAY_SIZE(exposure_auto_controls), }, { .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, .name = "Exposure, Auto Priority", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_AE_PRIORITY_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_EXPOSURE_ABSOLUTE, .name = "Exposure (Absolute)", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL, .size = 32, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_AUTO_WHITE_BALANCE, .name = "White Balance Temperature, Auto", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_WHITE_BALANCE_TEMPERATURE, .name = "White Balance Temperature", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_AUTO_WHITE_BALANCE, .name = "White Balance Component, Auto", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_BLUE_BALANCE, .name = "White Balance Blue Component", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, }, { .id = V4L2_CID_RED_BALANCE, .name = "White Balance Red Component", .entity = UVC_GUID_UVC_PROCESSING, .selector = UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL, .size = 16, .offset = 16, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, }, { .id = V4L2_CID_FOCUS_ABSOLUTE, .name = "Focus (absolute)", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_ABSOLUTE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_FOCUS_AUTO, .name = "Focus, Auto", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_FOCUS_AUTO_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, { .id = V4L2_CID_IRIS_ABSOLUTE, .name = "Iris, Absolute", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_IRIS_ABSOLUTE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_IRIS_RELATIVE, .name = "Iris, Relative", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_IRIS_RELATIVE_CONTROL, .size = 8, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, }, { .id = V4L2_CID_ZOOM_ABSOLUTE, .name = "Zoom, Absolute", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ZOOM_ABSOLUTE_CONTROL, .size = 16, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_ZOOM_CONTINUOUS, .name = "Zoom, Continuous", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_ZOOM_RELATIVE_CONTROL, .size = 0, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, .get = uvc_ctrl_get_zoom, .set = uvc_ctrl_set_zoom, }, { .id = V4L2_CID_PAN_ABSOLUTE, .name = "Pan (Absolute)", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, .size = 32, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_TILT_ABSOLUTE, .name = "Tilt (Absolute)", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PANTILT_ABSOLUTE_CONTROL, .size = 32, .offset = 32, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_UNSIGNED, }, { .id = V4L2_CID_PRIVACY, .name = "Privacy", .entity = UVC_GUID_UVC_CAMERA, .selector = UVC_CT_PRIVACY_CONTROL, .size = 1, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_BOOLEAN, .data_type = UVC_CTRL_DATA_TYPE_BOOLEAN, }, };
9.2.3 添加uvc控制信息
static int uvc_ctrl_add_info(struct uvc_device *dev, struct uvc_control *ctrl,const struct uvc_control_info *info) { int ret = 0; memcpy(&ctrl->info, info, sizeof(*info)); //初始化uvc控制的uvc控制信息对象 INIT_LIST_HEAD(&ctrl->info.mappings); //初始化uvc控制信息的uvc链表头 /* Allocate an array to save control values (cur, def, max, etc.) */ ctrl->uvc_data = kzalloc(ctrl->info.size * UVC_CTRL_DATA_LAST + 1,GFP_KERNEL); //分配uvc控制数据内存 if (ctrl->uvc_data == NULL) { ret = -ENOMEM; goto done; } ctrl->initialized = 1; //设置uvc控制初始化标准 uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s entity %u\n", ctrl->info.entity, ctrl->info.selector,dev->udev->devpath, ctrl->entity->id); done: if (ret < 0) kfree(ctrl->uvc_data); return ret; }
9.2.4 添加uvc位图
static int __uvc_ctrl_add_mapping(struct uvc_device *dev,struct uvc_control *ctrl, const struct uvc_control_mapping *mapping) { struct uvc_control_mapping *map; unsigned int size; map = kmemdup(mapping, sizeof(*mapping), GFP_KERNEL); //分配uvc控制位图内存 if (map == NULL) return -ENOMEM; size = sizeof(*mapping->menu_info) * mapping->menu_count; //计算uvc菜单数组占用空间 map->menu_info = kmemdup(mapping->menu_info, size, GFP_KERNEL); //分配uvc菜单数组内存 if (map->menu_info == NULL) { kfree(map); return -ENOMEM; } if (map->get == NULL) map->get = uvc_get_le_value; //设置默认获取方法 if (map->set == NULL) map->set = uvc_set_le_value; //设置默认设置方法 map->ctrl = &ctrl->info; //捆绑uvc控制信息和uvc控制信息位图 list_add_tail(&map->list, &ctrl->info.mappings); //添加uvc控制位图到uvc控制信息的位图链表 uvc_trace(UVC_TRACE_CONTROL,"Adding mapping '%s' to control %pUl/%u.\n",map->name, ctrl->info.entity, ctrl->info.selector); return 0; }