获取interfaceHandle
- 首先使用
CreateFile
获取设备操作句柄,DeviceHandle
。 - 然后使用
WinUsb_Initialize
获取接口操作句柄,默认获取设备的第一个接口的操作句柄。
控制传输
BOOL WinUsb_ControlTransfer(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] WINUSB_SETUP_PACKET SetupPacket,
[out] PUCHAR Buffer,
[in] ULONG BufferLength,
[out, optional] PULONG LengthTransferred,
[in, optional] LPOVERLAPPED Overlapped
);
InterfaceHandle
就是通过上述WinUsb_Initialize
获取到的 接口操作句柄。SetupPacket
对应usb协议里面的Setup 包。Buffer
要发送或者接收数据的缓冲区。BufferLength
缓冲区大小。LengthTransferred
实际发送或者接收的数据长度。Overlapped
用来进行异步传输,如果这个字段没有被设置,那么该接口是同步接口,等本次传输全部完成后,函数才会返回。否则函数立即返回,等传输完成后,通过Overlapped
机制进行回调通知。
Overlapped机制简介
获取端点信息
获取接口信息
BOOL WinUsb_QueryInterfaceSettings(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] UCHAR AlternateInterfaceNumber,
[out] PUSB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor
);
USB_INTERFACE_DESCRIPTOR
对应USB协议里面的标准接口描述符。通过该参数我们可以知道,接口有多少个端点。
获取端点信息
BOOL WinUsb_QueryPipe(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] UCHAR AlternateInterfaceNumber,
[in] UCHAR PipeIndex,
[out] PWINUSB_PIPE_INFORMATION PipeInformation
);
typedef struct _WINUSB_PIPE_INFORMATION {
USBD_PIPE_TYPE PipeType;
UCHAR PipeId;
USHORT MaximumPacketSize;
UCHAR Interval;
} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
知道有多少端点后,我们就可以逐个获取端点信息。
WINUSB_PIPE_INFORMATION
通过该参数,我们可以知道pipe的类型(控制传输/批量传输/中断传输/等时传输),以及pipe的方向(host-to-device或者device-to-host)。
进行批量(bulk)传输和中断(interrupt)传输
- 通过上面端点信息,我们可以知道该端点支持什么传输类型以及其数据传输的方向。接着我们就可以根据端点的这些信息进行数据传输。
BOOL WinUsb_ReadPipe(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] UCHAR PipeID,
[out] PUCHAR Buffer,
[in] ULONG BufferLength,
[out, optional] PULONG LengthTransferred,
[in, optional] LPOVERLAPPED Overlapped
);
BOOL WinUsb_WritePipe(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] UCHAR PipeID,
[in] PUCHAR Buffer,
[in] ULONG BufferLength,
[out, optional] PULONG LengthTransferred,
[in, optional] LPOVERLAPPED Overlapped
);
- 中断传输和批量传输都使用上面的两个接口传输数据。根据端点信息,我们可以知道管道的传输方向。如果方向是host-to-device,那么就是写,也就是我们需要用
WinUsb_WritePipe
接口向该端点写数据。 - 如果方向是device-to-host,那么我们可以用
WinUsb_ReadPipe
接口从端点读取数据。 - 和控制传输一样,这两个接口通过
Overlapped
机制来控制同步或者异步传输。
管道策略
- 所谓管道策略就是,可以根据需要控制端点的行为。比如设置传输超时时间。或者在发送请求时,如果请求包的大小刚好是端点能发送的最大长度的整数倍,是否需要发送一个零长度的包,等等。接口如下:
BOOL WinUsb_SetPipePolicy(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] UCHAR PipeID,
[in] ULONG PolicyType,
[in] ULONG ValueLength,
[in] PVOID Value
);
BOOL WinUsb_GetPipePolicy(
[in] WINUSB_INTERFACE_HANDLE InterfaceHandle,
[in] UCHAR PipeID,
[in] ULONG PolicyType,
[in, out] PULONG ValueLength,
[out] PVOID Value
);
总结
- 对于控制传输和等时传输,winusb分别提供了传输接口。
WinUsb_ControlTransfer
,WinUsb_ReadIsochPipe
,WinUsb_WriteIsochPipe
。 - 对于批量传输和中断传输,则统一使用一套接口。
WinUsb_ReadPipe
,WinUsb_WritePipe
。 - 上述接口都通过
Overlapped
机制来控制同步传输或者异步传输。 - 可以通过修改管道策略,个性化的控制管道的行为。
- 除了上述接口,winusb也提供了各种请求,可以灵活使用。比如
IOCTL_GENERICUSBFN_GET_INTERFACE_DESCRIPTOR_SET
可以获取接口的所有端点信息等。
参考资料
Access a USB device by using WinUSB functions
用于管道策略修改的 WinUSB 函数