• Linux gadget驱动分析3------复合设备驱动


     windows上面对usb复合设备的识别需要下面条件。

    如果设备满足下列要求,则总线驱动程序还会报告 USBCOMPOSITE 的兼容标识符:

    • 设备描述符的设备类字段 (bDeviceClass) 必须包含一个零值,或者设备描述符的类 (bDeviceClass)、子类 (bDeviceSubClass) 和协议 (bDeviceProtocol) 字段必须分别具有值 0xEF、0x02 和 0x01,如 USB 接口关联描述符中所述。

    • 设备必须具有多个接口。

    • 设备必须具有一个配置。“

    引用自:http://msdn.microsoft.com/zh-cn/library/ff537109

    下面是linux /driver/usb/gadget/mass_storage.c 中定义的设备描述符:

     1 static struct usb_device_descriptor msg_device_desc = {
     2     .bLength =        sizeof msg_device_desc,
     3     .bDescriptorType =    USB_DT_DEVICE,
     4 
     5     .bcdUSB =        cpu_to_le16(0x0200),
     6     .bDeviceClass =        USB_CLASS_PER_INTERFACE,
     7 
     8     /* Vendor and product id can be overridden by module parameters.  */
     9     .idVendor =        cpu_to_le16(FSG_VENDOR_ID),
    10     .idProduct =        cpu_to_le16(FSG_PRODUCT_ID),
    11     /* .bcdDevice = f(hardware) */
    12     /* .iManufacturer = DYNAMIC */
    13     /* .iProduct = DYNAMIC */
    14     /* NO SERIAL NUMBER */
    15     .bNumConfigurations =    1,
    16 };

    其中:

    .bDeviceClass = USB_CLASS_PER_INTERFACE,

    即为0,
    注意到其实mass storage类是被定义为:
    #define USB_CLASS_MASS_STORAGE 8 
    没有给.bDeviceClass 赋值为8,这样gadget 设备就会在windows上识别时获得 USBCOMPOSITE 的兼容标识符
     1 /*
     2  * Device and/or Interface Class codes
     3  * as found in bDeviceClass or bInterfaceClass
     4  * and defined by www.usb.org documents
     5  */
     6 #define USB_CLASS_PER_INTERFACE        0    /* for DeviceClass */
     7 #define USB_CLASS_AUDIO            1
     8 #define USB_CLASS_COMM            2
     9 #define USB_CLASS_HID            3
    10 #define USB_CLASS_PHYSICAL        5
    11 #define USB_CLASS_STILL_IMAGE        6
    12 #define USB_CLASS_PRINTER        7
    13 #define USB_CLASS_MASS_STORAGE        8
    14 #define USB_CLASS_HUB            9
    15 #define USB_CLASS_CDC_DATA        0x0a
    16 #define USB_CLASS_CSCID            0x0b    /* chip+ smart card */
    17 #define USB_CLASS_CONTENT_SEC        0x0d    /* content security */
    18 #define USB_CLASS_VIDEO            0x0e
    19 #define USB_CLASS_WIRELESS_CONTROLLER    0xe0
    20 #define USB_CLASS_MISC            0xef
    21 #define USB_CLASS_APP_SPEC        0xfe
    22 #define USB_CLASS_VENDOR_SPEC        0xff
    23 
    24 #define USB_SUBCLASS_VENDOR_SPEC    0xff

    上面那个结构体中:

    .idVendor = cpu_to_le16(FSG_VENDOR_ID),

    .idProduct = cpu_to_le16(FSG_PRODUCT_ID),

    如果不做修改,windows会直接找到通用的mass sotrage驱动 ,而不会加载USB 通用父驱动程序 (Usbccgp.sys),就不会i识别成复合设备,而是直使用设备的第一个接口,设备管理器只看到一个设备。

    widows的机制不是很了解

    参考:http://msdn.microsoft.com/zh-cn/library/ff537109

    我这里改成

    .idVendor =             cpu_to_le16(0x022b),

    .idProduct = cpu_to_le16(0x1234),

    然后增加一个接口,即设备两个接口同时

    static int fsg_add(struct usb_composite_dev *cdev,
                       struct usb_configuration *c,
                       struct fsg_common *common)
    {
            struct fsg_dev *fsg;
            int rc;
    
            fsg = kzalloc(sizeof *fsg, GFP_KERNEL);
            if (unlikely(!fsg))
                    return -ENOMEM;
    
            fsg->function.name        = FSG_DRIVER_DESC;
            fsg->function.strings     = fsg_strings_array;
            fsg->function.bind        = fsg_bind;
            fsg->function.unbind      = fsg_unbind;
            fsg->function.setup       = fsg_setup;
            fsg->function.set_alt     = fsg_set_alt;
            fsg->function.disable     = fsg_disable;
    
            fsg->common               = common;
            /* Our caller holds a reference to common structure so we
             * don't have to be worry about it being freed until we return
             * from this function.  So instead of incrementing counter now
             * and decrement in error recovery we increment it only when
             * call to usb_add_function() was successful. */
    
            rc = usb_add_function(c, &fsg->function);
            if (unlikely(rc))
                    kfree(fsg);
            else
                    fsg_common_get(fsg->common);
            struct f_sourcesink     *ss;
            int                     status;
    
            ss = kzalloc(sizeof *ss, GFP_KERNEL);
            if (!ss)
                    return -ENOMEM;
            init_completion(&ss->gdt_completion);
            ss->function.name = "source/sink";        //就是f_sourcesink.c中的接口,gadget zero中使用那个
            ss->function.descriptors = fs_source_sink_descs;
            ss->function.bind = sourcesink_bind;
            ss->function.unbind = sourcesink_unbind;
            ss->function.set_alt = sourcesink_set_alt;
            ss->function.disable = sourcesink_disable;
    
            status = usb_add_function(c, &ss->function);
            if (status)
                    kfree(ss);
            return rc;
    }

    调用两次usb_add_function,给设备添加两个接口。

    另外,在nuc900系列中,需要注意的是端点描述符里面

     1 static struct usb_endpoint_descriptor hs_source_desc = {
     2     .bLength =        USB_DT_ENDPOINT_SIZE,
     3     .bDescriptorType =    USB_DT_ENDPOINT,
     4 
     5     .bmAttributes =        USB_ENDPOINT_XFER_BULK,
     6     .wMaxPacketSize =    cpu_to_le16(512),
     7 };
     8 
     9 static struct usb_endpoint_descriptor hs_sink_desc = {
    10     .bLength =        USB_DT_ENDPOINT_SIZE,
    11     .bDescriptorType =    USB_DT_ENDPOINT,
    12 
    13     .bmAttributes =        USB_ENDPOINT_XFER_BULK,
    14     .wMaxPacketSize =    cpu_to_le16(512),
    15 };
    16 .wMaxPacketSize = cpu_to_le16(512), 
    每一个端点的maxpacketsize 加起来不能超过udc 控制器中定义的sram_data大小2048。
     
    现在就是一个设备有两个不同功能的接口,可以同时工作,其中一个是标准的mass storage类设备,windows有相应驱动,不用管,令一个是之前用的gadget zero的接口,需要gadget zero的驱动。 
    这里随便找一个usb驱动(只是先识别,并不能工作),修改一下.inf文件让它识别我的这个接口。
    需要改一下vid pid就行了,
    修改这两行为:
    %USBVID_022b&PID_1234.DeviceDesc%=SECBULK.Dev, USBVID_022b&PID_1234&REV_0000&MI_01
    USBVID_022b&PID_1234.DeviceDesc="test device"
    通常设备驱动的.inf 没有后面 &REV_0000&MI_01,这个应该就是指的第几个接口. .inf 文件不太了解,便用边查吧。
    然后安装驱动,识别出来就是一个test device 一个 USB Mass Storage Device,两个接口。这样设备及可以作为mass storage设备有可用作test device设备。 
    image
     
     
  • 相关阅读:
    CopyOnWriteArrayList分析
    java锁和同步
    线程池原理
    Hadoop1的安装
    Hadoop2的HA安装(high availability):JournalNode+ zookeeper
    Hadoop2的HA安装(high availability):nfs+zookeeper
    Hadoop2的FN安装(federated namespace)
    Redis 基础知识
    mycat
    GitFlow及项目工作流程
  • 原文地址:https://www.cnblogs.com/fengeryi/p/3401738.html
Copyright © 2020-2023  润新知