From ed00ee9ce0094e354e09209a94f08f9818f8954a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 20 Dec 2023 13:20:27 +0100 Subject: 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 Change-Id: Ia1f0965cea44b4bb6d936b02ec43f5a16a46f080 Reviewed-on: https://review.openocd.org/c/openocd/+/8059 Tested-by: jenkins Reviewed-by: Antonio Borneo --- src/jtag/drivers/libusb_helper.c | 56 ++++++++++++++++++++++++++++++++++++++++ src/jtag/drivers/libusb_helper.h | 23 +++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 9d788ee..57ea8cd 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -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; +} diff --git a/src/jtag/drivers/libusb_helper.h b/src/jtag/drivers/libusb_helper.h index 09309b4..3cd83c6 100644 --- a/src/jtag/drivers/libusb_helper.h +++ b/src/jtag/drivers/libusb_helper.h @@ -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 */ -- cgit v1.1