drivers/libusb_helper: introduce oocd_libusb_dev_mem_alloc() helper

On some systems (at least Windows/CYGWIN and macOS) libusb_dev_mem_alloc()
simply returns NULL.

Use the result of the very first libusb_dev_mem_alloc() call to decide
if the underlining system supports dev mem allocation or we should
fall-back to plain heap malloc().

From the decision time on, keep using the selected type of memory allocator
and deallocator.

Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Change-Id: Ia1f0965cea44b4bb6d936b02ec43f5a16a46f080
Reviewed-on: https://review.openocd.org/c/openocd/+/8059
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Tomas Vanek 2023-12-20 13:20:27 +01:00 committed by Evgeniy Naydanov
parent ec28cf03ae
commit ed00ee9ce0
2 changed files with 79 additions and 0 deletions

View File

@ -377,3 +377,59 @@ int jtag_libusb_handle_events_completed(int *completed)
{
return libusb_handle_events_completed(jtag_libusb_context, completed);
}
static enum {
DEV_MEM_NOT_YET_DECIDED,
DEV_MEM_AVAILABLE,
DEV_MEM_FALLBACK_MALLOC
} dev_mem_allocation;
/* Older libusb does not implement following API calls - define stubs instead */
#if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000105)
static uint8_t *libusb_dev_mem_alloc(libusb_device_handle *devh, size_t length)
{
return NULL;
}
static int libusb_dev_mem_free(libusb_device_handle *devh,
uint8_t *buffer, size_t length)
{
return LIBUSB_ERROR_NOT_SUPPORTED;
}
#endif
uint8_t *oocd_libusb_dev_mem_alloc(libusb_device_handle *devh,
size_t length)
{
uint8_t *buffer = NULL;
if (dev_mem_allocation != DEV_MEM_FALLBACK_MALLOC)
buffer = libusb_dev_mem_alloc(devh, length);
if (dev_mem_allocation == DEV_MEM_NOT_YET_DECIDED)
dev_mem_allocation = buffer ? DEV_MEM_AVAILABLE : DEV_MEM_FALLBACK_MALLOC;
if (dev_mem_allocation == DEV_MEM_FALLBACK_MALLOC)
buffer = malloc(length);
return buffer;
}
int oocd_libusb_dev_mem_free(libusb_device_handle *devh,
uint8_t *buffer, size_t length)
{
if (!buffer)
return ERROR_OK;
switch (dev_mem_allocation) {
case DEV_MEM_AVAILABLE:
return jtag_libusb_error(libusb_dev_mem_free(devh, buffer, length));
case DEV_MEM_FALLBACK_MALLOC:
free(buffer);
return ERROR_OK;
case DEV_MEM_NOT_YET_DECIDED:
return ERROR_FAIL;
}
return ERROR_FAIL;
}

View File

@ -67,4 +67,27 @@ int jtag_libusb_choose_interface(struct libusb_device_handle *devh,
int jtag_libusb_get_pid(struct libusb_device *dev, uint16_t *pid);
int jtag_libusb_handle_events_completed(int *completed);
/**
* Attempts to allocate a block of persistent DMA memory suitable for transfers
* against the USB device. Fall-back to the ordinary heap malloc()
* if the first libusb_dev_mem_alloc() call fails.
* @param devh _libusb_ device handle.
* @param length size of desired data buffer
* @returns a pointer to the newly allocated memory, or NULL on failure
*/
uint8_t *oocd_libusb_dev_mem_alloc(libusb_device_handle *devh,
size_t length);
/**
* Free device memory allocated with oocd_libusb_dev_mem_alloc().
* Uses either libusb_dev_mem_free() or free() consistently with
* the used method of allocation.
* @param devh _libusb_ device handle.
* @param buffer pointer to the previously allocated memory
* @param length size of desired data buffer
* @returns Returns ERROR_OK on success, ERROR_FAIL otherwise.
*/
int oocd_libusb_dev_mem_free(libusb_device_handle *devh,
uint8_t *buffer, size_t length);
#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_HELPER_H */