USB设备驱动.docx

上传人:b****2 文档编号:23224147 上传时间:2023-05-15 格式:DOCX 页数:14 大小:22.07KB
下载 相关 举报
USB设备驱动.docx_第1页
第1页 / 共14页
USB设备驱动.docx_第2页
第2页 / 共14页
USB设备驱动.docx_第3页
第3页 / 共14页
USB设备驱动.docx_第4页
第4页 / 共14页
USB设备驱动.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

USB设备驱动.docx

《USB设备驱动.docx》由会员分享,可在线阅读,更多相关《USB设备驱动.docx(14页珍藏版)》请在冰豆网上搜索。

USB设备驱动.docx

USB设备驱动

  随着USB设备的普及,摆在开发人员面前的驱动开发任务也是越来越繁重了,特别是对于一些嵌入式开发厂商来讲,由于设备所采用的操作系统不同,相应的硬件接口也是不一样的,开发相关的USB驱动程序更是难上加难。

WindowsCE.NET是微软推出的功能强大的嵌入式操作系统,国内采用此操作系统的厂商已经很多了,本文就以为例,简单介绍一下如何开发下的USB驱动程序。

首先要熟悉一些USB的基本概念,当然最好把USB1.1的协议看一遍,(当然现在2。

0的协议都已经有了)http:

//www.usb.org上可以下载,我记得好像有个中文版的,翻译的还可以,上有的,具体位置记不太清楚了,中文版的协议可以快速翻一边,了解一些基本的概念,但是设计到一些关键性的东西最好还是看英文版的心里比较清楚些。

这里我就不介绍USB的基本协议了,假设用户已经熟悉了USB设备的一些基本的概念,并且对WinowsCE.NET的开发有一定的了解。

下面简略介绍一下WindowsCE.NET中USB设备驱动开发的一些基础知识。

WindowsCE.NET的USB系统软件分为两层:

USBClient设备驱动程序和底层的WindowsCE实现的函数层。

USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。

底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。

HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。

USB设备驱动主要利用USBD接口函数和他们的外围设备打交道。

USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。

主要的传输函数有:

AbourtTransferIssueControlTransfer

CloseTransferIssueInterrupTransfer

GetIsochResultIssueIsochTransfer

GetTransferStatusIstransferComplete

IssueBulkTransferIssueVendorTransfer主要的用于打开和关闭USBD和USB设备之间的通信通道的函数有:

AbortPipeTransfersClosePipe

IsDefaultPipeHaltedIsPipeHalted

OpenPipeResetDefaultPipe

ResetPipe相应的打包函数接口有:

GetFrameLengthGetFrameNumberReleaseFrameLengthControl

SetFrameLengthTakeFrameLengthControl取得设置设备配置函数:

ClearFeatureSetDescriptor

GetDescriptorSetFeature

GetInterfaceSetInterface

GetStatusSyncFrame与USB进行交互的实现方法相关的多任务函数:

FindInterfaceRegisterClientDeviceId

GetDeviceInfoRegisterClientSettings

GetUSBDVersionRegisterNotificationRoutine

LoadGenericInterfaceDriverTranslateStringDescr

OpenClientRegisterKeyUnRegisterNotificationRoutine

常见的WindowsCE.NET下USB的设备驱动程序的编写有以下几种方法:

●流式接口函数

这种驱动程序主要呈现流式函数接口,主要输出XXX_Init,XXX_Deinit,XXX_Open,XXX_Close,XXX_Open,XXX_Close,XXX_Read,XXX_Write,

XXX_Seek,XXX_IOControl,XXX_PowerUp,XXX_PowerDown等流式接口,注意上述的几个接口一定都要输出,另外XXX必须为三个字符,否则会出错。

但是此类的驱动程序不是通过设备管理接口来加载的,所以必须手工的调用RegisterDevice()和DeregisterDevice()函数来加载和卸载驱动程序。

用户可以将此类的设备作为标准的文件来操作,只要调用相应的文件操作就可以和驱动程序打交道。

●使用现有的WindowCE.NET的应用程序接口

此类设备主要是利用WindowsCE.NET中已经有了现成的函数接口,例如USBMassStorageDisk,它主要利用现有的WindowsCE.Net中已经有的可安装文件系统接口,呈现给系统可用的文件系统,对于用户来讲,它是透明的,用户仅仅感觉在操作一个文件夹。

●创建指定到特定的USBD的用户指定的API

这种方法在USBD呈现设备时不需要任何限制,主要是特制的提供API给用户,一般不太常见。

USB设备驱动程序必须输出的函数有:

