USB API Overview
The Windows USB API provides developers with a set of functions and structures to interact with USB devices at both the generic and device‑specific levels. It includes the SetupDi functions for device enumeration, the WinUSB API for data transfers, and various helper structures.
Device Setup (SetupDi)
SetupDi functions allow you to enumerate, query, and manage USB devices installed on the system.
| Function | Description |
|---|---|
SetupDiGetClassDevs | Retrieves a device information set for a specified class. |
SetupDiEnumDeviceInfo | Enumerates devices in a device information set. |
SetupDiGetDeviceRegistryProperty | Obtains a device’s registry property. |
SetupDiOpenDeviceInterface | Opens a handle to a device interface. |
WinUSB Functions
WinUSB offers a high‑level interface for reading and writing to USB endpoints.
| Function | Description |
|---|---|
WinUsb_Initialize | Initializes the WinUSB interface for a device. |
WinUsb_ReadPipe | Reads data from a specified pipe. |
WinUsb_WritePipe | Writes data to a specified pipe. |
WinUsb_ControlTransfer | Performs a control transfer on the default pipe. |
WinUsb_GetDescriptor | Retrieves a descriptor from the device. |
Sample Code
The following example demonstrates how to enumerate a USB device and perform a simple bulk read using WinUSB.
#include <windows.h>
#include <winusb.h>
#include <setupapi.h>
#include <stdio.h>
int main() {
GUID guid = {0xA5DCBF10L,0x6530,0x11D2,{0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED}}; // GUID_DEVINTERFACE_USB_DEVICE
HDEVINFO devInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (devInfo == INVALID_HANDLE_VALUE) return 1;
SP_DEVICE_INTERFACE_DATA ifaceData;
ifaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
if (!SetupDiEnumDeviceInterfaces(devInfo, NULL, &guid, 0, &ifaceData)) return 1;
// Get required buffer size
DWORD needed;
SetupDiGetDeviceInterfaceDetail(devInfo, &ifaceData, NULL, 0, &needed, NULL);
PSP_DEVICE_INTERFACE_DETAIL_DATA detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(needed);
detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(devInfo, &ifaceData, detail, needed, NULL, NULL)) return 1;
HANDLE device = CreateFile(detail->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (device == INVALID_HANDLE_VALUE) return 1;
WINUSB_INTERFACE_HANDLE winUsb;
if (!WinUsb_Initialize(device, &winUsb)) return 1;
UCHAR buffer[64];
ULONG transferred;
WinUsb_ReadPipe(winUsb, 0x81, buffer, sizeof(buffer), &transferred, NULL);
printf("Read %lu bytes\\n", transferred);
WinUsb_Free(winUsb);
CloseHandle(device);
free(detail);
SetupDiDestroyDeviceInfoList(devInfo);
return 0;
}
For a complete guide, see the USB Samples page.