第2课第1.1.6节 usb摄像头驱动之分析描述符

设备描述符(通用)


USB设备描述符(白色的是每一个USB设备必须支持的,灰色的是UVC规范自己定义的):一个接口里面可能有多个设置,是不是指灰色部分,和端点的关系是怎样的?





1th讲解:

文件夹1th中myuvc.c的编写参考了uvc_driver.c。

static int myuvc_probe(struct usb_interface *intf,
    const struct usb_device_id *id)
{
    static int cnt = 0;
    printk("myuvc_probe : cnt = %d\n", cnt++);                 //打印interface的个数,该设备有几个接口probe函数就会被调用                                                                                              几次
    return 0;
}


static void myuvc_disconnect(struct usb_interface *intf)
{
    static int cnt = 0;
    printk("myuvc_disconnect : cnt = %d\n", cnt++);
}


static struct usb_device_id myuvc_ids[] = {
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },  /* VideoControl Interface */  //1表示视频控制接口

    { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 2, 0) },  /* VideoStreaming Interface */  //2表示视频流接口,这一行不加也                                                                                                                                    行,视频流接口可以理解为是从属                                                                                                                                  于控制接口的,找到控制接口后会自                                                                                                                                   动找到对应的视频流接口

{}
};


/* 1. 分配usb_driver */
/* 2. 设置 */
static struct usb_driver myuvc_driver = {
    .name       = "myuvc",
    .probe      = myuvc_probe,                                 //该设备有几个接口就被调用几次
    .disconnect = myuvc_disconnect,
    .id_table   = myuvc_ids,                                     //表示能支持哪一些设备
};


static int myuvc_init(void)
{
    /* 3. 注册 */
    usb_register(&myuvc_driver);
    return 0;
}


static void myuvc_exit(void)
{
    usb_deregister(&myuvc_driver);
}


module_init(myuvc_init);
module_exit(myuvc_exit);


MODULE_LICENSE("GPL");


执行lsusb命令可以查看usb摄像头是否被连接成功,lsusb  -v  -d  0x1e4e:命令可以打印USB设备0x1e4e的描述符。

这些描述符都是我们接上USB设备后USB总线驱动程序读取设备得到的,已经事先存在内存里面了。




5th详解:

            for (j = 0; j < intf->num_altsetting; j++)                          //一个接口下可以有多个设置
            {
                interface = &intf->altsetting[j].desc;
                printk("    Interface Descriptor altsetting %d:\n"
                       "      bLength             %5u\n"
                       "      bDescriptorType     %5u\n"
                       "      bInterfaceNumber    %5u\n"
                       "      bAlternateSetting   %5u\n"
                       "      bNumEndpoints       %5u\n"
                       "      bInterfaceClass     %5u\n"
                       "      bInterfaceSubClass  %5u\n"
                       "      bInterfaceProtocol  %5u\n"
                       "      iInterface          %5u\n",
                       j, 
                       interface->bLength, interface->bDescriptorType, interface->bInterfaceNumber,  //interface是prob函数传入的变量
                       interface->bAlternateSetting, interface->bNumEndpoints, interface->bInterfaceClass,
                       interface->bInterfaceSubClass, interface->bInterfaceProtocol,
                       interface->iInterface);

            }


6th详解(打印UVC规范自己定义的描述符):

            buffer = intf->cur_altsetting->extra;                                //UVC规范自己定义的所有描述符都存在这个buffer里面
            buflen = intf->cur_altsetting->extralen;                           //表示所有描述符的总长度
            printk("extra buffer of interface %d:\n", cnt-1);
            k = 0;
            desc_cnt = 0;
            while (k < buflen)
            {
                desc_len = buffer[k];                                                      //每一个描述符的长度是desc_len,每一个自定义描述符的最开始位置记录着该描述符的长度,因此  desc_len = buffer[k];  
                printk("extra desc %d: ", desc_cnt);                                 //表示第几个描述符(UVC自己定义的)
                for (l = 0; l < desc_len; l++, k++)
                {
                    printk("%02x ", buffer[k]);                                          //打印第k个描述符
                }
                desc_cnt++;
                printk("\n");
            }


       自定义描述符对应的应该是VS与VC拓扑图中的unit和terminal,以及他们的关系。VS接口中的自定义描述符表示了摄像头能支持哪种格式,某种格式下支持哪几种frame(分辨率等),是否支持拍照功能等。VC_HEADER等表示的是描述符的类型或者说是作用。




7th详解:

            interface = &intf->cur_altsetting->desc;
            if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 1))  //如果buffer[1]是0x24的话(即自定义描述符中的第二位),并且,分辨一下是视频类里面的VC与否。
            {
                parse_videocontrol_interface(intf, buffer, buflen);                             //解析VC接口,应该就是把VC里面的unit和terminal解释一遍,也就是解析自定义描述符,也就是解析那一串数字
            }
            if ((buffer[1] == USB_DT_CS_INTERFACE) && (interface->bInterfaceSubClass == 2))
            {
                parse_videostreaming_interface(intf, buffer, buflen);
            }


猜你喜欢

转载自blog.csdn.net/hahaha_2017/article/details/79953590