USBgadget设备驱动解析.docx

上传人:b****4 文档编号:4536868 上传时间:2023-05-07 格式:DOCX 页数:40 大小:234.71KB
下载 相关 举报
USBgadget设备驱动解析.docx_第1页
第1页 / 共40页
USBgadget设备驱动解析.docx_第2页
第2页 / 共40页
USBgadget设备驱动解析.docx_第3页
第3页 / 共40页
USBgadget设备驱动解析.docx_第4页
第4页 / 共40页
USBgadget设备驱动解析.docx_第5页
第5页 / 共40页
USBgadget设备驱动解析.docx_第6页
第6页 / 共40页
USBgadget设备驱动解析.docx_第7页
第7页 / 共40页
USBgadget设备驱动解析.docx_第8页
第8页 / 共40页
USBgadget设备驱动解析.docx_第9页
第9页 / 共40页
USBgadget设备驱动解析.docx_第10页
第10页 / 共40页
USBgadget设备驱动解析.docx_第11页
第11页 / 共40页
USBgadget设备驱动解析.docx_第12页
第12页 / 共40页
USBgadget设备驱动解析.docx_第13页
第13页 / 共40页
USBgadget设备驱动解析.docx_第14页
第14页 / 共40页
USBgadget设备驱动解析.docx_第15页
第15页 / 共40页
USBgadget设备驱动解析.docx_第16页
第16页 / 共40页
USBgadget设备驱动解析.docx_第17页
第17页 / 共40页
USBgadget设备驱动解析.docx_第18页
第18页 / 共40页
USBgadget设备驱动解析.docx_第19页
第19页 / 共40页
USBgadget设备驱动解析.docx_第20页
第20页 / 共40页
亲,该文档总共40页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

USBgadget设备驱动解析.docx

《USBgadget设备驱动解析.docx》由会员分享,可在线阅读,更多相关《USBgadget设备驱动解析.docx(40页珍藏版)》请在冰点文库上搜索。

USBgadget设备驱动解析.docx

USBgadget设备驱动解析

LinuxUSBgadget设备驱动解析

(1)“功能体验”

利用LinuxUSBgadget设备驱动可以实现一些比较有意思的功能,举两个例子:

1、一个嵌入式产品中的某个存储设备,或是一个存储设备的某个分区,可以作为一个U盘被PC设别,从而非常方便的完成文件交互,这个功能被广泛的应用于手机、数码相机等产品中。

2、一个嵌入式设备通过USB连接到你的PC后,在你的PC端会出现一个新的网络连接,在嵌入式设备上也会有一个网卡设备,你可以配置它们的IP地址,并进行网络通讯,俗称USBNET。

所有USB通讯的设备端都有usbdevice程序,通常称它们为usb固件。

在一些功能简单的设备里,用一些专用的可编程USB控制器就可以了。

而在一些运行了类似linux操作系统的复杂的嵌入式系统中,要完成usbdevice程序,就会要求你不仅熟悉usbdevice控制器的操作,还要熟悉操作系统的驱动架构。

我想通过“功能体验”、“驱动调试”、“gadget驱动结构分析”、“编写一个自己的gadget驱动”这4个方面解析linuxusbgadget设备驱动的编写方法。

一、linux模拟U盘功能的实现

在硬件环境为华清远见的fs2410平台,软件环境为linux-2.6.26的linux系统上,实现模拟U盘的功能。

向内核添加代码

#include

#include

#include

修改arch/arm/mach-s3c2410/mach-smdk2410.c

/*USBdevice上拉电阻处理*/

staticvoidsmdk2410_udc_pullup(enums3c2410_udc_cmd_ecmd)

