X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Flibusb_helper.c;h=fbbfb4114bc07635d6203773012f2a78b2de6535;hp=18fe4bad4c668694ae78a1e0d73b5995b7b03f77;hb=HEAD;hpb=cff0e417da58adef1ceef9a63a99412c2cc87ff3 diff --git a/src/jtag/drivers/libusb_helper.c b/src/jtag/drivers/libusb_helper.c index 18fe4bad4c..57ea8cd3fa 100644 --- a/src/jtag/drivers/libusb_helper.c +++ b/src/jtag/drivers/libusb_helper.c @@ -1,28 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + /*************************************************************************** * Copyright (C) 2009 by Zachary T Welch * * * * Copyright (C) 2011 by Mauro Gamba * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include + +#include + +#include +#include #include "libusb_helper.h" -#include "log.h" /* * comment from libusb: @@ -58,7 +50,7 @@ static int jtag_libusb_error(int err) } } -static bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc, +bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc, const uint16_t vids[], const uint16_t pids[]) { for (unsigned i = 0; vids[i]; i++) { @@ -85,7 +77,7 @@ static bool jtag_libusb_location_equal(struct libusb_device *device) } dev_bus = libusb_get_bus_number(device); - return jtag_usb_location_equal(dev_bus, port_path, path_len); + return adapter_usb_location_equal(dev_bus, port_path, path_len); } #else /* HAVE_LIBUSB_GET_PORT_NUMBERS */ static bool jtag_libusb_location_equal(struct libusb_device *device) @@ -138,7 +130,7 @@ static bool jtag_libusb_match_serial(struct libusb_device_handle *device, char *alternate_serial = adapter_get_alternate_serial(device, dev_desc); /* check possible failures */ - if (alternate_serial == NULL) + if (!alternate_serial) return false; /* then compare and free the alternate serial */ @@ -154,14 +146,15 @@ static bool jtag_libusb_match_serial(struct libusb_device_handle *device, } int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], - const char *serial, - struct libusb_device_handle **out, + const char *product, struct libusb_device_handle **out, adapter_get_alternate_serial_fn adapter_get_alternate_serial) { - int cnt, idx, errCode; + int cnt, idx, err_code; int retval = ERROR_FAIL; bool serial_mismatch = false; + bool product_mismatch = false; struct libusb_device_handle *libusb_handle = NULL; + const char *serial = adapter_get_required_serial(); if (libusb_init(&jtag_libusb_context) < 0) return ERROR_FAIL; @@ -177,29 +170,37 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], if (!jtag_libusb_match_ids(&dev_desc, vids, pids)) continue; - if (jtag_usb_get_location() && !jtag_libusb_location_equal(devs[idx])) + if (adapter_usb_get_location() && !jtag_libusb_location_equal(devs[idx])) continue; - errCode = libusb_open(devs[idx], &libusb_handle); + err_code = libusb_open(devs[idx], &libusb_handle); - if (errCode) { + if (err_code) { LOG_ERROR("libusb_open() failed with %s", - libusb_error_name(errCode)); + libusb_error_name(err_code)); continue; } /* Device must be open to use libusb_get_string_descriptor_ascii. */ - if (serial != NULL && + if (serial && !jtag_libusb_match_serial(libusb_handle, &dev_desc, serial, adapter_get_alternate_serial)) { serial_mismatch = true; libusb_close(libusb_handle); continue; } + if (product && + !string_descriptor_equal(libusb_handle, dev_desc.iProduct, product)) { + product_mismatch = true; + libusb_close(libusb_handle); + continue; + } + /* Success. */ *out = libusb_handle; retval = ERROR_OK; serial_mismatch = false; + product_mismatch = false; break; } if (cnt >= 0) @@ -208,6 +209,9 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[], if (serial_mismatch) LOG_INFO("No device matches the serial string"); + if (product_mismatch) + LOG_INFO("No device matches the product string"); + if (retval != ERROR_OK) libusb_exit(jtag_libusb_context); @@ -222,19 +226,24 @@ void jtag_libusb_close(struct libusb_device_handle *dev) libusb_exit(jtag_libusb_context); } -int jtag_libusb_control_transfer(struct libusb_device_handle *dev, uint8_t requestType, - uint8_t request, uint16_t wValue, uint16_t wIndex, char *bytes, - uint16_t size, unsigned int timeout) +int jtag_libusb_control_transfer(struct libusb_device_handle *dev, uint8_t request_type, + uint8_t request, uint16_t value, uint16_t index, char *bytes, + uint16_t size, unsigned int timeout, int *transferred) { - int transferred = 0; - - transferred = libusb_control_transfer(dev, requestType, request, wValue, wIndex, + int retval = libusb_control_transfer(dev, request_type, request, value, index, (unsigned char *)bytes, size, timeout); - if (transferred < 0) - transferred = 0; + if (retval < 0) { + LOG_ERROR("libusb_control_transfer error: %s", libusb_error_name(retval)); + if (transferred) + *transferred = 0; + return jtag_libusb_error(retval); + } - return transferred; + if (transferred) + *transferred = retval; + + return ERROR_OK; } int jtag_libusb_bulk_write(struct libusb_device_handle *dev, int ep, char *bytes, @@ -275,28 +284,28 @@ int jtag_libusb_set_configuration(struct libusb_device_handle *devh, int configuration) { struct libusb_device *udev = libusb_get_device(devh); - int retCode = -99; + int retval = -99; struct libusb_config_descriptor *config = NULL; int current_config = -1; - retCode = libusb_get_configuration(devh, ¤t_config); - if (retCode != 0) - return retCode; + retval = libusb_get_configuration(devh, ¤t_config); + if (retval != 0) + return retval; - retCode = libusb_get_config_descriptor(udev, configuration, &config); - if (retCode != 0 || config == NULL) - return retCode; + retval = libusb_get_config_descriptor(udev, configuration, &config); + if (retval != 0 || !config) + return retval; /* Only change the configuration if it is not already set to the same one. Otherwise this issues a lightweight reset and hangs LPC-Link2 with JLink firmware. */ if (current_config != config->bConfigurationValue) - retCode = libusb_set_configuration(devh, config->bConfigurationValue); + retval = libusb_set_configuration(devh, config->bConfigurationValue); libusb_free_config_descriptor(config); - return retCode; + return retval; } int jtag_libusb_choose_interface(struct libusb_device_handle *devh, @@ -368,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; +}