●USBDeviecAttach

当USB设备连接到计算机上时,USBD模块就会调用此函数,这个函数主要用于初始化USB设备,取得USB设备信息,配置USB设备,并且申请必需的资源。

●USBInstallDriver

主要用于创建一个驱动程序加载所需的注册表信息,例如读写超时,设备名称等。

●USBUninstallDriver

主要用于释放驱动程序所占用的资源,以及删除USBInstallDriver函数创建的注册表等。

上述的三个函数接口是所有的USB驱动程序必须提供的,缺一不可。

另外比较重要的是USB设备驱动程序的注册表配置,一般的USB设备驱动程序的注册表配置在HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients下,每个驱动程序的子键都有Group1_ID\Group2_ID\Group3_ID\DriverName格式,如果注册表信息与USB设备信息符合,USBD就会加载此驱动程序。

否则设备的子键应该由供应商,设备类和协议信息通过下划线组成。

具体的配置举个例子:

例如你有个PDA设备,它具有一个USB接口,它的供应厂商ID假设为0x0888,设备ID为0x0999,没有使用特殊的协议,那么它的加载注册表应该写为:

[HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\2184_2457\Default\Default\PDA]"DLL"="pdausb.dll"

需要注意的是注册表构成都是十进制数值来标识的,注意一下十进制和十六进制的转换。

再举个USB鼠标的例子,USB鼠标是标准的HID设备,它的协议为:

InterfaceClassCode为3(HID类),InterfaceSubclassCode为1(引导接口类),InterfaceProtocolCode为2(鼠标协议类),所以它的注册如下:

[HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\Default\Default\3_1_2\USBMouse]"DLL"="usbmouse.dll"到此为止,我们可以看出,其实驱动开发无非做两件事情,一件是和硬件打交道,另外一件是和操作系统打交道。

举个简单的例子,例如:

我们需要开发一个USB鼠标驱动程序,我们就需要了解USB鼠标硬件上是怎么发送数据的?

操作系统怎么才能得到鼠标的控制事件?

其实USB鼠标是有一个中断PIPE的,用于传送鼠标产生的数据,WindwosCE.NET中有个接口函数叫做mouse_event(),专门用于产生鼠标事件,但是它是不关心具体什么硬件的,甚至我们自己在应用程序中调用这个函数都可以实现模拟鼠标,对应的有个keybd_event(),用于产生键盘事件,知道了这个就好办多了,只要将相应的数据转换一下,调用一下mouse_event()即可,上述讲了堆理论,可能读者脑袋都已经大了,为此,我们举个简单的例子来详细说明一下驱动程序的开发过程。

例如我们有个USBMouse设备,设备信息描述如下:

DeviceDescriptor:

bcdUSB:

0x0100

bDeviceClass:

0x00

bDeviceSubClass:

0x00

bDeviceProtocol:

0x00

bMaxPacketSize0:

0x08(8)

idVendor:

0x05E3(GenesysLogicInc.)

idProduct:

0x0001

bcdDevice:

0x0101

iManufacturer:

0x00

iProduct:

0x01

iSerialNumber:

0x00

bNumConfigurations:

0x01ConnectionStatus:

DeviceConnected

CurrentConfigValue:

0x01

DeviceBusSpeed:

Low

DeviceAddress:

0x02

OpenPipes:

1EndpointDescriptor:

bEndpointAddress:

0x81

TransferType:

Interrupt

wMaxPacketSize:

0x0003(3)

bInterval:

0x0A可以看出上述设备有一个中断PIPE,包的最大值为3。

可能有人问上述的值怎么得到的,win2k的DDK中有个usbview的例程,编译一下,将你的USB设备插到PC机的USB口中,运行usbview.exe即可看得相应的设备信息。

有了这些基本信息,就可以编写USB设备了,首先声明一下,下面的代码取自微软的USB鼠标样本程序,版权归微软所有,此处仅仅借用来描述一下USB鼠标驱动的开发过程,读者如需要引用此代码,需要得到微软的同意。

首先,必须输出USBD要求调用的三个函数,首先到设备插入到USB端口时,USBD会调用USBDeviceAttach()函数,相应的代码如下:

extern"C"BOOL

USBDeviceAttach(

USB_HANDLEhDevice,//USB设备句柄

LPCUSB_FUNCSlpUsbFuncs,//USBDI的函数集合

LPCUSB_INTERFACElpInterface,//设备接口描述信息

LPCWSTRszUniqueDriverId,//设备ID描述字符串。

LPBOOLfAcceptControl,//返回TRUE,标识我们可以控制此设备,反之表示不能控制

DWORDdwUnused)

