我是靠谱客的博主 朴素酸奶,最近开发中收集的这篇文章主要介绍linux内核调试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

我在编写camera应用程序的时候去调试V4L2_CID_HUE这个值时

queryctrl.id = V4L2_CID_HUE;

ret = ioctl(fd, VIDIOC_QUERY, &queryctrl);   //ioctl若成功返回0,失败返回错误代码

if(ret < 0)

{

    printf("%d not supportedn");

    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呢

最后

以上就是朴素酸奶为你收集整理的linux内核调试的全部内容,希望文章能够帮你解决linux内核调试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部