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

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

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

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

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

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

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

 static struct usb_device_descriptor msg_device_desc = {
.bLength = sizeof msg_device_desc,
.bDescriptorType = USB_DT_DEVICE, .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE, /* Vendor and product id can be overridden by module parameters. */
.idVendor = cpu_to_le16(FSG_VENDOR_ID),
.idProduct = cpu_to_le16(FSG_PRODUCT_ID),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
/* NO SERIAL NUMBER */
.bNumConfigurations = ,
};

其中:

.bDeviceClass = USB_CLASS_PER_INTERFACE,

即为0,
注意到其实mass storage类是被定义为:
#define USB_CLASS_MASS_STORAGE 8 
没有给.bDeviceClass 赋值为8,这样gadget 设备就会在windows上识别时获得 USB\COMPOSITE 的兼容标识符
 /*
* Device and/or Interface Class codes
* as found in bDeviceClass or bInterfaceClass
* and defined by www.usb.org documents
*/
#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
#define USB_CLASS_AUDIO 1
#define USB_CLASS_COMM 2
#define USB_CLASS_HID 3
#define USB_CLASS_PHYSICAL 5
#define USB_CLASS_STILL_IMAGE 6
#define USB_CLASS_PRINTER 7
#define USB_CLASS_MASS_STORAGE 8
#define USB_CLASS_HUB 9
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b /* chip+ smart card */
#define USB_CLASS_CONTENT_SEC 0x0d /* content security */
#define USB_CLASS_VIDEO 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff #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系列中,需要注意的是端点描述符里面

 static struct usb_endpoint_descriptor hs_source_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(),
}; static struct usb_endpoint_descriptor hs_sink_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(),
};
.wMaxPacketSize = cpu_to_le16(),
每一个端点的maxpacketsize 加起来不能超过udc 控制器中定义的sram_data大小2048。
 
现在就是一个设备有两个不同功能的接口,可以同时工作,其中一个是标准的mass storage类设备,windows有相应驱动,不用管,令一个是之前用的gadget zero的接口,需要gadget zero的驱动。 
这里随便找一个usb驱动(只是先识别,并不能工作),修改一下.inf文件让它识别我的这个接口。
需要改一下vid pid就行了,
修改这两行为:
%USB\VID_022b&PID_1234.DeviceDesc%=SECBULK.Dev, USB\VID_022b&PID_1234&REV_0000&MI_01
USB\VID_022b&PID_1234.DeviceDesc="test device"
通常设备驱动的.inf 没有后面 &REV_0000&MI_01,这个应该就是指的第几个接口. .inf 文件不太了解,便用边查吧。
然后安装驱动,识别出来就是一个test device 一个 USB Mass Storage Device,两个接口。这样设备及可以作为mass storage设备有可用作test device设备。 
 
 

Linux gadget驱动分析3------复合设备驱动的更多相关文章

  1. Linux I2C驱动分析(三)----i2c_dev驱动和应用层分析 【转】

    本文转载自:http://blog.chinaunix.net/uid-21558711-id-3959287.html 分类: LINUX 原文地址:Linux I2C驱动分析(三)----i2c_ ...

  2. linuxok6410的I2C驱动分析---用户态驱动

    3  i2c-dev 3.1 概述 之前在介绍I2C子系统时,提到过使用i2c-dev.c文件在应用程序中实现我们的I2C从设备驱动.不过,它实现的是一个虚拟,临时的i2c_client,随着设备文件 ...

  3. tiny4412 串口驱动分析六 --- TTY驱动架构

    转载: http://www.linuxidc.com/Linux/2013-11/92639.htm 参考: http://blog.csdn.net/lamdoc/article/details/ ...

  4. linux驱动基础系列--Linux下Spi接口Wifi驱动分析

    前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...

  5. Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)

    一.spi总线注册 这里所说的SPI核心,就是指/drivers/spi/目录下spi.c文件中提供给其他文件的函数,首先看下spi核心的初始化函数spi_init(void).程序如下: 点击(此处 ...

  6. Linux gadget驱动分析1------驱动加载过程

    为了解决一个问题,简单看了一遍linux gadget驱动的加载流程.做一下记录. 使用的内核为linux 2.6.35 硬件为芯唐NUC950. gadget是在UDC驱动上面的一层,如果要编写ga ...

  7. s3c6410 linux gadget hid驱动

    s3c6410 linux gadget hid驱动调了我一个多星期了今天终于搞定了,来跟大家分享下. 上一个星期纠结了一个星期的寄存器,试了N次,不管把3.1和3.7的hid驱动移植过来也是一样的情 ...

  8. linux的串口驱动分析

    1.串口驱动中的数据结构 • UART驱动程序结构:struct uart_driver  驱动 • UART端口结构: struct uart_port  串口 • UART相关操作函数结构: st ...

  9. linux内核SPI总线驱动分析(一)(转)

    linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析            (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...

  10. linux串口驱动分析

    linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...

随机推荐

  1. (转)淘淘商城系列——商品搜索功能Service实现

    http://blog.csdn.net/column/details/15737.html 首先我们在taotao-search-interface工程中新建一个SearchService接口,并在 ...

  2. HDU_1176_免费馅饼_16.4.23再做

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1176 免费馅饼 Time Limit: 2000/1000 MS (Java/Others)    M ...

  3. python游戏开发:pygame事件与设备轮询

    一.pygame事件 1.简介 pygame事件可以处理游戏中的各种事情.其实在前两节的博客中,我们已经使用过他们了.如下是pygame的完整事件列表: QUIT,ACTIVEEVENT,KEYDOW ...

  4. vue基础---计算属性和侦听器

    [一]计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护.例如: <div id="example"> ...

  5. Python之TCP编程

    参考原文 廖雪峰Python教程 客户端 我们知道每一条TCP的连接有2个端点,这两个端点叫做套接字socket.如果我们要进行基于TCP的通信必须先创建套接字.在Python中可以这样创建套接字so ...

  6. ios xmpp 发送语音图片解决方案

    ios xmpp 发送语音,图片解决方案,有需要的朋友可以参考下. 目前做IM多是用的xmpp. 因为项目需求需要实现语音和图片的发送. 发送语音图片有三种方法. 1,xmpp smack.文件传输方 ...

  7. css3文字渐变无效果的解决方案

    现在css3越来月流行了,为了实现一些高大上的效果,我们会用一些渐变的特效,请看文字渐变的特效代码: .title { font-size: 60px; line-height: 80px; text ...

  8. Coin Toss(uva 10328,动态规划递推,限制条件,至少转至多,高精度)

    有n张牌,求出至少有k张牌连续是正面的排列的种数.(1=<k<=n<=100) Toss is an important part of any event. When everyt ...

  9. 洛谷——P2659 美丽的序列

    P2659 美丽的序列 单调栈维护区间最小值,单调递增栈维护区间最小值, 考虑当前数对答案的贡献,不断加入数,如果加入的数$>$栈顶,说明栈顶的元素对当前数所在区间是有贡献的,同时加入当前的数. ...

  10. python之cookbook-day03

    第一章:数据结构和算法 1.3 保留最后 N 个元素 问题: 在迭代操作或其他操作的时候,怎样只保留最后有限几个元素的历史记录? 解决方案: 保留有限历史记录正是 collections.deque ...