上位机与USB设备通信
2015-05-26 23:16
316 查看
首先使用CreateFile打开USB端口,CreateFile函数会返回一个HANDLE类型的句柄,该句柄可以用于下述的ReadFile和WriteFile之间的操作。
这是最关键的一步是如何获取devicePathName, 幸好windows提供了解决的方法,
使用SetupDiGetClassDevs方法, 关于该方法在MSDN有非常详细的解答:
详细请参考以下网址:
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff551069(v=vs.85).aspx>
如果想要获取详细的错误信息,通过调用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
// 第一次调用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>
[/code]
备注: 在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
/// 实现以指定的参数方式打开USB设备 CreateFile(devicePathName, GENERIC_READ | GENERIC_WRITE, // 已读写方式打开 FILE_SHARE_READ| FILE_SHARE_WRITE, 0, OPEN_EXISTING // 打开已经存在的设备,当设备不存在时会返回错误 FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED, // 通信时的一些属性的设置、FILE_FLAG_OVERLAPPED表示已异步的方式打开设备 );
这是最关键的一步是如何获取devicePathName, 幸好windows提供了解决的方法,
使用SetupDiGetClassDevs方法, 关于该方法在MSDN有非常详细的解答:
详细请参考以下网址:
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff551069(v=vs.85).aspx>
</pre><pre name="code" class="cpp">
// 关于HDEVINFO类型在setupapi.h文件中有定义 // typedef LPVOID HDEVINFO // 表示是一个指向void类型的指针 // 如果调用成功,返回所有符合要求的设备信息的句柄 // 如果调用失败,返回INVALID_HANDLE_VALUE HDEVINFO SetupDiGetClassDevs( _In_opt_ constGUID *ClassGuid, // 指向device setup class或device interface class接口的guid,这个参数是可选的, // 可以为NULL _In_opt_ PCTSTREnumerator, // 指向一个一NULL结尾的字符串,可以是即插即用设备的枚举器ID。该参数也是可选的, // 可以为NULL _In_opt_ HWND hwndParent, _In_ DWORD Flags ); // 调用方法 deviceInfoSet = SetupDiGetClassDevs( * guid, NUL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if(deviceInfoSet == INVALID_HANDLE_VALUE) // 失败 {} else // 成功 {}
如果想要获取详细的错误信息,通过调用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
一般的调用流程如下所述 SP_DEVICE_INTERFACE_DATA deviceInterfaceData; deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // 调用一次返回指定设备的硬件信息 while(SetupDiEnumDeviceInterface(deviceInfoSet, // 设备信息集 NULL, *guid, //设备接口的guid,与SetupDiGetClassDevs保持一致即可 deviceIndex, // 索引号,每调用一次该方法,加1,初始为0 &deviceIntefaceData // SP_DEVICE_INTERFACE_DATA指针,记住在调用该方法之前必须设置cbSize的大小 )) { DWORD bufferSize; DWORD requiredSize; SetupDiGetDeviceInterfaceDetail(deviceInfoSet, // &deviceInterfaceData, // 表示SP_DEVICE_INTERFACE_DATA,指定DeviceInfoSet的接口,一般来说是SetupDiEnumDeviceInterface返回// 的内容 NULL, // SP_DEVICE_INTERFACE_DETAIL_DATA指针用来接收指定interface的信息 0, // SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小,当上一个参数为NULL时,该参数必须为0 &requiredSize, // 返回DeviceInterfaceDetailData的buffer 大小 NULL ); }
// 第一次调用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>
// 该结构体返回的DevicePath即设备的路径
typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA { DWORD cbSize; // 表示该结构体的大小 TCHAR DevicePath[ANYSIZE_ARRAY]; // 已NULL结尾,包括设备接口路径的字符串(device interface path) // 这个路径信息可以传递给一些win32函数,例如 CreateFile: } SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;
[/code]
备注: 在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
相关文章推荐
- LabVIEW中与USB设备进行通信1
- 上位机与打印设备通信模型
- LibUSB通过SetReport()请求与USBHID设备通信
- 用户态应用程序直接与USB设备通信(不需要USB设备Driver)
- LabVIEW中与USB设备进行通信2
- Windows主机端与自定义USB HID设备通信详解
- Windows主机端与自定义USB HID设备通信详解 - Windows - 阿Min的BLOG
- 根据GUID和PID和USB设备通信的方法
- Windows主机端与自定义USB HID设备通信详解
- Windows主机端与自定义USB HID设备通信详解
- 两台android设备间通过OTG-USB连接,实现通信(android设备间的通信)
- USB CDC通信设备子类概述
- 两台android设备间通过OTG-USB连接,实现通信(android设备间的通信)
- Windows主机端与自定义USB HID设备通信详解
- stm32的usb与上位机通过中断传输进行通信控制led--LibUsbDotNet
- 从调试数据分析USB通信协议——USB键盘鼠标【HID类设备】(四)
- Windows主机端与自定义USB HID设备通信详解
- 关于Android设备USBHID通信控制传输相关接口说明
- 关于C#上位机的usb_hid通信相关问题说明
- 遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题