Qingfu Wen
Qingfu Wen

Reputation: 51

WinUsb_Initialize error 8 - ERROR_NOT_ENOUGH_MEMORY

I am trying to read usb devices on Windows 10, following this two pages using-winusb-api-to-communicate-with-a-usb-device and WinUSBCommTest.cpp, but when I try to run this code, WinUsb_Initialize fails for windows error 8, ERROR_NOT_ENOUGH_MEMORY. And I don't know how to fix it, could anyone please help me out?

BOOL GetWinUSBHandle(HANDLE hDeviceHandle, PWINUSB_INTERFACE_HANDLE phWinUSBHandle)
{
  if (hDeviceHandle == INVALID_HANDLE_VALUE)
  {
    return FALSE;
  }

  BOOL bResult = WinUsb_Initialize(hDeviceHandle, phWinUSBHandle);
  if(!bResult)
  {
    //Error.
    printf("WinUsb_Initialize Error %d.", GetLastError());
    return FALSE;
  }

  return bResult;
}

BOOL GetDeviceHandle (GUID guidDeviceInterface, PHANDLE hDeviceHandle)
{
  if (guidDeviceInterface==GUID_NULL)
  {
    return FALSE;
  }

  BOOL bResult = TRUE;
  HDEVINFO hDeviceInfo;
  SP_DEVINFO_DATA DeviceInfoData;

  SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
  PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;

  ULONG requiredLength=0;

  LPTSTR lpDevicePath = NULL;

  DWORD index = 0;

  // Get information about all the installed devices for the specified
  // device interface class.
  hDeviceInfo = SetupDiGetClassDevs( 
    &guidDeviceInterface,
    NULL, 
    NULL,
    DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

  if (hDeviceInfo == INVALID_HANDLE_VALUE) 
  { 
    // ERROR 
    PTRACE("Error SetupDiGetClassDevs: %d.\n", GetLastError());
    goto done;
  }

  //Enumerate all the device interfaces in the device information set.
  DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

  for (index = 0; SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData); index++)
  {
    //Reset for this iteration
    if (lpDevicePath)
    {
      LocalFree(lpDevicePath);
    }
    if (pInterfaceDetailData)
    {
      LocalFree(pInterfaceDetailData);
    }

    deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

    //Get information about the device interface.
    bResult = SetupDiEnumDeviceInterfaces( 
      hDeviceInfo,
      &DeviceInfoData,
      &guidDeviceInterface,
      0, 
      &deviceInterfaceData);

    // Check if last item
    if (GetLastError () == ERROR_NO_MORE_ITEMS)
    {
      break;
    }

    //Check for some other error
    if (!bResult) 
    {
      printf("Error SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
      goto done;
    }

    //Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA
    //which we need to allocate, so we have to call this function twice.
    //First to get the size so that we know how much to allocate
    //Second, the actual call with the allocated buffer

    bResult = SetupDiGetDeviceInterfaceDetail(
      hDeviceInfo,
      &deviceInterfaceData,
      NULL, 0,
      &requiredLength,
      NULL);


    //Check for some other error
    if (!bResult) 
    {
      if ((ERROR_INSUFFICIENT_BUFFER==GetLastError()) && (requiredLength>0))
      {
        //we got the size, allocate buffer
        pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength);

        if (!pInterfaceDetailData) 
        { 
          // ERROR 
          printf("Error allocating memory for the device detail buffer.\n");
          goto done;
        }
      }
      else
      {
        printf("Error SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
        goto done;
      }
    }

    //get the interface detailed data
    pInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

    //Now call it with the correct size and allocated buffer
    bResult = SetupDiGetDeviceInterfaceDetail(
      hDeviceInfo,
      &deviceInterfaceData,
      pInterfaceDetailData,
      requiredLength,
      NULL,
      &DeviceInfoData);

    //Check for some other error
    if (!bResult) 
    {
      printf("Error SetupDiGetDeviceInterfaceDetail: %d.\n", GetLastError());
      goto done;
    }

    //copy device path

    size_t nLength = _tcslen(pInterfaceDetailData->DevicePath) + 1;  
    lpDevicePath = (TCHAR *) LocalAlloc (LPTR, nLength * sizeof(TCHAR));
    StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData->DevicePath);
    lpDevicePath[nLength-1] = 0;

    printf("Device path:  %s\n", lpDevicePath);

  }

  if (!lpDevicePath)
  {
    //Error.
    printf("Error %d.", GetLastError());
    goto done;
  }

  //Open the device
  *hDeviceHandle = CreateFile (
    lpDevicePath,
    GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);

  if (*hDeviceHandle == INVALID_HANDLE_VALUE)
  {
    //Error.
    printf("Error %d.", GetLastError());
    goto done;
  }



done:
  LocalFree(lpDevicePath);
  LocalFree(pInterfaceDetailData);    
  bResult = SetupDiDestroyDeviceInfoList(hDeviceInfo);

  return bResult;
}

Upvotes: 3

Views: 2143

Answers (1)

Renate
Renate

Reputation: 811

If you enumerate on GUID_DEVINTERFACE_USB_DEVICE you will get a device (vs a specific interface). If your thingy has multiple interfaces the WinUsb_Initialize will fail with an 8 - ERROR_NOT_ENOUGH_MEMORY. You need to enumerate on something specific like GUID_DEVINTERFACE_ANDROID. When you get the path, print it and you will see that it is not interface specific.

This is a GUID_DEVINTERFACE_USB_DEVICE (whole device)
\\?\usb#vid_1004&pid_62c6#vs12345678#{a5dcbf10-6530-11d2-901f-00c04fb951ed

This is a GUID_DEVINTERFACE_ANDROID (specific interface, #1)
\\?\usb#vid_1004&pid_62c6&mi_01#6&987654&1&0001#{f72fe0d4-cbcb-407d-8814-9ed673d0dd6b}

Upvotes: 5

Related Questions