USB GUID

//*****************************************************************************

作者:Eragon

Bghttp://hi.baidu.com/nirvana68/                      

//*****************************************************************************

驱动程序安装成功后,应用程序的设计

VC6+DDK xp+DS3.2

 

 

驱动程序安装好后,应用程序要通过安装的驱动程序与设备的通信,但是应用程序怎么才能找到对应用的驱动程序呢?通过设备的GUID找到设备路径。

windows操作系统环境下,设备通常被当作特殊文件处理。要打开设备,就要知道该设备的路径,要找到设备的路径,要使用GUID来查找。

 

设备在安装时,windows安装器和相应设备的驱动程序负责将相应的设备与对应的GUID联系起来,并将GUID写入注册表,这样通过GUID(接口类GUID)就可以找到对应设备。

 

对于HID设备,因为它的驱动已经集成在操作系统中,在同一系统中GUID是一样的,但通常这个值在不同的系统下也许会不一样所以一般不直接使用这个GUID,而是使用一个API函数来获取(函数是void _stdcall HidD_GetHidGuid(Out LPGUID HidGuid).  而我们自己做的嵌入式设备,因为驱动是自己写的,所以GUID肯定不一样,而且这个GUID不会因为设备用在不同的操作系统上而改变,因为这个GUID在生成设备驱动的时候已经生成,就对应这个设备了,这个设备类GUID可以在每个驱动的interface.h文件中看到。我们就是要用这个文件中的GUID宏定义来查找已连接上设备,把系统中查到的设备列举出来,然后检查它的VIDPID以及设备版本号,看是不是要访问的设备,如果是,就可以对设备进行各种操作了,不是的话就循环下一个设备,直到找到或遍历完为止。

 

1.下面这个函数用来获取所有与ClassGuid指定的GUID相同的设备,当然对于HID设备在同一个pc机上可能会检测到多个,但是我们自己做的嵌入式设备,一般都是一个,要找到我们要的设备通过VIDPID以及设备版本号。该函数返回HDEVINFO句柄,这个句柄指向ClassGuid指定的所有设备的一个信息集合。这个句柄传给SetupDiEnumDeviceInterfaces()函数的第一个参数。

HDEVINFO SetupDiGetClassDevs(const GUID * ClassGuid,

                              PCTSTR     Enumerator                             

                              HWND      hwndParent

                              DWND      Flags

                              );

参数解析:

ClassGuid:设备的GUID指针。对于HID设备由函数void _stdcall HidD_GetHidGuid(Out LPGUID HidGuid)获得。对于自已做的嵌入式设备,因为驱动是我们自己写的,此设备类GUID在生成的驱动程序的interface.h中,是宏定义真接赋给此参数。

一个设备有两个GUID。一个是设备接口类GUIDDevice Interface class GUID);一个是安装类GUIDSetup class GUID)。

 

设备接口类GUID在注册表HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/

DeviceClasses子键下。如果一个驱动程序安装好了,但是不知道它的接口类GUID,可以通过VIDPID等到DeviceClasses子键下中反查其GUID,注意,在DeviceClasses反查时有两个GUID目录下包含我们要找的VIDPID。其中有一个GUID目录包含好多设备路径,这个不是,另一个GUID目录仅包含一个设备的信息,这个才是我们要找到路径,在这个GUID目录下点#号,在右边可以看到一个名为SymbolicLink的项,它的值就是打开设备时要用到的路径(即设备接口名)。如果是通过DS生成的驱动,可以直接在interface.h中找到设备接口类的GUID,然后在注册表中找到它的位置。(不过既然在interface.h中找到了设备接口类GUID,就没必要再在注册表中找了,是吧?!)。

 

安装类GUID是设备安装时,由Windows安装器读取驱动程序inf文件中的安装类GUID添加到注册表中。HID设备的inf文件在Windows/inf文件夹下的input.inf.安装类GUID在注册表的HKEY_LOCAL_MACHINE_/SYSTEM/CurrentControlSet/Control/Class子键下,单击这个子键可以在右边找到在inf文件中设置的类名,图标等。再展开这个子键,可以看到0000子键和Properties子键。在0000子键下,可以看到用DS设置的子键(向导设置注册表时,Subkey表单项,Subkey表单项用来设置Value Name 表单项设置的注册表项出现的位置),单击这个子键,在右边就可以看到DeviceNameDeviceName就是Value Name表单项的值)项的键值(就是Default Value表单项填写的值),当然在inf文件中也能找到,因为它记录在inf文件中。单击0000子键,可以看到右边有很多表项,其中DriverDesc就是设备在设备管理器中显示的名称,InfPath是安装驱动后备份在Windows/inf目录(属性为隐藏)下的inf文件.MatchingDeviceId就是要匹配的硬件ID。(DS向导的注册表项的设置中,Type表单项用于设置这个新建的注册表项的类型,REG_SZ是字符串类型,根据Default Value的值而定。Root表单项设置需要增加到哪个根键下。Value Name表单项用于设置新建的注册表项名,Subkey表单项用于设置新建注册表项所在的根键,Default Value表单项就是新建表项的键值。Driver Variable Name是该项在驱动程序中出现的变量名)

