WinUSB接口封装
2022-08-17
624
0
主要还是SetupAPI函数的封装
#include <SetupAPI.h>
//获取设备的实例路径
HRESULT
RetrieveDevicePath(
_Out_bytecap_(BufLen) LPTSTR DevicePath,
_In_ ULONG BufLen,
_Out_opt_ PBOOL FailureDeviceNotFound
);
HRESULT
OpenDevice(
_Out_ PDEVICE_DATA DeviceData,
_Out_opt_ PBOOL FailureDeviceNotFound
)
/*++
Routine description:
Open all needed handles to interact with the device.
If the device has multiple USB interfaces, this function grants access to
only the first interface.
If multiple devices have the same device interface GUID, there is no
guarantee of which one will be returned.
Arguments:
DeviceData - Struct filled in by this function. The caller should use the
WinusbHandle to interact with the device, and must pass the struct to
CloseDevice when finished.
FailureDeviceNotFound - TRUE when failure is returned due to no devices
found with the correct device interface (device not connected, driver
not installed, or device is disabled in Device Manager); FALSE
otherwise.
Return value:
HRESULT
--*/
{
HRESULT hr = S_OK;
BOOL bResult;
DeviceData->HandlesOpen = FALSE;
hr = RetrieveDevicePath(DeviceData->DevicePath,
sizeof(DeviceData->DevicePath),
FailureDeviceNotFound);
if (FAILED(hr)) {
return hr;
}
//CreateFile创建文件句柄
DeviceData->DeviceHandle = CreateFile(DeviceData->DevicePath,//所要打开的she别名
GENERIC_WRITE | GENERIC_READ,//访问模式
FILE_SHARE_WRITE | FILE_SHARE_READ,//共享模式
NULL,
OPEN_EXISTING,//创建方式
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,//文件属性和标志
NULL);
if (INVALID_HANDLE_VALUE == DeviceData->DeviceHandle) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
//WinUsb_Initialize为指定的file创建一个winusb句柄
bResult = WinUsb_Initialize(DeviceData->DeviceHandle,
&DeviceData->WinusbHandle);
if (FALSE == bResult) {
hr = HRESULT_FROM_WIN32(GetLastError());
CloseHandle(DeviceData->DeviceHandle);
return hr;
}
DeviceData->HandlesOpen = TRUE;
return hr;
}
VOID
CloseDevice(
_Inout_ PDEVICE_DATA DeviceData
)
/*++
Routine description:
Perform required cleanup when the device is no longer needed.
If OpenDevice failed, do nothing.
Arguments:
DeviceData - Struct filled in by OpenDevice
Return value:
None
--*/
{
if (FALSE == DeviceData->HandlesOpen) {
//
// Called on an uninitialized DeviceData
//
return;
}
WinUsb_Free(DeviceData->WinusbHandle);//释放WinUsb_Initialize创建的句柄
CloseHandle(DeviceData->DeviceHandle);//释放CreateFile创建的句柄
DeviceData->HandlesOpen = FALSE;
return;
}
HRESULT
RetrieveDevicePath(
_Out_bytecap_(BufLen) LPTSTR DevicePath,
_In_ ULONG BufLen,
_Out_opt_ PBOOL FailureDeviceNotFound
)
/*++
Routine description:
Retrieve the device path that can be used to open the WinUSB-based device.
If multiple devices have the same device interface GUID, there is no
guarantee of which one will be returned.
Arguments:
DevicePath - On successful return, the path of the device (use with CreateFile).
BufLen - The size of DevicePath's buffer, in bytes
FailureDeviceNotFound - TRUE when failure is returned due to no devices
found with the correct device interface (device not connected, driver
not installed, or device is disabled in Device Manager); FALSE
otherwise.
Return value:
HRESULT
--*/
{
BOOL bResult = FALSE;
HDEVINFO deviceInfo;
SP_DEVICE_INTERFACE_DATA interfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
ULONG length;
ULONG requiredLength=0;
HRESULT hr;
if (NULL != FailureDeviceNotFound) {
*FailureDeviceNotFound = FALSE;
}
//
// Enumerate all devices exposing the interface
/*获取“设备信息集”的句柄,“设备信息集”是一个阵列,
包含有关与指定的设备接口类匹配的所有安装的设备的信息。
阵列中名为“设备接口”的每个元素对应于一个已经安装并向系统注册的设备。
设备接口类通过传递在 INF 文件中定义的设备接口 GUID 进行标识。该函数将 HDEVINFO 句柄返回到设备信息集。*/
//
GUID guid;
CLSIDFromString(TEXT("{F72FE0D4-CBCB-407d-8814-9ED673D0DD6B}"), &guid);
deviceInfo = SetupDiGetClassDevs(&guid,//&GUID_DEVINTERFACE_USBApplication2,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfo == INVALID_HANDLE_VALUE) {
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
//
// Get the first interface (index 0) in the result set
//
/*枚举设备信息集中的设备接口并获取有关设备接口的信息。
此调用需要以下各项:
已初始化的调用程序分配的 SP_DEVICE_INTERFACE_DATA 结构,其 cbSize 成员设置为结构的大小。
步骤 1 中的 HDEVINFO 句柄。
在 INF 文件中定义的接口 GUID。*/
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
&guid,//&GUID_DEVINTERFACE_USBApplication2,
0,
&interfaceData);
if (FALSE == bResult) {
//
// We would see this error if no devices were found
//
if (ERROR_NO_MORE_ITEMS == GetLastError() &&
NULL != FailureDeviceNotFound) {
*FailureDeviceNotFound = TRUE;
}
hr = HRESULT_FROM_WIN32(GetLastError());
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
//
// Get the size of the path string
// We expect to get a failure with insufficient buffer
//
/*获取设备接口的详细信息*/
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&interfaceData,
NULL,
0,
&requiredLength,
NULL);
if (FALSE == bResult && ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
hr = HRESULT_FROM_WIN32(GetLastError());
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
//
// Allocate temporary space for SetupDi structure
//
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)
LocalAlloc(LMEM_FIXED, requiredLength);
if (NULL == detailData)
{
hr = E_OUTOFMEMORY;
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
length = requiredLength;
//
// Get the interface's path string
//
/*其中包含在SP_DEVICE_INTERFACE_DETAIL_DATA 结构的 DevicePath 成员中接收的设备路径。
将设备路径传递到 CreateFile 以获取设备的文件句柄。
确保设置了 FILE_FLAG_OVERLAPPED 标志,因为 WinUSB 信赖于此设置。*/
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo,
&interfaceData,
detailData,
length,
&requiredLength,
NULL);
if(FALSE == bResult)
{
hr = HRESULT_FROM_WIN32(GetLastError());
LocalFree(detailData);
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
//
// Give path to the caller. SetupDiGetDeviceInterfaceDetail ensured
// DevicePath is NULL-terminated.
//
hr = StringCbCopy(DevicePath,
BufLen,
detailData->DevicePath);
LocalFree(detailData);
SetupDiDestroyDeviceInfoList(deviceInfo);
return hr;
}
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936