{

u8*s3c2410_pullup_info[]={

"",

"Pull-upenable",

"Pull-updisable",

"UDCreset,incaseof"

};

printk("smdk2410_udc:

%s\\n",s3c2410_pullup_info[cmd]);

s3c2410_gpio_cfgpin(S3C2410_GPG9,S3C2410_GPG9_OUTP);

switch(cmd)

{

caseS3C2410_UDC_P_ENABLE:

s3c2410_gpio_setpin(S3C2410_GPG9,1);//setgpg9outputHIGH

break;

caseS3C2410_UDC_P_DISABLE:

s3c2410_gpio_setpin(S3C2410_GPG9,0);//setgpg9outputLOW

break;

caseS3C2410_UDC_P_RESET:

//FIXME!

!

!

break;

default:

break;

}

}

staticstructs3c2410_udc_mach_infosmdk2410_udc_cfg__initdata={

.udc_command=smdk2410_udc_pullup,

};

staticstructplatform_device*smdk2410_devices[]__initdata={

…,

&s3c_device_usbgadget,/*USBgadgetdevice设备登记*/

};

staticvoid__initsdmk2410_init(void)

{

u32upll_value;

set_s3c2410fb_info(&smdk2410_lcdcfg);

s3c24xx_udc_set_platdata(&smdk2410_udc_cfg);/*初始化*/

s3c_device_sdi.dev.platform_data=&smdk2410_mmc_cfg;

/*TurnoffsuspendonbothUSBports,andswitchthe

*selectableUSBporttoUSBdevicemode.*/

s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST|

S3C2410_MISCCR_USBSUSPND0|

S3C2410_MISCCR_USBSUSPND1,0x0);

/*设置USB时钟*/

upll_value=(

0x78<

|(0x02<

|(0x03<

while(upll_value!

=readl(S3C2410_UPLLCON)){

writel(upll_value,S3C2410_UPLLCON);

udelay(20);

}

}

修改drivers/usb/gadget/file_storage.c

staticvoidstart_transfer(structfsg_dev*fsg,structusb_ep*ep,

structusb_request*req,int*pbusy,

enumfsg_buffer_state*state)

{

intrc;

udelay(800);

……

}

配置内核支持U盘模拟

<*>USBGadgetSupport--->

USBPeripheralController(S3C2410USBDeviceController)--->

S3C2410USBDeviceController

[*]S3C2410udcdebugmessages

USBGadgetDrivers

File-backedStorageGadget

3、编译内核

#makezImage

#makemodules

在目录drivers/usb/gadget下生成g_file_storage.ko

加载驱动,测试功能

利用前面的生成的内核,启动系统后,加载g_file_storage.ko

#insmodg_file_storage.ko

#insmodg_file_storage.kofile=/dev/mtdblock2stall=0removable=1

0.03USB:

usb_gadget_register_driver()\'g_file_storage\'

0.04USB:

bindinggadgetdriver\'g_file_storage\'

0.05USB:

s3c2410_set_selfpowered()

g_file_storagegadget:

File-backedStorageGadget,version:

20October2004

g_file_storagegadget:

NumberofLUNs=1

g_file_storagegadget-lun0:

ro=0,file:

/dev/mtdblock3

0.06USB:

udc_enablecalled

smdk2410_udc:

Pull-upenable

连接设备到windows,windows系统会自动设备到一个新的U盘加入。

格式化U盘,存入文件。

卸载U盘后,在目标板上执行如下操作:

#mkdir/mnt/gadget

#mount-tvfat/dev/mtdblock2/mnt/gadget/

#ls

可以看到windows存入U盘的文件。

二、usbnet功能的实现

配置内核支持usbnet

<*>USBGadgetSupport--->

USBPeripheralController(S3C2410USBDeviceController)--->

S3C2410USBDeviceController

[*]S3C2410udcdebugmessages

USBGadgetDrivers

EthernetGadget(withCDCEthernetsupport)

[*]RNDISsupport

2、编译内核

#makezImage

#makemodules

在目录drivers/usb/gadget下生成g_ether.ko

3、加载驱动,测试功能

利用前面的生成的内核,启动系统后,加载g_ether.ko

#insmodg_ether.ko

#ifconfigusb0192.168.1.120

……

usb0Linkencap:

EthernetHWaddr5E:

C5:

F6:

D4:

2B:

91

inetaddr:

192.168.1.120Bcast:

192.168.1.255Mask:

255.255.255.0

UPBROADCASTRUNNINGMULTICASTMTU:

1500Metric:

1

RXpackets:

253errors:

0dropped:

0overruns:

0frame:

0

TXpackets:

43errors:

0dropped:

0overruns:

0carrier:

0

collisions:

0txqueuelen:

1000

RXbytes:

35277(34.4KiB)TXbytes:

10152(9.9KiB)

连接设备到windows,windows系统会提示安装驱动,根据提示安装上RNDIS驱动。

这个驱动可以在网络上找到。

此时windows会新生成一个网络连接,配置它的ip地址等信息。

然后就可以和目标系统通过USB实现网络通讯了。

 

LinuxUSBgadget设备驱动解析

(2)---驱动调试

作者:

刘洪涛,华清远见嵌入式学院金牌讲师。

这一节主要把在实现“linux模拟U盘功能”过程中的一些调试过程记录下来,并加以解析。

一、背景知识

1、USBMassStorage类规范概述

USB组织在universalSerialBusMassStorageClassSpaceification1.1版本中定义了海量存储设备类(MassStorageClass)的规范,这个类规范包括四个独立的子类规范,即:

1.USBMassStorageClassControl/Bulk/Interrupt(CBI)Transport

2.USBMassStorageClassBulk-OnlyTransport

3.USBMassStorageClassATACommandBlock

4.USBMassStorageClassUFICommandSpecification

前两个子规范定义了数据/命令/状态在USB上的传输方法。

Bulk-Only传输规范仅仅使用Bulk端点传送数据/命令/状态,CBI传输规范则使用Control/Bulk/Interrupt三种类型的端点进行数据/命令/状态传送。

后两个子规范则定义了存储介质的操作命令。

ATA命令规范用于硬盘,UFI命令规范是针对USB移动存储。

MicrosoftWindows中提供对MassStorage协议的支持,因此USB移动设备只需要遵循MassStorage协议来组织数据和处理命令,即可实现与PC机交换数据。

而Flash的存储单元组织形式采用FAT16文件系统,这样,就可以直接在Windows的浏览器中通过可移动磁盘来交换数据了,Windows负责对FAT16文件系统的管理,USB设备不需要干预FAT16文件系统操作的具体细节。

USB(Host)唯一通过描述符了解设备的有关信息,根据这些信息,建立起通信,在这些描述符中,规定了设备所使用的协议、端点情况等。

因此,正确地提供描述符,是USB设备正常工作的先决条件。

Linux-2.6.26内核中在利用USBgadget驱动实现模拟U盘时主要涉及到file_storage.c、s3c2410_udc.c等驱动文件(这些文件的具体结构,将在下一篇文章中描述)。

此时我们想先从这些代码中找到USB描述描述符,从中确定使用的存储类规范,从而确定协议。

确定通讯协议是我们调试的基础。

存储类规范是由接口描述符决定的。

接口描述符各项的定义义如下:

其中,bInterfaceClass、bInterfaceSubClass、bInterfaceProtocol可以判断出设备是否是存储类,以及属于哪种存储子类和存储介质的操作命令。

在file_storage.c文件中,

/*USBprotocolvalue=thetransportmethod*/

#defineUSB_PR_CBI0x00//Control/Bulk/Interrupt

#defineUSB_PR_CB0x01//Control/Bulkw/ointerrupt

#defineUSB_PR_BULK0x50//Bulk-only

/*USBsubclassvalue=theprotocolencapsulation*/

#defineUSB_SC_RBC0x01//ReducedBlockCommands(flash)

#defineUSB_SC_80200x02//SFF-8020i,MMC-2,ATAPI(CD-ROM)

#defineUSB_SC_QIC0x03//QIC-157(tape)

#defineUSB_SC_UFI0x04//UFI(floppy)

#defineUSB_SC_80700x05//SFF-8070i(removable)

#defineUSB_SC_SCSI0x06//TransparentSCSI

默认的情况是:

mod_data={//Defaultvalues

.transport_parm="BBB",

.protocol_parm="SCSI",

……

默认的赋值如下:

bInterfaceClass=08表示:

存储类

bInterfaceSubClass=0x06表示:

透明的SCSI指令

bInterfaceProtocol=0x50表示:

bulk-only传输

2、Bulk-Only传输协议

下面看看Bulk-Only传输协议:

(详细的规范请阅读《UniversalSerialBusMassStorageClassBulk-OnlyTransport》)

设备插入到USB后,USB即对设备进行搜索,并要求设备提供相应的描述符。

在USBHost得到上述描述符后,即完成了设备的配置,识别出为Bulk-Only的MassStorage设备,然后即进入Bulk-Only传输方式。

在此方式下,USB与设备间的所有数据均通过Bulk-In和Bulk-Out来进行传输,不再通过控制端点传输任何数据。

在这种传输方式下,有三种类型的数据在USB和设备之间传送,CBW、CSW和普通数据。

CBW(CommandBlockWrapper,即命令块包)是从USBHost发送到设备的命令,命令格式遵从接口中的bInterfaceSubClass所指定的命令块,这里为SCSI传输命令集。

USB设备需要将SCSI命令从CBW中提取出来,执行相应的命令,完成以后,向Host发出反映当前命令执行状态的CSW(CommandStatusWrapper),Host根据CSW来决定是否继续发送下一个CBW或是数据。

Host要求USB设备执行的命令可能为发送数据,则此时需要将特定数据传送出去,完毕后发出CSW,以使Host进行下一步的操作。

USB设备所执行的操作可用下图描述:

CBW的格式如下:

dCBWSignature:

CBW的标识,固定值:

43425355h(littleendian)。

dCBWTag:

主机发送的一个命令块标识,设备需要原样作为dCSWTag(CSW中的一部分)再发送给Host;主要用于关联CSW到对应的CBW。

dCBWDataTransferLength:

本次CBW命令要求在命令与回应之间传输的字节数。

如果为0,则不传输数据。

bmCBWFlags:

反映数据传输的方向,0表示来自Host,1表示发至Host;

bCBWLUN:

对于有多个LUN逻辑单元的设备,用来选择具体目标。

如果没有多个LUN,则写0。

bCBWCBLength:

命令的长度,范围在0~16.

CBWCB:

传输的具体命令,符合bInterfaceSubClass.中定义的命令规范,此处是SCSI

CSW命令格式如下:

dCSWSignature:

CSW的标识,固定值:

53425355h(littleendian)

dCSWTag:

设置这个标识和CBW中的dCBWTag一致,参照上面关于dCBWTag的解释

dCSWDataResidue:

还需要传送的数据,此数据根据dCBWDataTransferLength-本次已经传送的数据得到

bCSWStatus:

指示命令的执行状态。

如果命令正确执行,bCSWStatus返回0即可。

3、SCSI指令集

Bulk-Only的CBW中的CBWCB中的内容即为如下格式的命令块描述符(CommandBlockDescriptor)。

SCSI-2有三种字长的命令,6字节、10字节和12字节,MicrosoftWindows环境下支持12字节长的命令。

OperationCode:

操作代码,表示特定的命令。

高3位为GroupCode,共有8种组合,

即8个组,低5五位为CommandCode,可以有32种命令。

LogicolunitNumber:

为了兼容SCSI-1而设的,此处可以不必关心。

Logicalblockaddress:

为高位在前,低位在后的逻辑块地址,即扇区地址。

第2位为高位,第3、4、5依次为低位。

Transferlength:

为需要从逻辑块地址处开始传输的扇区数(比如在Write命令中)。

Parameterlistlength:

为需要传输的数据长度(比如在ModeSense命令中);

Allocationlength:

为初始程序为返回数据所分配的最大字节数,此值可以为零,表示不需要传送数据。

SCSI指令集的DirectAccesss类型存储介质的传输命令有许多,MassStorage协议只用到了其中的一些。

更多的SCSI指令参见:

http:

//en.wikipedia.org/wiki/SCSI_command

指令代码指令名称说明

04hFormatUnit格式化存储单元

12hInquiry索取器件信息

1BhStart/Stopload/unload

55hModeselect允许Host对外部设备设置参数。

5AhModeSense向host传输参数

EhPrevent/AllowMediumRemoval写保护

>28hRead(10)Host读存储介质中的二进制数据

A8hRead(12)同上,不过比较详细一点

25hReadCapacity要求设备返回当前容量

23hReadFormatCapacity查询当前容量及可用空间

03hRequestSense请求设备向主机返回执行结果,及状态数据

01hRexeroUnit返回零轨道

2BhSeek(10)为设备分配到特定地址

1DhSendDiagnostic执行固件复位并执行诊断

00hTestUnitReady请求设备报告是否处于Ready状态

2FhVerify在存储中验证数据

2AhWrite(10)从主机向介质写二进制数据

AAhWrite(12)同上,不过比较详细

2EhWriteandVerify写二进制数据并验证

对于不同的命令,其命令块描述符略有不同,其要求的返回内容也有所不同,根据相应的文档,可以对每种请求作出适当的回应。

比如,下面是INQUIRY请求的命令块描述符和其返回内容的数据格式:

如:

INQUIRY

命令描述符:

返回数据格式

Host会依次发出INQUIRY、ReadCapacity、UFIModeSense请求,如果上述请求的返回结果都正确,则Host会发出READ命令,读取文件系统0簇0扇区的MBR数据,进入文件系统识别阶段。

4、利用USBView观察结果

可通过USBView软件查看到USB设置阶段获取到的信息。

二、出现的主要问题

在调试过程中遇到了一个问题。

现象是:

在目标板加载完驱动后,即执行完:

#insmodg_file_storage.kofile=/dev/mtdblock2stall=0removable=1

后,接好USB线。

此时在windows端设备出有usbstorage设备加入,但出现不了盘符。

下面记录下调试过程。

三、调试过程

根据规范,当完成SCSI指令集中Inquiry命令时,可以出现盘符。

所以可以通过bushound软件查看通讯过程,找出原因。

下面是利用bushound工具在出现问题时采集到的数据。

DevPhaseDataInfoTimeCmd.Phase.Ofs

-------------------------------------------------------------------

26CTL80060001-00001200GETDESCRIPTR0us1.1.0

26DI12011001-00000010-2505a5a4-12030102........%

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2