上位机与USB设备通信

首先使用CreateFile打开USB端口,CreateFile函数会返回一个HANDLE类型的句柄,该句柄可以用于下述的ReadFile和WriteFile之间的操作。   

[cpp]  view plain  copy
  1. ///  实现以指定的参数方式打开USB设备  
  2. CreateFile(devicePathName,   
  3.         GENERIC_READ | GENERIC_WRITE,   // 已读写方式打开  
  4.         FILE_SHARE_READ| FILE_SHARE_WRITE,   
  5.         0,   
  6.         OPEN_EXISTING // 打开已经存在的设备,当设备不存在时会返回错误  
  7.         FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED,    // 通信时的一些属性的设置、FILE_FLAG_OVERLAPPED表示已异步的方式打开设备  
  8. );  

 

 

这是最关键的一步是如何获取devicePathName, 幸好windows提供了解决的方法,

使用SetupDiGetClassDevs方法, 关于该方法在MSDN有非常详细的解答:

详细请参考以下网址:

<https://msdn.microsoft.com/en-us/library/windows/hardware/ff551069(v=vs.85).aspx>

[cpp]  view plain  copy
  1. </pre><pre name="code" class="cpp">  
[cpp]  view plain  copy
  1. // 关于HDEVINFO类型在setupapi.h文件中有定义  
  2. // typedef LPVOID HDEVINFO   
  3. // 表示是一个指向void类型的指针  
  4. // 如果调用成功,返回所有符合要求的设备信息的句柄  
  5. // 如果调用失败,返回INVALID_HANDLE_VALUE  
  6. HDEVINFO  SetupDiGetClassDevs(  
  7.     _In_opt_ constGUID   *ClassGuid,   // 指向device setup class或device interface class接口的guid,这个参数是可选的,                                  // 可以为NULL  
  8.     _In_opt_       PCTSTREnumerator,   // 指向一个一NULL结尾的字符串,可以是即插即用设备的枚举器ID。该参数也是可选的,                                                 // 可以为NULL  
  9.     _In_opt_       HWND  hwndParent,  
  10.     _In_           DWORD Flags  
  11. );  
  12.   
  13. // 调用方法    
  14.  deviceInfoSet = SetupDiGetClassDevs( * guid,  NUL, NULL,  DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);  
  15. if(deviceInfoSet == INVALID_HANDLE_VALUE)   // 失败  
  16. {}  
  17. else   // 成功  
  18. {}  

如果想要获取详细的错误信息,通过调用GetLastError可以获取。同时如果想要调用远程计算机上的设备的时候请使用SetupDiGetClassDevsEx。当调用SetupDiGetClassDevs成功后,调用SetupDiEnumDeviceInterface方法,枚举包含在设备信息集中的设备接口(enum the device information contained in the device详细请参考下述网址:https://msdn.microsoft.com/en-us/library/windows/hardware/ff551015(v=vs.85).aspx

[cpp]  view plain  copy
  1. 一般的调用流程如下所述  
  2.   
  3. SP_DEVICE_INTERFACE_DATA deviceInterfaceData;  
  4. deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);  
  5.   
  6. // 调用一次返回指定设备的硬件信息  
  7. while(SetupDiEnumDeviceInterface(deviceInfoSet,       // 设备信息集  
  8.             NULL,   
  9.             *guid,                  //设备接口的guid,与SetupDiGetClassDevs保持一致即可  
  10.             deviceIndex,            // 索引号,每调用一次该方法,加1,初始为0  
  11.             &deviceIntefaceData     //  SP_DEVICE_INTERFACE_DATA指针,记住在调用该方法之前必须设置cbSize的大小  
  12.         ))  
  13. {  
  14.     DWORD bufferSize;   
  15.     DWORD requiredSize;   
  16.     SetupDiGetDeviceInterfaceDetail(deviceInfoSet,   //   
  17.                 &deviceInterfaceData, // 表示SP_DEVICE_INTERFACE_DATA,指定DeviceInfoSet的接口,一般来说是SetupDiEnumDeviceInterface返回// 的内容  
  18.                 NULL, // SP_DEVICE_INTERFACE_DETAIL_DATA指针用来接收指定interface的信息  
  19.                 0, // SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小,当上一个参数为NULL时,该参数必须为0  
  20.                 &requiredSize, // 返回DeviceInterfaceDetailData的buffer 大小  
  21.                 NULL );  
  22. }  


// 第一次调用SetupDiGetDeviceInterfaceDetail方法后返回SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小

SP_DEVICE_INTERFACE_DETAIL_DATA detailBufferData;

detailBufferData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // 如果指定了这个参数,那么在使用之前必须设置cbSize参数的大小

SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, // &detailBufferData, // SP_DEVICE_INTERFACE_DETAIL_DATA指针用来接收指定interface的信息 requiredSize, // 上一次调用后返回的SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小 &requiredSize, // 返回DeviceInterfaceDetailData的buffer 大小 NULL );

如果SetupDiDeviceInterfaceDetail调用成功,detailBufferData包含有USB设备的路径信息。

}

关于SetupDiGetInterfaceDetail方法的详细请参考下述网址

<https://msdn.microsoft.com/en-us/library/windows/hardware/ff551120(v=vs.85).aspx>

还有一个非常重要的结构体需要介绍下。

SP_DEVICE_INTERFACE_DETAIL_DATA  

关于详细的资料可以参考以下网址:

<https://msdn.microsoft.com/en-us/library/windows/hardware/ff552343(v=vs.85).aspx>

 
 
  1. // 该结构体返回的DevicePath即设备的路径  
  1. typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA {  
  2.   DWORD cbSize;      // 表示该结构体的大小  
  3.   TCHAR DevicePath[ANYSIZE_ARRAY];    // 已NULL结尾,包括设备接口路径的字符串(device interface path)  
  4.                       // 这个路径信息可以传递给一些win32函数,例如 CreateFile:  
  5. } SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;  

备注: 在SetupDiXXX系列函数中,当SP_DEVICE_INTERFACE_DETAIL_DATA以参数的形式传递时,
函数会判断结构体的大小与成员cbSize是否一致,否则调用的函数会返回error。



 


/*

调用SetupDiGetClassDevs方法后,请调用SetupDiEnumDeviceInfo方法。该方法返回的SP_DEVINFO_DATA结构体指定了device information set集合中的设备元素信息。

*/


然后是读写USB设备,这有好几种方法,这里介绍两种:

①:ReadFile和WriteFile;

②:使用winusb_readpipe和winusb_writepipe方法;



最后当不再需要的时候一定要记得删除SetupDiGetClassDevs的返回信息,通过调用SetupDiDestroyDeviceInfoList函数即可,关于该函数的详细的介绍请参考下述MSDN网址

<https://msdn.microsoft.com/en-us/library/windows/hardware/ff550996(v=vs.85).aspx>



 因为晚上时间有限,写的有不正确的地方希望能指出来,不胜感激。

 

参考:

http://blog.csdn.NET/tody_guo/article/details/8675237

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值