uvc协议cmos属性无法同步问题

最近做了一个项目通过uvc协议控制按键实现截图功能,供货商修改了uvcvideo属性的saturation(饱和度),当按键按下时修改了cmos侧的saturation为1,应用检测这个状态,当检测到1时,截一张图,并把saturation值设为0。实际使用,在windows上用amcap软件测试是没有问题的,在linux下使用guvcview软件测试时发现,按键按下后,软件并不能读到1,切换到windows,再切换回ubuntu时状态值变为了1,按键按下后才切换到windows的由此判断按键按下后saturation是上报到cmos侧了,但是ubuntu并不能读到这个值,使用开发板是相同的问题,使用v4l2-ctl 也不能读到1。分析后明白应该是驱动里面为了usb减少总线占用,使用了本地映射的方式,通过v4l2-ctl读取值时是直接读取的本地映射的值,并不是通过ioctrl从设备侧读到的真实的值。通过分析源码发现果然这是这样,附源码:

int uvc_ctrl_get(struct uvc_video_chain *chain,
struct v4l2_ext_control *xctrl)
{
	struct uvc_control *ctrl;
	struct uvc_control_mapping *mapping;
	struct uvc_menu_info *menu;
	unsigned int i;
	int ret;
	
	ctrl = uvc_find_control(chain, xctrl->id, &mapping);
	if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
		return -EINVAL;
	
	if (!ctrl->loaded) {
		ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
				chain->dev->intfnum, ctrl->info.selector,
				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
				ctrl->info.size);
		if (ret < 0)
			return ret;
		ctrl->loaded = 1;
	}

	xctrl->value = mapping->get(mapping, UVC_GET_CUR,
		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));
	
	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
		menu = mapping->menu_info;
		for (i = 0; i < mapping->menu_count; ++i, ++menu) {
			if (menu->value == xctrl->value) {
				xctrl->value = i;
				break;
			}
		}
	}
	return 0;
}

通过!ctrl->loaded判断,如果是第一次加载,就通过ioctrl从设备测读取,后面就不再执行这一段代码,也就是不通过ioctrl从设备侧读属性值了。
修改代码如下:

int uvc_ctrl_get(struct uvc_video_chain *chain, struct v4l2_ext_control *xctrl)
{
	struct uvc_control *ctrl;
	struct uvc_control_mapping *mapping;
	struct uvc_menu_info *menu;
	unsigned int i;
	int ret;

	ctrl = uvc_find_control(chain, xctrl->id, &mapping);
	if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_GET_CUR) == 0)
		return -EINVAL;

	// 移除loaded状态检查,每次直接查询
	ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, ctrl->entity->id,
				chain->dev->intfnum, ctrl->info.selector,
				uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
				ctrl->info.size);
	if (ret < 0)
		return ret;

	// 保留原逻辑的其余部分
	xctrl->value = mapping->get(mapping, UVC_GET_CUR,
		uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT));

	if (mapping->v4l2_type == V4L2_CTRL_TYPE_MENU) {
		menu = mapping->menu_info;
		for (i = 0; i < mapping->menu_count; ++i, ++menu) {
			if (menu->value == xctrl->value) {
				xctrl->value = i;
				break;
			}
		}
	}

	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值