Reputation: 51
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
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