我在编写camera应用程序的时候去调试V4L2_CID_HUE这个值时
queryctrl.id = V4L2_CID_HUE;
ret = ioctl(fd, VIDIOC_QUERY, &queryctrl); //ioctl若成功返回0,失败返回错误代码
if(ret < 0)
{
printf("%d not supported\n");
return ;
}
以上这段函数总是提示9963779 not supported,但是在UVC描述符里面设备明明回复是支持hue的,就感觉很奇怪,于是打开内核调试insmod uvcvideo.ko [param1=value1 param2=value2 ...]
insmod uvcvideo.ko trace=4
说明:
module_param(name, type, perm);中的name既是用户看到的参数名,又是模块内接受参数的变量
module_param_named(name, varible, type, perm);中的name是外部可见的参数名,varible是源文件内部的全局变量
因为在uvc_driver.c中module_param_named(trace, uvc_trace_param, uint, S_IRUGO|S_IWUSR);
为了使uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, " "removing it.\n", entity->id, blacklist[i].index);能够打印出来
#define uvc_trace(flag, msg...) \
do { \
if (uvc_trace_param & flag) \
printk(KERN_DEBUG "uvcvideo: " msg); \
} while (0)
在加载模块的时候必须使uvc_trace_param=UVC_TRACE_CONTROL,对于模块外部来说就是trace=4以便使里面的printk能够正常打印
打开了内核调试接口后面,可以通过cat /proc/kmsg来查看内核打印消息,内容很长很长,但是更方便的是通过dmesg命令可以查看内核的打印消息。
直接dmesg
输出如下:
上面的信息提示,虽然UVC回报描述符里面有hue,但是在将描述符添加到内核相关结构体的时候重新判断这些功能是否可行,不可行的话给屏蔽掉了
具体的函数在uvc_ctrl.c文件的uvc_ctrl_prune_entity的函数中实现。
进一步去分析uvc_ctrl_prune_entity
static void uvc_ctrl_prune_entity(struct uvc_device *dev, struct uvc_entity *entity)
{
static const struct {
struct usb_device_id id;
u8 index;
} blacklist[] = {
{ { USB_DEVICE(0x1c4f, 0x3000) }, 6 }, /* WB Temperature */
{ { USB_DEVICE(0x5986, 0x0241) }, 2 }, /* Hue */
};
u8 *controls;
unsigned int size;
unsigned int i;
if (UVC_ENTITY_TYPE(entity) != UVC_VC_PROCESSING_UNIT)
return;
controls = entity->processing.bmControls;
size = entity->processing.bControlSize;
for (i = 0; i < ARRAY_SIZE(blacklist); ++i) {
if (!usb_match_id(dev->intf, &blacklist[i].id))
continue;
if (blacklist[i].index >= 8 * size || !uvc_test_bit(controls, blacklist[i].index))
continue;
uvc_trace(UVC_TRACE_CONTROL, "%u/%u control is black listed, " "removing it.\n", entity->id, blacklist[i].index);
uvc_clear_bit(controls, blacklist[i].index);
}
}
跟踪usb_match_id(dev->intf, &blacklist[i].id))
——>if (usb_match_one_id(interface, id))
return id;
——>if (!usb_match_device(dev, id))
return 0;
return 1;
而在usb_match_device函数中我发现由于id传过来的match_flags=USB_DEVICE_ID_MATCH_DEVICE,所以与里面的每个if都不匹配,最终return 1;
这样一层层往上发现usb_match_id 最终竟然返回1,那么在uvc_ctrl_prune_entity函数中总是会执行uvc_clear_bit(controls, blacklist[i].index);,这样Hue就被剔除在entity之外了
这是不是UVC中的一个bug呢?