Linux gadget驱动分析3------复合设备驱动
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------复合设备驱动的更多相关文章
- Linux I2C驱动分析(三)----i2c_dev驱动和应用层分析 【转】
本文转载自:http://blog.chinaunix.net/uid-21558711-id-3959287.html 分类: LINUX 原文地址:Linux I2C驱动分析(三)----i2c_ ...
- linuxok6410的I2C驱动分析---用户态驱动
3 i2c-dev 3.1 概述 之前在介绍I2C子系统时,提到过使用i2c-dev.c文件在应用程序中实现我们的I2C从设备驱动.不过,它实现的是一个虚拟,临时的i2c_client,随着设备文件 ...
- tiny4412 串口驱动分析六 --- TTY驱动架构
转载: http://www.linuxidc.com/Linux/2013-11/92639.htm 参考: http://blog.csdn.net/lamdoc/article/details/ ...
- linux驱动基础系列--Linux下Spi接口Wifi驱动分析
前言 本文纯粹的纸上谈兵,我并未在实际开发过程中遇到需要编写或调试这类驱动的时候,本文仅仅是根据源码分析后的记录!基于内核版本:2.6.35.6 .主要是想对spi接口的wifi驱动框架有一个整体的把 ...
- Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)
一.spi总线注册 这里所说的SPI核心,就是指/drivers/spi/目录下spi.c文件中提供给其他文件的函数,首先看下spi核心的初始化函数spi_init(void).程序如下: 点击(此处 ...
- Linux gadget驱动分析1------驱动加载过程
为了解决一个问题,简单看了一遍linux gadget驱动的加载流程.做一下记录. 使用的内核为linux 2.6.35 硬件为芯唐NUC950. gadget是在UDC驱动上面的一层,如果要编写ga ...
- s3c6410 linux gadget hid驱动
s3c6410 linux gadget hid驱动调了我一个多星期了今天终于搞定了,来跟大家分享下. 上一个星期纠结了一个星期的寄存器,试了N次,不管把3.1和3.7的hid驱动移植过来也是一样的情 ...
- linux的串口驱动分析
1.串口驱动中的数据结构 • UART驱动程序结构:struct uart_driver 驱动 • UART端口结构: struct uart_port 串口 • UART相关操作函数结构: st ...
- linux内核SPI总线驱动分析(一)(转)
linux内核SPI总线驱动分析(一)(转) 下面有两个大的模块: 一个是SPI总线驱动的分析 (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) ...
- linux串口驱动分析
linux串口驱动分析 硬件资源及描写叙述 s3c2440A 通用异步接收器和发送器(UART)提供了三个独立的异步串行 I/O(SIO)port,每一个port都能够在中断模式或 DMA 模式下操作 ...
随机推荐
- MySql(五)select排序查询
举个栗子/**查询员工信息,要求工资按照从高到低进行排序(默认升序)**/SELECT * FROM employees ORDER BY salary ASC;/**方法2:**/SELECT * ...
- MFC窗体大小变化
对话框的大小变化后,假若对话框上的控件大小不变化,看起来会比较难看.下面就介绍怎么让对话框上的控件随着对话框的大小的变化自动调整. 首先明确的是Windows有一个WM_SIZE消息响应函数,这个函数 ...
- Vue的特性
1.数据驱动视图 <div id="app"> <p> {{ message }}<p> </div> var app = new ...
- Object.prototype 原型和原型链
Object.prototype 原型和原型链 原型 Javascript中所有的对象都是Object的实例,并继承Object.prototype的属性和方法,有些属性是隐藏的.换句话说,在对象创建 ...
- 日本語 IME输入法(Microsoft 输入法)切换问题
平假名 与 片假名之间的切换 按住 Ctrl + Caps Lock(平假名) 按住 Alt + Caps Lock(片假名) 另外:语言之间的切换 Alt + Shift 键 / Windows + ...
- 第一章 Linux命令行简介
1 Linux系统命令操作语法的格式 命令_[参数选项]_[文件或路径] 其中 _ 至少一个空格 如:rm -f /etc/hosts 其中/etc/hosts完整路径不带空格 ...
- [bzoj1569][JSOI2008][Blue Mary的职员分配]
Description 由于Blue Mary呕心沥血的管理,Blue Mary的网络公司蒸蒸日上.现在一共拥有了n名职员,可惜没有任何的金钱和声誉.平均每名每天职员都可以给公司带来x单位金钱或者y单 ...
- slf4j+log4j2的配置
昨天自己测试了一下slf4j+log4j2的配置,可以正常使用,虽然配置十分简单,但好记性不如烂笔头,想想还是记录下来吧. 运行的环境:jdk1.7.tomcat7.Maven的web项目 1.在新建 ...
- [luoguP1103] 书本整理(DP)
传送门 以 去掉多少个 为阶段不好做. 去掉 k 个也可以变成选 n - k 个 f[i][j] 表示前 i 个数中 选 j 个的最优解,a[i] 必选 f[i][j] = min(f[i][j], ...
- node.js 利用流实现读写同步,边读边写
//10个数 10个字节,每次读4b,写1b let fs=require("fs"); function pipe(source,target) { //先创建可读流,再创建可写 ...