Refs #1407. Merged USB bulk library code into LibOpenBLT to remove dependency on UsbBulkLib.dll.

git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@940 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
Frank Voorburg 2022-02-08 22:43:42 +00:00
parent e9482079a4
commit 6706102797
4 changed files with 331 additions and 155 deletions

View File

@ -177,7 +177,7 @@ if(BUILD_SHARED)
target_link_libraries(openblt_shared usb-1.0 dl "-Wl,-rpath,.") target_link_libraries(openblt_shared usb-1.0 dl "-Wl,-rpath,.")
elseif(WIN32) elseif(WIN32)
# Link the Winsock library # Link the Winsock library
target_link_libraries(openblt_shared ws2_32) target_link_libraries(openblt_shared ws2_32 winusb setupapi)
endif(UNIX) endif(UNIX)
if(CMAKE_C_COMPILER_ID MATCHES MSVC) if(CMAKE_C_COMPILER_ID MATCHES MSVC)
# Microsoft Visual Studio does not add "lib" to the name of the DLL, whereas GCC # Microsoft Visual Studio does not add "lib" to the name of the DLL, whereas GCC

View File

@ -34,56 +34,29 @@
#include <stddef.h> /* for NULL declaration */ #include <stddef.h> /* for NULL declaration */
#include <stdbool.h> /* for boolean type */ #include <stdbool.h> /* for boolean type */
#include <windows.h> /* for Windows API */ #include <windows.h> /* for Windows API */
#include <SetupAPI.h> /* for Windows setup and device installer */
#include <winusb.h> /* for Windows interface to winusb.dll */
#include <strsafe.h> /* for safer C string library */
#include "usbbulk.h" /* USB bulk driver */ #include "usbbulk.h" /* USB bulk driver */
/**************************************************************************************** /****************************************************************************************
* Macro definitions * Macro definitions
****************************************************************************************/ ****************************************************************************************/
/* USB bulk driver return values. */ /* USB bulk library return values. */
#define UBL_ERROR (0u) #define UBL_OKAY (0U)
#define UBL_OKAY (1u) #define UBL_ERROR (1U)
#define UBL_TIMEOUT (2U)
/****************************************************************************************
* Type definitions
****************************************************************************************/
/* USB bulk driver interface functions. */
typedef uint8_t (__stdcall * tUsbBulkLibFuncOpen)(LPGUID guid);
typedef void (__stdcall * tUsbBulkLibFuncClose)(void);
typedef uint8_t (__stdcall * tUsbBulkLibFuncTransmit)(uint8_t * data, uint16_t len);
typedef uint8_t (__stdcall * tUsbBulkLibFuncReceive)(uint8_t * data, uint16_t len, uint32_t timeout);
/*************************************************************************************** /***************************************************************************************
* Function prototypes * Function prototypes
****************************************************************************************/ ****************************************************************************************/
/* USB bulk driver handling. */ /* USB bulk library interface. */
static void UsbBulkLibLoadDll(void); static uint8_t UblOpen(LPCGUID guid);
static void UsbBulkLibUnloadDll(void); static void UblClose(void);
static uint8_t UsbBulkLibFuncOpen(LPGUID guid); static uint8_t UblTransmit(uint8_t* data, uint16_t len);
static void UsbBulkLibFuncClose(void); static uint8_t UblReceive(uint8_t* data, uint16_t len, uint32_t timeout);
static uint8_t UsbBulkLibFuncTransmit(uint8_t * data, uint16_t len);
static uint8_t UsbBulkLibFuncReceive(uint8_t * data, uint16_t len, uint32_t timeout);
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Handle to the USB bulk driver dynamic link library. */
static HINSTANCE usbBulkLibDllHandle;
/** \brief Function pointer to the USB bulk driver library Open function. */
static tUsbBulkLibFuncOpen usbBulkLibFuncOpenPtr;
/** \brief Function pointer to the USB bulk driver library Close function. */
static tUsbBulkLibFuncClose usbBulkLibFuncClosePtr;
/** \brief Function pointer to the USB bulk driver library Transmit function. */
static tUsbBulkLibFuncTransmit usbBulkLibFuncTransmitPtr;
/** \brief Function pointer to the USB bulk driver library Receive function. */
static tUsbBulkLibFuncReceive usbBulkLibFuncReceivePtr;
/************************************************************************************//** /************************************************************************************//**
@ -92,15 +65,7 @@ static tUsbBulkLibFuncReceive usbBulkLibFuncReceivePtr;
****************************************************************************************/ ****************************************************************************************/
void UsbBulkInit(void) void UsbBulkInit(void)
{ {
/* Initialize locals. */ /* Nothing to do here so just leave it empty. */
usbBulkLibDllHandle = NULL;
/* Reset library function pointers. */
usbBulkLibFuncOpenPtr = NULL;
usbBulkLibFuncClosePtr = NULL;
usbBulkLibFuncTransmitPtr = NULL;
usbBulkLibFuncReceivePtr = NULL;
/* Perform initialization of USB bulk driver API. */
UsbBulkLibLoadDll();
} /*** end of UsbBulkInit ***/ } /*** end of UsbBulkInit ***/
@ -110,8 +75,7 @@ void UsbBulkInit(void)
****************************************************************************************/ ****************************************************************************************/
void UsbBulkTerminate(void) void UsbBulkTerminate(void)
{ {
/* Perform termination of USB bulk driver API. */ /* Nothing to do here so just leave it empty. */
UsbBulkLibUnloadDll();
} /*** end of UsbBulkTerminate ***/ } /*** end of UsbBulkTerminate ***/
@ -130,7 +94,7 @@ bool UsbBulkOpen(void)
bool result = false; bool result = false;
/* Open the connection with the USB device. */ /* Open the connection with the USB device. */
if (UsbBulkLibFuncOpen(&deviceGuidOpenBLT) == UBL_OKAY) if (UblOpen(&deviceGuidOpenBLT) == UBL_OKAY)
{ {
result = true; result = true;
} }
@ -146,7 +110,7 @@ bool UsbBulkOpen(void)
void UsbBulkClose(void) void UsbBulkClose(void)
{ {
/* Close the connection with the USB device. */ /* Close the connection with the USB device. */
UsbBulkLibFuncClose(); UblClose();
} /*** end of UsbBulkClose ***/ } /*** end of UsbBulkClose ***/
@ -169,7 +133,7 @@ bool UsbBulkWrite(uint8_t const * data, uint16_t length)
if ((data != NULL) && (length > 0)) /*lint !e774 */ if ((data != NULL) && (length > 0)) /*lint !e774 */
{ {
/* Write data to the USB device. */ /* Write data to the USB device. */
if (UsbBulkLibFuncTransmit((uint8_t *)data, length) == UBL_OKAY) if (UblTransmit((uint8_t *)data, length) == UBL_OKAY)
{ {
result = true; result = true;
} }
@ -201,7 +165,7 @@ bool UsbBulkRead(uint8_t * data, uint16_t length, uint32_t timeout)
if ((data != NULL) && (length > 0)) /*lint !e774 */ if ((data != NULL) && (length > 0)) /*lint !e774 */
{ {
/* Read data from the USB device. */ /* Read data from the USB device. */
if (UsbBulkLibFuncReceive(data, length, timeout) == UBL_OKAY) if (UblReceive(data, length, timeout) == UBL_OKAY)
{ {
result = true; result = true;
} }
@ -211,84 +175,124 @@ bool UsbBulkRead(uint8_t * data, uint16_t length, uint32_t timeout)
} /*** end of UsbBulkRead ***/ } /*** end of UsbBulkRead ***/
/************************************************************************************//** /****************************************************************************************
** \brief Loads the USB bulk driver DLL and initializes the API function pointers. * U S B B U L K L I B R A R Y F U N C T I O N S
**
****************************************************************************************/ ****************************************************************************************/
static void UsbBulkLibLoadDll(void)
{
/* Start out by resetting the API function pointers. */
usbBulkLibFuncOpenPtr = NULL;
usbBulkLibFuncClosePtr = NULL;
usbBulkLibFuncTransmitPtr = NULL;
usbBulkLibFuncReceivePtr = NULL;
/* Attempt to load the library and obtain a handle to it. */ /****************************************************************************************
usbBulkLibDllHandle = LoadLibrary("UsbBulkLib"); * Macro definitions
/* Assert libary handle. */
assert(usbBulkLibDllHandle != NULL);
/* Only continue if the library was successfully loaded */
if (usbBulkLibDllHandle != NULL) /*lint !e774 */
{
/* Set UblOpen function pointer. */
usbBulkLibFuncOpenPtr = (tUsbBulkLibFuncOpen)GetProcAddress(usbBulkLibDllHandle, "UblOpen");
/* Set UblClose function pointer. */
usbBulkLibFuncClosePtr = (tUsbBulkLibFuncClose)GetProcAddress(usbBulkLibDllHandle, "UblClose");
/* Set UblTransmit function pointer. */
usbBulkLibFuncTransmitPtr = (tUsbBulkLibFuncTransmit)GetProcAddress(usbBulkLibDllHandle, "UblTransmit");
/* Set UblReceive function pointer. */
usbBulkLibFuncReceivePtr = (tUsbBulkLibFuncReceive)GetProcAddress(usbBulkLibDllHandle, "UblReceive");
}
} /*** end of UsbBulkLibLoadDll ***/
/************************************************************************************//**
** \brief Unloads the USB bulk driver DLL and resets the API function pointers.
**
****************************************************************************************/ ****************************************************************************************/
static void UsbBulkLibUnloadDll(void) /** \brief Max length of the device path. */
{ #define MAX_DEVPATH_LENGTH (128)
/* Reset the API function pointers. */
usbBulkLibFuncOpenPtr = NULL;
usbBulkLibFuncClosePtr = NULL;
usbBulkLibFuncTransmitPtr = NULL;
usbBulkLibFuncReceivePtr = NULL;
/* Unload the library and invalidate its handle. */ /** \brief Identifier value of an invalid USB PIPE. */
if (usbBulkLibDllHandle != NULL) #define INVALID_PIPE_ID (255)
{
(void)FreeLibrary(usbBulkLibDllHandle);
usbBulkLibDllHandle = NULL; /****************************************************************************************
} * Type definitions
} /*** end of UsbBulkLibUnloadDll ***/ ****************************************************************************************/
/** \brief Type for grouping together all USB bulk device related data. */
typedef struct
{
HANDLE hDev;
WINUSB_INTERFACE_HANDLE hWinUSBDev;
UCHAR pipeBulkIn;
UCHAR pipeBulkOut;
HANDLE evReader;
} tBulkUsbDev;
/****************************************************************************************
* Local data declarations
****************************************************************************************/
static tBulkUsbDev bulkUsbDev;
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static HANDLE UblOpenDevice(LPCGUID InterfaceGuid);
static BOOL UblGetDevicePath(LPCGUID InterfaceGuid, PCHAR DevicePath, size_t BufLen);
/************************************************************************************//** /************************************************************************************//**
** \brief Opens and configures the connection with the USB bulk device. ** \brief Opens and configures the connection with the USB bulk device.
** \param guid Pointer to GUID of the USB bulk device as found in the driver's ** \param guid Pointer to GUID of the USB bulk device as found in the driver's
** INF-file. ** INF-file.
** \return UBL_OKAY if successful, UBL_ERROR otherwise. ** \return UBL_OKAY if successful, UBL_ERROR otherwise.
** **
****************************************************************************************/ ****************************************************************************************/
static uint8_t UsbBulkLibFuncOpen(LPGUID guid) static uint8_t UblOpen(LPCGUID guid)
{ {
uint8_t result = UBL_ERROR; USB_INTERFACE_DESCRIPTOR ifaceDescriptor;
WINUSB_PIPE_INFORMATION pipeInfo;
uint32_t i;
/* Check function pointer and library handle. */ /* Init device members. */
assert(usbBulkLibFuncOpenPtr != NULL); bulkUsbDev.hDev = NULL;
assert(usbBulkLibDllHandle != NULL); bulkUsbDev.hWinUSBDev = NULL;
bulkUsbDev.pipeBulkIn = INVALID_PIPE_ID;
/* Only continue with valid function pointer and library handle. */ bulkUsbDev.pipeBulkOut = INVALID_PIPE_ID;
if ((usbBulkLibFuncOpenPtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */ /* Open the usb device. */
bulkUsbDev.hDev = UblOpenDevice(guid);
if (bulkUsbDev.hDev == NULL)
{ {
/* Call library function. */ UblClose();
result = usbBulkLibFuncOpenPtr(guid); return UBL_ERROR;
} }
/* Give the result back to the caller. */ /* Init the winusb device. */
return result; if (WinUsb_Initialize(bulkUsbDev.hDev, &bulkUsbDev.hWinUSBDev) == FALSE)
} /*** end of UsbBulkLibFuncOpen ***/ {
UblClose();
return UBL_ERROR;
}
/* Obtain interface settings. */
if (WinUsb_QueryInterfaceSettings(bulkUsbDev.hWinUSBDev, 0, &ifaceDescriptor) == FALSE)
{
UblClose();
return UBL_ERROR;
}
/* Iterate through endpoint to find bulk IN and OUT. */
for (i = 0; i < ifaceDescriptor.bNumEndpoints; i++)
{
if (WinUsb_QueryPipe(bulkUsbDev.hWinUSBDev, 0, (UCHAR)i, &pipeInfo) == FALSE)
{
UblClose();
return UBL_ERROR;
}
/* Is this the bulk IN endpoint? */
if ((pipeInfo.PipeType == UsbdPipeTypeBulk) && \
(USB_ENDPOINT_DIRECTION_IN(pipeInfo.PipeId)))
{
bulkUsbDev.pipeBulkIn = pipeInfo.PipeId;
}
/* Is this the bulk OUT endpoint? */
else if ((pipeInfo.PipeType == UsbdPipeTypeBulk) && \
(USB_ENDPOINT_DIRECTION_OUT(pipeInfo.PipeId)))
{
bulkUsbDev.pipeBulkOut = pipeInfo.PipeId;
}
}
/* Verify that the bulk IN and OUT pipes were found. */
if ((bulkUsbDev.pipeBulkIn == INVALID_PIPE_ID) || \
(bulkUsbDev.pipeBulkOut == INVALID_PIPE_ID))
{
UblClose();
return UBL_ERROR;
}
/* Create the reader event handle. */
bulkUsbDev.evReader = CreateEvent(NULL, TRUE, FALSE, NULL);
if (bulkUsbDev.evReader == NULL)
{
UblClose();
return UBL_ERROR;
}
/* Still here so all is okay. */
return UBL_OKAY;
} /*** end of UblOpen ***/
/************************************************************************************//** /************************************************************************************//**
@ -296,23 +300,31 @@ static uint8_t UsbBulkLibFuncOpen(LPGUID guid)
** handles. ** handles.
** **
****************************************************************************************/ ****************************************************************************************/
static void UsbBulkLibFuncClose(void) static void UblClose(void)
{ {
/* Check function pointer and library handle. */ /* close reader event handle */
assert(usbBulkLibFuncClosePtr != NULL); if (bulkUsbDev.evReader != NULL)
assert(usbBulkLibDllHandle != NULL);
/* Only continue with valid function pointer and library handle. */
if ((usbBulkLibFuncClosePtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */
{ {
/* Call library function. */ (void)CloseHandle(bulkUsbDev.evReader);
usbBulkLibFuncClosePtr();
} }
} /*** end of UsbBulkLibFuncClose ***/ /* close the winusb device */
if (bulkUsbDev.hWinUSBDev != NULL)
{
(void)WinUsb_Free(bulkUsbDev.hWinUSBDev);
}
/* reset bulk OUT and IN pipes */
bulkUsbDev.pipeBulkOut = INVALID_PIPE_ID;
bulkUsbDev.pipeBulkIn = INVALID_PIPE_ID;
/* close the usb device handle */
if (bulkUsbDev.hDev != NULL)
{
(void)CloseHandle(bulkUsbDev.hDev);
}
} /*** end of UblClose ***/
/************************************************************************************//** /************************************************************************************//**
** \brief Starts transmission of the data on the bulk OUT pipe. Because USB bulk ** \brief Starts transmission of the data on the bulk OUT pipe. Because USB bulk
** transmissions are quick, this function does not use the overlapped ** transmissions are quick, this function does not use the overlapped
** functionality, which means the caller is blocked until the tranmission ** functionality, which means the caller is blocked until the tranmission
** completed. ** completed.
@ -321,23 +333,25 @@ static void UsbBulkLibFuncClose(void)
** \return UBL_OKAY if successful, UBL_ERROR otherwise. ** \return UBL_OKAY if successful, UBL_ERROR otherwise.
** **
****************************************************************************************/ ****************************************************************************************/
static uint8_t UsbBulkLibFuncTransmit(uint8_t * data, uint16_t len) static uint8_t UblTransmit(uint8_t * data, uint16_t len)
{ {
uint8_t result = UBL_ERROR; DWORD bytesWritten = 0;
/* Check function pointer and library handle. */ /* Submit the transmit request. */
assert(usbBulkLibFuncTransmitPtr != NULL); if (WinUsb_WritePipe(bulkUsbDev.hWinUSBDev, bulkUsbDev.pipeBulkOut, data, len,
assert(usbBulkLibDllHandle != NULL); &bytesWritten, NULL) == 0)
/* Only continue with valid function pointer and library handle. */
if ((usbBulkLibFuncTransmitPtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */
{ {
/* Call library function. */ /* Could not write the data. */
result = usbBulkLibFuncTransmitPtr(data, len); return UBL_ERROR;
} }
/* Give the result back to the caller. */ if (bytesWritten != len)
return result; {
} /*** end of UsbBulkLibFuncTransmit ***/ /* Not all data was written. */
return UBL_ERROR;
}
/* Still here so all is okay. */
return UBL_OKAY;
} /*** end of UblTransmit ***/
/************************************************************************************//** /************************************************************************************//**
@ -346,28 +360,190 @@ static uint8_t UsbBulkLibFuncTransmit(uint8_t * data, uint16_t len)
** thread is placed into sleep mode until the reception is complete. ** thread is placed into sleep mode until the reception is complete.
** \param data Pointer to byte array where the data will be stored. ** \param data Pointer to byte array where the data will be stored.
** \param len Number of bytes to receive. ** \param len Number of bytes to receive.
** \param timeout Maximum time in milliseconds for the read to complete. ** \param timeout Max time in milliseconds for the read to complete.
** \return UBL_OKAY if successful, UBL_TIMEOUT if failure due to timeout or ** \return UBL_OKAY if all bytes were received, UBL_TIMEOUT if a timeout occured,
** UBL_ERROR otherwise. ** UBL_ERROR otherwise.
** **
****************************************************************************************/ ****************************************************************************************/
static uint8_t UsbBulkLibFuncReceive(uint8_t * data, uint16_t len, uint32_t timeout) static uint8_t UblReceive(uint8_t * data, uint16_t len, uint32_t timeout)
{ {
uint8_t result = UBL_ERROR; OVERLAPPED osReader = { 0 }; /* overlapped structure for read operations */
HANDLE hArray[1]; /* event handle array */
DWORD dwRead; /* bytes actually read */
DWORD dwRes; /* result from WaitForSingleObject */
BOOL bRes; /* result from WinUsb_ReadPipe */
DWORD bytesRead = 0;
DWORD totalBytesRead = 0;
DWORD dwStartTime;
/* Check function pointer and library handle. */ /* Get the current time and store it for timeout feature. */
assert(usbBulkLibFuncReceivePtr != NULL); dwStartTime = GetTickCount();
assert(usbBulkLibDllHandle != NULL);
/* Only continue with valid function pointer and library handle. */ /* Create an overlapped structure for read events. */
if ((usbBulkLibFuncReceivePtr != NULL) && (usbBulkLibDllHandle != NULL)) /*lint !e774 */ osReader.hEvent = bulkUsbDev.evReader;
/* Build array with events to detect. */
hArray[0] = osReader.hEvent;
while (((GetTickCount() - dwStartTime) < timeout) && (totalBytesRead < len))
{ {
/* Call library function. */ /* Start the read operation. */
result = usbBulkLibFuncReceivePtr(data, len, timeout); bRes = WinUsb_ReadPipe(bulkUsbDev.hWinUSBDev, bulkUsbDev.pipeBulkIn, data, len,
&bytesRead, &osReader);
/* Upon positive return means the read was completed. */
if (bRes)
{
/* Update the total. */
totalBytesRead += bytesRead;
/* Check number of bytes read. */
if (totalBytesRead == len)
{
/* All bytes read from bulk IN pipe. */
return UBL_OKAY;
}
else
{
/* No I/O operation is pending, yet still not received all the bytes so
* restart the read operation.
*/
continue;
}
}
/* Still here so this is either because of an error or because the read is delayed
* because of an overlapped operation this is in progress.
*/
if (GetLastError() != ERROR_IO_PENDING)
{
/* Not delayed, but here due to an error. */
return UBL_ERROR;
}
/* Read is delayed so wait for it to complete or a timeout to occur. */
dwRes = WaitForMultipleObjects(1, hArray, FALSE, timeout);
/* Process the result. */
switch (dwRes)
{
case WAIT_OBJECT_0: /*lint !e835 */
/* Read operation returned so check the results. */
if (!GetOverlappedResult(bulkUsbDev.hDev, &osReader, &dwRead, FALSE))
{
if (GetLastError() != ERROR_OPERATION_ABORTED)
{
/* Read completed but with error. */
return UBL_ERROR;
}
}
else
{
/* See if all the data was now read. */
totalBytesRead += dwRead;
if (totalBytesRead == len)
{
return UBL_OKAY;
}
}
break;
case WAIT_TIMEOUT:
/* Timeout occurred so abort the pipe operation. */
(void)WinUsb_AbortPipe(bulkUsbDev.hWinUSBDev, bulkUsbDev.pipeBulkIn);
return UBL_TIMEOUT;
default:
/* Unexpected so abort the pipe operation. */
(void)WinUsb_AbortPipe(bulkUsbDev.hWinUSBDev, bulkUsbDev.pipeBulkIn);
return UBL_ERROR;
}
} }
/* Give the result back to the caller. */ /* Still here so read incomplete due to timeout. */
return result; return UBL_ERROR;
} /*** end of UsbBulkLibFuncReceive ***/ } /*** end of UblReceive ***/
/************************************************************************************//**
** \brief Opens the USB device and obtains its handle, which is needed to obtain a
** handle to the WinUSB device.
** \param InterfaceGuid InterfaceGuid GUID of the device (not its class though).
** \return The handle to the USB device or NULL.
**
****************************************************************************************/
static HANDLE UblOpenDevice(LPCGUID InterfaceGuid)
{
HANDLE hDev = NULL;
char devicePath[MAX_DEVPATH_LENGTH] = { 0 };
BOOL retVal;
retVal = UblGetDevicePath(InterfaceGuid, devicePath, sizeof(devicePath));
if (retVal)
{
hDev = CreateFile(devicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE |
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, NULL);
}
return hDev;
} /*** end of UblOpenDevice ***/
/************************************************************************************//**
** \brief Attempts to obtain the path to the WinUSB device, based on its GUID.
** \param InterfaceGuid InterfaceGuid GUID of the device (not its class though).
** \param DevicePath Pointer to where the path should be stored.
** \param BufLen Maximum length of the path.
** \return TRUE if the device path was obtained, FALSE otherwise.
**
****************************************************************************************/
static BOOL UblGetDevicePath(LPCGUID InterfaceGuid, PCHAR DevicePath, size_t BufLen)
{
BOOL bResult;
HDEVINFO deviceInfo;
SP_DEVICE_INTERFACE_DATA interfaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData;
ULONG length;
ULONG requiredLength = 0;
HRESULT hr;
deviceInfo = SetupDiGetClassDevs(InterfaceGuid, NULL, NULL, DIGCF_PRESENT |
DIGCF_DEVICEINTERFACE);
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
(void)SetupDiEnumDeviceInterfaces(deviceInfo, NULL, InterfaceGuid, 0,
&interfaceData);
(void)SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength,
NULL);
if (requiredLength == 0)
{
(void)SetupDiDestroyDeviceInfoList(deviceInfo);
return FALSE;
}
detailData = LocalAlloc(LMEM_FIXED, requiredLength);
if (detailData == NULL)
{
(void)SetupDiDestroyDeviceInfoList(deviceInfo);
return FALSE;
}
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
length = requiredLength;
bResult = SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, detailData,
length, &requiredLength, NULL);
if (bResult == FALSE)
{
LocalFree(detailData);
return FALSE;
}
hr = StringCchCopy(DevicePath, BufLen, detailData->DevicePath);
if (FAILED(hr))
{
(void)SetupDiDestroyDeviceInfoList(deviceInfo);
LocalFree(detailData);
}
LocalFree(detailData);
return bResult;
} /*** end of UblGetDevicePath ***/
/*********************************** end of usbbulk.c **********************************/ /*********************************** end of usbbulk.c **********************************/

Binary file not shown.

Binary file not shown.