rajhlinux

WinUSB C++ API

Jan 24th, 2025
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.46 KB | Source Code | 0 0
  1. #include <windows.h>
  2. #include <winusb.h>
  3. #include <cfgmgr32.h>
  4. #include <tchar.h>
  5. #include <strsafe.h>
  6. #include <stdio.h>
  7.  
  8. // Define the correct device interface GUID
  9. DEFINE_GUID(GUID_DEVINTERFACE_WinUSBApplication,
  10.     0x99DA2DEC, 0xC919, 0x4F9D, 0x93, 0x84, 0xDA, 0xA7, 0xEB, 0xBD, 0x40, 0xEC);
  11.  
  12. typedef struct _DEVICE_DATA {
  13.     WINUSB_INTERFACE_HANDLE WinusbHandle;
  14.     HANDLE                  DeviceHandle;
  15.     TCHAR                   DevicePath[MAX_PATH];
  16.     UCHAR                   IsochronousInPipe;
  17. } DEVICE_DATA, *PDEVICE_DATA;
  18.  
  19. HRESULT OpenDevice(PDEVICE_DATA DeviceData, PBOOL FailureDeviceNotFound);
  20. VOID CloseDevice(PDEVICE_DATA DeviceData);
  21. BOOL ReadFromIsochronousEndpoint(PDEVICE_DATA DeviceData, UCHAR* buffer, ULONG bufferLength);
  22. HRESULT RetrieveDevicePath(LPTSTR DevicePath, ULONG BufLen, PBOOL FailureDeviceNotFound);
  23. BOOL QueryDeviceEndpoints(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* IsochronousInPipe);
  24.  
  25. HRESULT OpenDevice(PDEVICE_DATA DeviceData, PBOOL FailureDeviceNotFound)
  26. {
  27.     HRESULT hr = RetrieveDevicePath(DeviceData->DevicePath, sizeof(DeviceData->DevicePath), FailureDeviceNotFound);
  28.     if (FAILED(hr)) {
  29.         _tprintf(_T("Failed to retrieve device path. HRESULT: 0x%x\n"), hr);
  30.         return hr;
  31.     }
  32.  
  33.     _tprintf(_T("Device Path: %s\n"), DeviceData->DevicePath);
  34.  
  35.     DeviceData->DeviceHandle = CreateFile(DeviceData->DevicePath, GENERIC_WRITE | GENERIC_READ,
  36.         FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING,
  37.         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
  38.  
  39.     if (INVALID_HANDLE_VALUE == DeviceData->DeviceHandle) {
  40.         _tprintf(_T("Failed to open device. Error: %d\n"), GetLastError());
  41.         return HRESULT_FROM_WIN32(GetLastError());
  42.     }
  43.  
  44.     if (!WinUsb_Initialize(DeviceData->DeviceHandle, &DeviceData->WinusbHandle)) {
  45.         hr = HRESULT_FROM_WIN32(GetLastError());
  46.         CloseHandle(DeviceData->DeviceHandle);
  47.         _tprintf(_T("WinUsb_Initialize failed. Error: %d\n"), GetLastError());
  48.         return hr;
  49.     }
  50.  
  51.     return S_OK;
  52. }
  53.  
  54. VOID CloseDevice(PDEVICE_DATA DeviceData)
  55. {
  56.     if (DeviceData->WinusbHandle) {
  57.         WinUsb_Free(DeviceData->WinusbHandle);
  58.         DeviceData->WinusbHandle = NULL;
  59.     }
  60.     if (DeviceData->DeviceHandle) {
  61.         CloseHandle(DeviceData->DeviceHandle);
  62.         DeviceData->DeviceHandle = NULL;
  63.     }
  64. }
  65.  
  66. BOOL ReadFromIsochronousEndpoint(PDEVICE_DATA DeviceData, UCHAR* buffer, ULONG bufferLength)
  67. {
  68.     ULONG frameNumber = 0;
  69.     ULONG numberOfPackets = 128; // Adjust size if needed
  70.     USBD_ISO_PACKET_DESCRIPTOR isoPacketDescriptors[128] = { 0 }; // Adjust size if needed
  71.     OVERLAPPED overlapped = { 0 };
  72.     overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  73.  
  74.     if (!overlapped.hEvent) {
  75.         printf("Failed to create event for overlapped I/O.\n");
  76.         return FALSE;
  77.     }
  78.  
  79.     WINUSB_ISOCH_BUFFER_HANDLE isochBuffer;
  80.     BOOL result = WinUsb_RegisterIsochBuffer(DeviceData->WinusbHandle, DeviceData->IsochronousInPipe,
  81.                                              buffer, bufferLength, &isochBuffer);
  82.     if (!result) {
  83.         printf("Error registering isochronous buffer: %d.\n", GetLastError());
  84.         CloseHandle(overlapped.hEvent);
  85.         return FALSE;
  86.     }
  87.  
  88.     result = WinUsb_ReadIsochPipe(isochBuffer, 0, bufferLength, &frameNumber,
  89.                                   numberOfPackets, isoPacketDescriptors, &overlapped);
  90.     if (!result && GetLastError() != ERROR_IO_PENDING) {
  91.         printf("Error reading from isochronous endpoint: %d.\n", GetLastError());
  92.         WinUsb_UnregisterIsochBuffer(isochBuffer);
  93.         CloseHandle(overlapped.hEvent);
  94.         return FALSE;
  95.     }
  96.  
  97.     // Wait for the read operation to complete
  98.     result = GetOverlappedResult(DeviceData->DeviceHandle, &overlapped, &frameNumber, TRUE);
  99.     if (!result) {
  100.         printf("Error in overlapped result: %d.\n", GetLastError());
  101.         WinUsb_UnregisterIsochBuffer(isochBuffer);
  102.         CloseHandle(overlapped.hEvent);
  103.         return FALSE;
  104.     }
  105.  
  106.     WinUsb_UnregisterIsochBuffer(isochBuffer);
  107.     CloseHandle(overlapped.hEvent);
  108.  
  109.     // Print the data read from the isochronous endpoint
  110.     for (ULONG i = 0; i < frameNumber; i++) {
  111.         printf("Packet %lu: Status = %d, Length = %lu\n", i, isoPacketDescriptors[i].Status, isoPacketDescriptors[i].Length);
  112.     }
  113.  
  114.     return TRUE;
  115. }
  116.  
  117. HRESULT RetrieveDevicePath(LPTSTR DevicePath, ULONG BufLen, PBOOL FailureDeviceNotFound)
  118. {
  119.     if (FailureDeviceNotFound) *FailureDeviceNotFound = FALSE;
  120.  
  121.     ULONG length = 0;
  122.     CONFIGRET cr = CM_Get_Device_Interface_List_Size(&length, (LPGUID)&GUID_DEVINTERFACE_WinUSBApplication,
  123.                                                      NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
  124.     if (cr != CR_SUCCESS) return HRESULT_FROM_WIN32(CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA));
  125.  
  126.     PTSTR DeviceInterfaceList = (PTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, length * sizeof(TCHAR));
  127.     if (!DeviceInterfaceList) return E_OUTOFMEMORY;
  128.  
  129.     cr = CM_Get_Device_Interface_List((LPGUID)&GUID_DEVINTERFACE_WinUSBApplication, NULL, DeviceInterfaceList,
  130.                                       length, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
  131.     if (cr != CR_SUCCESS) {
  132.         HeapFree(GetProcessHeap(), 0, DeviceInterfaceList);
  133.         return HRESULT_FROM_WIN32(CM_MapCrToWin32Err(cr, ERROR_INVALID_DATA));
  134.     }
  135.  
  136.     if (*DeviceInterfaceList == TEXT('\0')) {
  137.         if (FailureDeviceNotFound) *FailureDeviceNotFound = TRUE;
  138.         HeapFree(GetProcessHeap(), 0, DeviceInterfaceList);
  139.         return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  140.     }
  141.  
  142.     HRESULT hr = StringCbCopy(DevicePath, BufLen, DeviceInterfaceList);
  143.     HeapFree(GetProcessHeap(), 0, DeviceInterfaceList);
  144.     return hr;
  145. }
  146.  
  147.  
  148. BOOL QueryDeviceEndpointsDirect(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* IsochronousInPipe, UCHAR desiredAltSetting, UCHAR endpointIndex)
  149. {
  150.     USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
  151.  
  152.     // Set the specified alternate setting
  153.     if (!WinUsb_SetCurrentAlternateSetting(hDeviceHandle, desiredAltSetting)) {
  154.         printf("Failed to set alternate setting %d: %d\n", desiredAltSetting, GetLastError());
  155.         return FALSE;
  156.     }
  157.  
  158.     // Query the interface descriptor for the specified alternate setting
  159.     if (!WinUsb_QueryInterfaceSettings(hDeviceHandle, desiredAltSetting, &InterfaceDescriptor)) {
  160.         printf("Failed to query interface settings for alternate setting %d: %d\n", desiredAltSetting, GetLastError());
  161.         return FALSE;
  162.     }
  163.  
  164.     printf("Alternate Setting %d:\n", desiredAltSetting);
  165.     printf("  Interface Number: %d\n", InterfaceDescriptor.bInterfaceNumber);
  166.     printf("  Number of Endpoints: %d\n", InterfaceDescriptor.bNumEndpoints);
  167.     printf("  Interface Class: %02X\n", InterfaceDescriptor.bInterfaceClass);
  168.     printf("  Interface SubClass: %02X\n", InterfaceDescriptor.bInterfaceSubClass);
  169.     printf("  Interface Protocol: %02X\n", InterfaceDescriptor.bInterfaceProtocol);
  170.  
  171.     WINUSB_PIPE_INFORMATION Pipe;
  172.  
  173.     // Query the pipe for the known endpoint index
  174.     if (!WinUsb_QueryPipe(hDeviceHandle, desiredAltSetting, endpointIndex, &Pipe)) {
  175.         printf("    Failed to query pipe %d: %d\n", endpointIndex, GetLastError());
  176.         return FALSE;
  177.     }
  178.  
  179.     printf("    Endpoint %d: PipeType = %d, PipeId = %d\n", endpointIndex, Pipe.PipeType, Pipe.PipeId);
  180.  
  181.     // Ensure the endpoint is Isochronous and IN direction
  182.     if (Pipe.PipeType == UsbdPipeTypeIsochronous && USB_ENDPOINT_DIRECTION_IN(Pipe.PipeId)) {
  183.         *IsochronousInPipe = Pipe.PipeId;
  184.         return TRUE;
  185.     }
  186.  
  187.     printf("No suitable isochronous IN endpoint found.\n");
  188.     return FALSE;
  189. }
  190.  
  191.  
  192.  
  193.  
  194.  
  195. int _tmain()
  196. {
  197.     DEVICE_DATA deviceData = {};
  198.     BOOL noDevice = FALSE;
  199.  
  200.     HRESULT hr = OpenDevice(&deviceData, &noDevice);
  201.     if (FAILED(hr)) {
  202.         if (noDevice) wprintf(L"Device not connected or driver not installed\n");
  203.         else wprintf(L"Failed to open device. HRESULT: 0x%x\n", hr);
  204.         return 0;
  205.     }
  206.  
  207.     UCHAR buffer[1024];
  208. if (!QueryDeviceEndpointsDirect(deviceData.WinusbHandle, &deviceData.IsochronousInPipe, /*desiredAltSetting*/ 1, /*endpointIndex*/ 0)) {
  209.     wprintf(L"Failed to query device endpoints\n");
  210.     CloseDevice(&deviceData);
  211.     return 0;
  212. }
  213.  
  214.     if (ReadFromIsochronousEndpoint(&deviceData, buffer, sizeof(buffer))) {
  215.         printf("Data successfully read from isochronous endpoint\n");
  216.     }
  217.  
  218.     CloseDevice(&deviceData);
  219.     return 0;
  220. }
Advertisement
Add Comment
Please, Sign In to add comment