同样在CurrentControlSet/Enum子键下,也有安装类GUID

Enumerator:值为NULL表示将搜索全部设备;也可以指定一个设备的PnP名字的字符串,从而限制搜索。

hwndParent: 为父窗口的句柄,可以指定为NULL

Flags:位4的值为1时,指定使用接口类GUID,位11时,表示列举出已经连接的设备,否则将连接全部安装的设备;

当函数调用失败时,将返回INVALID_HANDLE_VALUE,调用GetLastError()函数可以获取失败的原因。

 

BOOL SetupDiEnumDeviceInterfaces (HDEVINFO   DeviceInfoSet,

                               PSP_DEVINFO_DATA   DeviceInfoData,

                               Const GUID *InterfaceClassGuid,

                               DWORD     MemberIndex,

                               PSP_DEVICE_INTERFACE_DATA   DeviceInterfaceData

                               );

参数信息:

DeviceInfoSetHDEVINFO类型):   SetupDiGetClassDevs函数返回的设备集合的句柄保存在这个参数中

DeviceInfoDataSP_DEVINFO_DATA类型的指针,SP_DEVINFO_DATA是结构体,PSP_DEVINFO_DATA此结构体的指针):强制获取某个设备的信息。通常为NULL  

InterfaceClassGuid:是指向设备的接口类GUID的指针,我们应用程序会指定一个变量来保存接口类GUID,假设为MyGUIDGUID类型),此时这个参数就会是&MyGuid。与第一个函数的参数值一样。

MemberIndex(设置为DWORD类型):用于控制现在SetupdinumDeviceInterfaces 函数获取的是哪一个设备的接口信息。0表示第一个设备,1为第二个设备。这个索引也是调用第一个函数时处理好的。索引的设备是第一个函数检测到的已连接的设备。当该值超过实际的索引数时,函数会返回零表示没找到与我们应用程序指定的VIDPID相符的设备;

DeviceInterfaceDataSP_DEVICE_INTERFACE_DATA类型指针):用来保存当前MemberIndex指定的设备的信息,在此函数调用前要先将该结构体变量的成员cbSize成员赋值为此结构体的大小。赋值的时候是&DeviceInterfaceData(定义:SP_DEVICE_INTERFACE_DATA   DeviceInterfaceData

此函数的返回值为BOOL类型

 

BOOL SetupDiGetDeviceInterfaceDetail(HDEVINFO DeviceInfoSet,

                                   PSP_DEVICE_INTERFACE_DATA                                       DeviceInterfaceData

                                   PSP_DEVICE_INTERFACE_DETALL_DATA   DeviceInterfaceDetailData,

                                   DWORD DeviceInterfaceDetailDataSize

                                   PDWORD RequiredSize

                                   PSP_DEVINFO_DATA   DeviceInfoData                   

                                   );

 

参数信息:

DeviceInfoSet:同样第一个函数的返回值;

DeviceInterfaceData:与第二个函数的最后一个参数一样

DeviceInterfaceDetailData: 比第二个参数获取的的设备信息还详细的设备信息,其中该结构体的成员变量DevicePath中就保存着用来打开设备的路径(或者叫设备接口名),该参数给API函数CreatFile以打开指定设备。在调用此函数之前,先要将该结构体的成员变量cbSize的值赋为该结构体的大小

DeviceInterfaceDetailDataSize:第三个参数所需的buffer大小。

RequiredSize:指定保存更详细设备信息所需要的buffer大小。

DeviceInfoData:是一个用来接收该接口所在设备的设备信息的结构体指针。通常值为NULL,表示该参数无效;

该函数调用两次,第一次获取保存设备详细信息buffer的大小,即RequiredSize,这时函数的第34个参数为NULL,等获取到buffer大小后,再次调用该函数此时第126都不变,第三个参数为buffer的地址,第四个为buffer大小。

记住当使用完后要销毁信息集合调用SetupDiDestroyDeviceInfoList(信息集合句柄);实现。

猜你喜欢

转载自blog.csdn.net/qq229596421/article/details/79611853
usb