【usb】winusb 接口设计分析

获取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_ReadIsochPipeWinUsb_WriteIsochPipe
  • 对于批量传输和中断传输,则统一使用一套接口。WinUsb_ReadPipe, WinUsb_WritePipe
  • 上述接口都通过Overlapped机制来控制同步传输或者异步传输。
  • 可以通过修改管道策略,个性化的控制管道的行为。
  • 除了上述接口,winusb也提供了各种请求,可以灵活使用。比如IOCTL_GENERICUSBFN_GET_INTERFACE_DESCRIPTOR_SET可以获取接口的所有端点信息等。

参考资料

Access a USB device by using WinUSB functions
用于管道策略修改的 WinUSB 函数

猜你喜欢

转载自blog.csdn.net/C2681595858/article/details/129171307