{

*fAcceptControl=FALSE;

//我们的鼠标设备有特定的描述信息,要检测是否是我们的设备。

if(lpInterface==NULL)

returnFALSE;

//打印相关的USB设备接口描述信息。

DEBUGMSG(ZONE_INIT,(TEXT("USBMouse:

DeviceAttach,IF%u,#EP:

%u,Class:

%u,Sub:

%u,Prot:

%u\r\n"),lpInterface->Descriptor.bInterfaceNumber,lpInterface->Descriptor.bNumEndpoints,lpInterface->Descriptor.bInterfaceClass,lpInterface->Descriptor.bInterfaceSubClass,lpInterface->Descriptor.bInterfaceProtocol));

//初试数据USB鼠标类,产生一个接受USB鼠标数据的线程

CMouse*pMouse=newCMouse(hDevice,lpUsbFuncs,lpInterface);

if(pMouse==NULL)

returnFALSE;if(!

pMouse->Initialize())

{

deletepMouse;

returnFALSE;

}//注册一个监控USB设备事件的回调函数,用于监控USB设备是否已经拔掉。

(*lpUsbFuncs->lpRegisterNotificationRoutine)(hDevice,

USBDeviceNotifications,pMouse);*fAcceptControl=TRUE;

returnTRUE;

}第二个函数是USBInstallDriver()函数,

一些基本定义如下:

constWCHARgcszRegisterClientDriverId[]=L"RegisterClientDriverID";

constWCHARgcszRegisterClientSettings[]=L"RegisterClientSettings";

constWCHARgcszUnRegisterClientDriverId[]=L"UnRegisterClientDriverID";

constWCHARgcszUnRegisterClientSettings[]=L"UnRegisterClientSettings";

constWCHARgcszMouseDriverId[]=L"Generic_Sample_Mouse_Driver";函数接口如下:

extern"C"BOOL

USBInstallDriver(

LPCWSTRszDriverLibFile)//@parm[IN]-ContainsclientdriverDLLname

{

BOOLfRet=FALSE;

HINSTANCEhInst=LoadLibrary(L"USBD.DLL");//注册USB设备信息

if(hInst)

{

LPREGISTER_CLIENT_DRIVER_IDpRegisterId=(LPREGISTER_CLIENT_DRIVER_ID)

GetProcAddress(hInst,gcszRegisterClientDriverId);LPREGISTER_CLIENT_SETTINGSpRegisterSettings=

(LPREGISTER_CLIENT_SETTINGS)GetProcAddress(hInst,

gcszRegisterClientSettings);if(pRegisterId&&pRegisterSettings)

{

USB_DRIVER_SETTINGSDriverSettings;DriverSettings.dwCount=sizeof(DriverSettings);//设置我们的特定的信息。

DriverSettings.dwVendorId=USB_NO_INFO;

DriverSettings.dwProductId=USB_NO_INFO;

DriverSettings.dwReleaseNumber=USB_NO_INFO;DriverSettings.dwDeviceClass=USB_NO_INFO;

DriverSettings.dwDeviceSubClass=USB_NO_INFO;

DriverSettings.dwDeviceProtocol=USB_NO_INFO;DriverSettings.dwInterfaceClass=0x03;//HID

DriverSettings.dwInterfaceSubClass=0x01;//bootdevice

DriverSettings.dwInterfaceProtocol=0x02;//mousefRet=(*pRegisterId)(gcszMouseDriverId);if(fRet)

{

fRet=(*pRegisterSettings)(szDriverLibFile,

gcszMouseDriverId,NULL,&DriverSettings);if(!

fRet)

{

//BUGBUGunregistertheClientDriversID

}

}

}

else

{

RETAILMSG(1,(TEXT("!

USBMouse:

ErrorgettingUSBDfunctionpointers\r\n")));

}

FreeLibrary(hInst);

}

returnfRet;

}

上述代码主要用于产生USB设备驱动程序需要的注册表信息,需要注意的是:

USB设备驱动程序不使用标准的注册表函数,而是使用RegisterClientDriverID()和RegisterClientSettings来注册相应的设备信息。

另外一个函数是USBUninstallDriver()函数,具体代码如下:

extern"C"BOOL

USBUnInstallDriver()

{

BOOLfRet=FALSE;

HINSTANCEhInst=LoadLibrary(L"USBD.DLL");if(hInst)

{

LPUN_REGISTER_CLIENT_DRIVER_IDpUnRegisterId=

(LPUN_REGISTER_CLIENT_DRIVER_ID)

GetProcAddress(hInst,gcszUnRegisterClientDriverId);LPUN_REGISTER_CLIENT_SETTINGSpUnRegisterSettings=

(LPUN_REGISTER_CLIENT_SETTINGS)GetProcAddress(hInst,

gcszUnRegisterClientSettings);if(pUnRegisterSettings)

{

USB_DRIVER_SETTINGSDriverSettings;DriverSettings.dwCount=sizeof(DriverSettings);

//必须填入与注册时相同的信息。

DriverSettings.dwVendorId=USB_NO_INFO;

DriverSettings.dwProductId=USB_NO_INFO;

DriverSettings.dwReleaseNumber=USB_NO_INFO;DriverSettings.dwDeviceClass=USB_NO_INFO;

DriverSettings.dwDeviceSubClass=USB_NO_INFO;

DriverSettings.dwDeviceProtocol=USB_NO_INFO;DriverSettings.dwInterfaceClass=0x03;//HID

DriverSettings.dwInterfaceSubClass=0x01;//bootdevice

DriverSettings.dwInterfaceProtocol=0x02;//mousefRet=(*pUnRegisterSettings)(gcszMouseDriverId,NULL,

&DriverSettings);

}if(pUnRegisterId)

{

BOOLfRetTemp=(*pUnRegisterId)(gcszMouseDriverId);

fRet=fRet?

fRetTemp:

fRet;

}

FreeLibrary(hInst);

}

returnfRet;

}

此函数主要用于删除USBInstallDriver()时创建的注册表信息,同样的它使用自己的函数接口UnRegisterClientDriverID()和UnRegisterClientSettings()来做相应的处理。

另外一个需要处理的注册的监控通知函数USBDeviceNotifications():

extern"C"BOOLUSBDeviceNotifications(LPVOIDlpvNotifyParameter,DWORDdwCode,

LPDWORD*dwInfo1,LPDWORD*dwInfo2,LPDWORD*dwInfo3,

LPDWORD*dwInfo4)

{

CMouse*pMouse=(CMouse*)lpvNotifyParameter;switch(dwCode)

{

caseUSB_CLOSE_DEVICE:

//删除相关的资源。

deletepMouse;

returnTRUE;

}

returnFALSE;

}

USB鼠标的类的定义如下:

classCMouse

{

public:

CMouse:

:

CMouse(USB_HANDLEhDevice,LPCUSB_FUNCSlpUsbFuncs,

LPCUSB_INTERFACElpInterface);

~CMouse();BOOLInitialize();

private:

//传输完毕调用的回调函数

staticDWORDCALLBACKMouseTransferCompleteStub(LPVOIDlpvNotifyParameter);

//中断处理函数

staticULONGCALLBACKCMouse:

:

MouseThreadStub(PVOIDcontext);

DWORDMouseTransferComplete();

DWORDMouseThread();BOOLSubmitInterrupt();

BOOLHandleInterrupt();BOOLm_fClosing;

BOOLm_fReadyForMouseEvents;HANDLEm_hEvent;

HANDLEm_hThread;USB_HANDLEm_hDevice;

USB_PIPEm_hInterruptPipe;

USB_TRANSFERm_hInterruptTransfer;LPCUSB_FUNCSm_lpUsbFuncs;

LPCUSB_INTERFACEm_pInterface;BOOLm_fPrevButton1;

BOOLm_fPrevButton2;

BOOLm_fPrevButton3;//数据接受缓冲区。

BYTEm_pbDataBuffer[8];

};具体实现如下:

//构造函数,初始化时调用

CMouse:

:

CMouse(USB_HANDLEhDevice,LPCUSB_FUNCSlpUsbFuncs,

LPCUSB_INTERFACElpInterface)

{

m_fClosing=FALSE;

m_fReadyForMouseEvents=FALSE;

m_hEvent=NULL;

m_hThread=NULL;m_hDevice=hDevice;

m_hInterruptPipe=NULL;

m_hInterruptTransfer=NULL;m_lpUsbFuncs=lpUsbFuncs;

m_pInterface=lpInterface;m_fPrevButton1=FALSE;

m_fPrevButton2=FALSE;

m_fPrevButton3=FALSE;memset(m_pbDataBuffer,0,sizeof(m_pbDataBuffer));

}//析构函数,用于清除申请的资源。

CMouse:

:

~CMouse()

{

//通知系统去关闭相关的函数接口。

m_fClosing=TRUE;//Wakeuptheconnectionthreadagainandgiveittimetodi

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

当前位置:首页 > 自然科学 > 物理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1