diff --git a/.travis.yml b/.travis.yml index 79d024b45..7a82b02d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ matrix: compiler: - clang before_install: - - mkdir build && cd build && wget "https://sourceforge.net/projects/libusb-win32/files/libusb-win32-releases/1.2.6.0/libusb-win32-bin-1.2.6.0.zip" && 7z x libusb-win32-bin-1.2.6.0.zip -o"$PROGRAMFILES" && mv "$PROGRAMFILES/libusb-win32-bin-1.2.6.0" "$PROGRAMFILES/libusb-win32" + - mkdir build && cd build && wget "https://github.com/libusb/libusb/releases/download/v1.0.29/libusb-1.0.29.7z" && 7z x libusb-1.0.29.7z -o"$PROGRAMFILES/libusb" install: choco install doxygen.install ninja script: @@ -19,7 +19,7 @@ matrix: addons: apt: packages: - - libusb-dev + - libusb-1.0-0-dev - doxygen - cmake script: @@ -32,7 +32,7 @@ matrix: addons: apt: packages: - - libusb-dev + - libusb-1.0-0-dev - doxygen script: - autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install @@ -44,7 +44,7 @@ matrix: addons: apt: packages: - - libusb-dev + - libusb-1.0-0-dev - doxygen - cmake script: @@ -57,7 +57,7 @@ matrix: addons: apt: packages: - - libusb-dev + - libusb-1.0-0-dev - doxygen script: - autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install @@ -67,7 +67,7 @@ matrix: compiler: - clang before_install: - - brew install doxygen libusb-compat + - brew install doxygen libusb script: - mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX=~/.local .. && make -j2 && make install @@ -76,6 +76,6 @@ matrix: compiler: - clang before_install: - - brew install doxygen libusb-compat m4 + - brew install doxygen libusb m4 script: - autoreconf -vfi && mkdir build && cd build && ../configure --prefix=$HOME/.local/ && make -j2 && make install diff --git a/CMakeLists.txt b/CMakeLists.txt index a8605fa40..3cbe39b08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,9 +99,6 @@ IF(CMAKE_COMPILER_IS_GNUCC) SET(CMAKE_C_FLAGS "-Wall -pedantic -std=c99 ${CMAKE_C_FLAGS}") ENDIF(CMAKE_COMPILER_IS_GNUCC) -# Workarounds for libusb in C99 -ADD_DEFINITIONS(-Du_int8_t=uint8_t -Du_int16_t=uint16_t) - IF(MINGW) IF (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") IF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86") @@ -132,10 +129,10 @@ IF(NOT WIN32) SET(exec_prefix ${CMAKE_INSTALL_PREFIX}) SET(PACKAGE "libnfc") IF(LIBNFC_DRIVER_PN53X_USB) - SET(PKG_REQ ${PKG_REQ} "libusb") + SET(PKG_REQ ${PKG_REQ} "libusb-1.0") ENDIF(LIBNFC_DRIVER_PN53X_USB) IF(LIBNFC_DRIVER_ACR122_USB) - SET(PKG_REQ ${PKG_REQ} "libusb") + SET(PKG_REQ ${PKG_REQ} "libusb-1.0") ENDIF(LIBNFC_DRIVER_ACR122_USB) IF(LIBNFC_DRIVER_PCSC) SET(PKG_REQ ${PKG_REQ} "libpcsclite") diff --git a/cmake/modules/FindLIBUSB.cmake b/cmake/modules/FindLIBUSB.cmake index 4afd8afaa..a58a32d46 100644 --- a/cmake/modules/FindLIBUSB.cmake +++ b/cmake/modules/FindLIBUSB.cmake @@ -26,14 +26,35 @@ ENDIF(CMAKE_SYSTEM_NAME MATCHES FreeBSD) IF(NOT LIBUSB_FOUND) IF(WIN32) + SET(LIBUSB_ROOT "$ENV{ProgramFiles}/libusb") + FIND_PATH(LIBUSB_INCLUDE_DIRS libusb.h "${LIBUSB_ROOT}/include" NO_SYSTEM_ENVIRONMENT_PATH) IF(MINGW) - FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/include" NO_SYSTEM_ENVIRONMENT_PATH) - FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/lib/gcc") - SET(LIBUSB_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/bin/x86/") + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 PATHS "${LIBUSB_ROOT}/MinGW64/static" NO_SYSTEM_ENVIRONMENT_PATH) + SET(LIBUSB_LIBRARY_DIR "${LIBUSB_ROOT}/MinGW64/dll") + ELSE() + FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 PATHS "${LIBUSB_ROOT}/MinGW32/static" NO_SYSTEM_ENVIRONMENT_PATH) + SET(LIBUSB_LIBRARY_DIR "${LIBUSB_ROOT}/MinGW32/dll") + ENDIF() ELSE(MINGW) - FIND_PATH(LIBUSB_INCLUDE_DIRS lusb0_usb.h "$ENV{ProgramW6432}/libusb-win32/include" NO_SYSTEM_ENVIRONMENT_PATH) - FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64") - SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramW6432}/libusb-win32/bin/amd64/") + IF(MSVC_VERSION GREATER_EQUAL 1930) + SET(LIBUSB_VS_DIR "VS2022") + ELSEIF(MSVC_VERSION GREATER_EQUAL 1920) + SET(LIBUSB_VS_DIR "VS2019") + ELSEIF(MSVC_VERSION GREATER_EQUAL 1910) + SET(LIBUSB_VS_DIR "VS2017") + ELSEIF(MSVC_VERSION GREATER_EQUAL 1900) + SET(LIBUSB_VS_DIR "VS2015") + ELSE() + SET(LIBUSB_VS_DIR "VS2013") + ENDIF() + IF(CMAKE_SIZEOF_VOID_P EQUAL 8) + FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb-1.0 PATHS "${LIBUSB_ROOT}/${LIBUSB_VS_DIR}/MS64/dll" "${LIBUSB_ROOT}/${LIBUSB_VS_DIR}/MS64/static" NO_SYSTEM_ENVIRONMENT_PATH) + SET(LIBUSB_LIBRARY_DIR "${LIBUSB_ROOT}/${LIBUSB_VS_DIR}/MS64/dll") + ELSE() + FIND_LIBRARY(LIBUSB_LIBRARIES NAMES libusb-1.0 PATHS "${LIBUSB_ROOT}/${LIBUSB_VS_DIR}/MS32/dll" "${LIBUSB_ROOT}/${LIBUSB_VS_DIR}/MS32/static" NO_SYSTEM_ENVIRONMENT_PATH) + SET(LIBUSB_LIBRARY_DIR "${LIBUSB_ROOT}/${LIBUSB_VS_DIR}/MS32/dll") + ENDIF() ENDIF(MINGW) # Must fix up variable to avoid backslashes during packaging STRING(REGEX REPLACE "\\\\" "/" LIBUSB_LIBRARY_DIR ${LIBUSB_LIBRARY_DIR}) @@ -41,7 +62,7 @@ IF(NOT LIBUSB_FOUND) # If not under Windows we use PkgConfig FIND_PACKAGE (PkgConfig) IF(PKG_CONFIG_FOUND) - PKG_CHECK_MODULES(LIBUSB REQUIRED libusb) + PKG_CHECK_MODULES(LIBUSB REQUIRED libusb-1.0) ELSE(PKG_CONFIG_FOUND) MESSAGE(FATAL_ERROR "Could not find PkgConfig") ENDIF(PKG_CONFIG_FOUND) diff --git a/configure.ac b/configure.ac index 46b65d338..9809031b4 100644 --- a/configure.ac +++ b/configure.ac @@ -194,9 +194,6 @@ CFLAGS="$CFLAGS -Wall -pedantic -Wextra" # Defines and C flags CFLAGS="$CFLAGS -std=c99" -# Workarounds for libusb in c99 -CFLAGS="$CFLAGS -Du_int8_t=uint8_t -Du_int16_t=uint16_t" - AC_CONFIG_FILES([ Doxyfile Makefile diff --git a/libnfc/buses/usbbus.c b/libnfc/buses/usbbus.c index d2477f5ae..3bf2b0884 100644 --- a/libnfc/buses/usbbus.c +++ b/libnfc/buses/usbbus.c @@ -27,7 +27,7 @@ /** * @file usbbus.c - * @brief libusb 0.1 driver wrapper + * @brief libusb 1.0 driver wrapper */ #ifdef HAVE_CONFIG_H @@ -41,39 +41,31 @@ #define LOG_CATEGORY "libnfc.buses.usbbus" #define LOG_GROUP NFC_LOG_GROUP_DRIVER -int usb_prepare(void) +static libusb_context *usb_context = NULL; + +libusb_context * +usb_get_context(void) { static bool usb_initialized = false; if (!usb_initialized) { + int r = libusb_init(&usb_context); + if (r < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to initialize libusb (%s)", libusb_strerror(r)); + return NULL; + } #ifdef ENVVARS char *env_log_level = getenv("LIBNFC_LOG_LEVEL"); - // Set libusb debug only if asked explicitely: + // Set libusb debug only if asked explicitly: // LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB) if (env_log_level && (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) { - setenv("USB_DEBUG", "255", 1); + libusb_set_option(usb_context, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_DEBUG); } #endif - usb_init(); usb_initialized = true; } - int res; - // usb_find_busses will find all of the busses on the system. Returns the - // number of changes since previous call to this function (total of new - // busses and busses removed). - if ((res = usb_find_busses()) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", _usb_strerror(res)); - return -1; - } - // usb_find_devices will find all of the devices on each bus. This should be - // called after usb_find_busses. Returns the number of changes since the - // previous call to this function (total of new device and devices removed). - if ((res = usb_find_devices()) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", _usb_strerror(res)); - return -1; - } - return 0; + return usb_context; } diff --git a/libnfc/buses/usbbus.h b/libnfc/buses/usbbus.h index 3c0381a81..dd83fddd2 100644 --- a/libnfc/buses/usbbus.h +++ b/libnfc/buses/usbbus.h @@ -27,28 +27,17 @@ /** * @file usbbus.h - * @brief libusb 0.1 driver header + * @brief libusb 1.0 driver header */ #ifndef __NFC_BUS_USB_H__ # define __NFC_BUS_USB_H__ -#ifndef _WIN32 -// Under POSIX system, we use libusb (>= 0.1.12) -#include -#include -#define USB_TIMEDOUT ETIMEDOUT -#define _usb_strerror( X ) strerror(-X) -#else -// Under Windows we use libusb-win32 (>= 1.2.5) -#include -#define USB_TIMEDOUT 116 -#define _usb_strerror( X ) usb_strerror() -#endif +#include #include #include -int usb_prepare(void); +libusb_context *usb_get_context(void); #endif // __NFC_BUS_USB_H__ diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c index fc545014b..12a9c72fb 100644 --- a/libnfc/drivers/acr122_usb.c +++ b/libnfc/drivers/acr122_usb.c @@ -174,7 +174,7 @@ struct acr122_usb_apdu_frame { // Internal data struct struct acr122_usb_data { - usb_dev_handle *pudh; + libusb_device_handle *pudh; uint32_t uiEndPointIn; uint32_t uiEndPointOut; uint32_t uiMaxPacketSize; @@ -220,39 +220,39 @@ static int acr122_usb_send_apdu(nfc_device *pnd, static int acr122_usb_bulk_read(struct acr122_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout) { - int res = usb_bulk_read(data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, timeout); - if (res > 0) { - LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, res); - } else if (res < 0) { - if (res != -USB_TIMEDOUT) { - res = NFC_EIO; - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", _usb_strerror(res)); - } else { - res = NFC_ETIMEOUT; - } + int transferred; + int res = libusb_bulk_transfer(data->pudh, data->uiEndPointIn, abtRx, szRx, &transferred, timeout); + if (res == 0) { + LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, transferred); + return transferred; + } else if (res == LIBUSB_ERROR_TIMEOUT) { + return NFC_ETIMEOUT; + } else { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", libusb_strerror(res)); + return NFC_EIO; } - return res; } static int acr122_usb_bulk_write(struct acr122_usb_data *data, uint8_t abtTx[], const size_t szTx, const int timeout) { LOG_HEX(NFC_LOG_GROUP_COM, "TX", abtTx, szTx); - int res = usb_bulk_write(data->pudh, data->uiEndPointOut, (char *) abtTx, szTx, timeout); - if (res > 0) { + int transferred; + int res = libusb_bulk_transfer(data->pudh, data->uiEndPointOut, abtTx, szTx, &transferred, timeout); + if (res == 0) { // HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details - if ((res % data->uiMaxPacketSize) == 0) { - usb_bulk_write(data->pudh, data->uiEndPointOut, "\0", 0, timeout); + if ((transferred % data->uiMaxPacketSize) == 0) { + libusb_bulk_transfer(data->pudh, data->uiEndPointOut, (unsigned char *)"\0", 0, &transferred, timeout); } - } else if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", _usb_strerror(res)); - if (res == -USB_TIMEDOUT) { - res = NFC_ETIMEOUT; + return transferred; + } else { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", libusb_strerror(res)); + if (res == LIBUSB_ERROR_TIMEOUT) { + return NFC_ETIMEOUT; } else { - res = NFC_EIO; + return NFC_EIO; } } - return res; } struct acr122_usb_supported_device { @@ -269,32 +269,37 @@ const struct acr122_usb_supported_device acr122_usb_supported_devices[] = { // Find transfer endpoints for bulk transfers static void -acr122_usb_get_end_points(struct usb_device *dev, struct acr122_usb_data *data) +acr122_usb_get_end_points(libusb_device *dev, struct acr122_usb_data *data) { uint32_t uiIndex; uint32_t uiEndPoint; - struct usb_interface_descriptor *puid = dev->config->interface->altsetting; + struct libusb_config_descriptor *config; + if (libusb_get_config_descriptor(dev, 0, &config) != 0) + return; + const struct libusb_interface_descriptor *puid = &config->interface[0].altsetting[0]; // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) { // Only accept bulk transfer endpoints (ignore interrupt endpoints) - if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) + if ((puid->endpoint[uiIndex].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK) continue; // Copy the endpoint to a local var, makes it more readable code uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress; // Test if we dealing with a bulk IN endpoint - if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) { + if ((uiEndPoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { data->uiEndPointIn = uiEndPoint; data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize; } // Test if we dealing with a bulk OUT endpoint - if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) { + if ((uiEndPoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { data->uiEndPointOut = uiEndPoint; data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize; } } + + libusb_free_config_descriptor(config); } static size_t @@ -302,77 +307,91 @@ acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const { (void)context; - usb_prepare(); - size_t device_found = 0; - uint32_t uiBusIndex = 0; - struct usb_bus *bus; - for (bus = usb_get_busses(); bus; bus = bus->next) { - struct usb_device *dev; - - for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) { - for (size_t n = 0; n < sizeof(acr122_usb_supported_devices) / sizeof(struct acr122_usb_supported_device); n++) { - if ((acr122_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) && - (acr122_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { - // Make sure there are 2 endpoints available - // with libusb-win32 we got some null pointers so be robust before looking at endpoints: - if (dev->config == NULL || dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { - // Nope, we maybe want the next one, let's try to find another - continue; - } - if (dev->config->interface->altsetting->bNumEndpoints < 2) { - // Nope, we maybe want the next one, let's try to find another - continue; - } - - usb_dev_handle *udev = usb_open(dev); - if (udev == NULL) - continue; - - // Set configuration - // acr122_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice)); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s Name %s", bus->dirname, dev->filename, acr122_usb_supported_devices[n].name); - usb_close(udev); - if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", ACR122_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { - // truncation occurred, skipping that one - continue; - } - device_found++; - // Test if we reach the maximum "wanted" devices - if (device_found == connstrings_len) { - return device_found; - } + + libusb_context *ctx = usb_get_context(); + if (ctx == NULL) + return 0; + + libusb_device **devs; + ssize_t cnt = libusb_get_device_list(ctx, &devs); + if (cnt < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to get USB device list (%s)", libusb_strerror((int)cnt)); + return 0; + } + + for (ssize_t i = 0; i < cnt; i++) { + libusb_device *dev = devs[i]; + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(dev, &desc) != 0) + continue; + + for (size_t n = 0; n < sizeof(acr122_usb_supported_devices) / sizeof(struct acr122_usb_supported_device); n++) { + if ((acr122_usb_supported_devices[n].vendor_id == desc.idVendor) && + (acr122_usb_supported_devices[n].product_id == desc.idProduct)) { + // Make sure there are 2 endpoints available + struct libusb_config_descriptor *config; + if (libusb_get_config_descriptor(dev, 0, &config) != 0) + continue; + bool valid = (config->interface != NULL && + config->interface->altsetting != NULL && + config->interface->altsetting->bNumEndpoints >= 2); + libusb_free_config_descriptor(config); + if (!valid) + continue; + + libusb_device_handle *udev; + if (libusb_open(dev, &udev) != 0) + continue; + + uint8_t bus_number = libusb_get_bus_number(dev); + uint8_t device_address = libusb_get_device_address(dev); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %03d Device %03d Name %s", bus_number, device_address, acr122_usb_supported_devices[n].name); + libusb_close(udev); + if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%03d:%03d", ACR122_USB_DRIVER_NAME, bus_number, device_address) >= (int)sizeof(nfc_connstring)) { + // truncation occurred, skipping that one + continue; + } + device_found++; + // Test if we reach the maximum "wanted" devices + if (device_found == connstrings_len) { + libusb_free_device_list(devs, 1); + return device_found; } } } } + libusb_free_device_list(devs, 1); return device_found; } struct acr122_usb_descriptor { - char *dirname; - char *filename; + char *dirname; // bus number formatted as "%03d" + char *filename; // device address formatted as "%03d" }; static bool -acr122_usb_get_usb_device_name(struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len) +acr122_usb_get_usb_device_name(libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) { *buffer = '\0'; - if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) { + struct libusb_device_descriptor desc; + libusb_get_device_descriptor(dev, &desc); + + if (desc.iManufacturer || desc.iProduct) { if (udev) { - usb_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len); + libusb_get_string_descriptor_ascii(udev, desc.iManufacturer, (unsigned char *)buffer, len); if (strlen(buffer) > 0) strcpy(buffer + strlen(buffer), " / "); - usb_get_string_simple(udev, dev->descriptor.iProduct, buffer + strlen(buffer), len - strlen(buffer)); + libusb_get_string_descriptor_ascii(udev, desc.iProduct, (unsigned char *)(buffer + strlen(buffer)), len - strlen(buffer)); } } if (!*buffer) { for (size_t n = 0; n < sizeof(acr122_usb_supported_devices) / sizeof(struct acr122_usb_supported_device); n++) { - if ((acr122_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) && - (acr122_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { + if ((acr122_usb_supported_devices[n].vendor_id == desc.idVendor) && + (acr122_usb_supported_devices[n].product_id == desc.idProduct)) { strncpy(buffer, acr122_usb_supported_devices[n].name, len); buffer[len - 1] = '\0'; return true; @@ -399,83 +418,97 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) .uiEndPointIn = 0, .uiEndPointOut = 0, }; - struct usb_bus *bus; - struct usb_device *dev; - usb_prepare(); + libusb_context *ctx = usb_get_context(); + if (ctx == NULL) + goto free_mem; + + libusb_device **devs = NULL; + ssize_t cnt = libusb_get_device_list(ctx, &devs); + if (cnt < 0) + goto free_mem; - for (bus = usb_get_busses(); bus; bus = bus->next) { - if (connstring_decode_level > 1) { - // A specific bus have been specified - if (0 != strcmp(bus->dirname, desc.dirname)) + for (ssize_t i = 0; i < cnt; i++) { + libusb_device *dev = devs[i]; + + if (connstring_decode_level > 1) { + // A specific bus has been specified + char bus_str[4]; + snprintf(bus_str, sizeof(bus_str), "%03d", libusb_get_bus_number(dev)); + if (0 != strcmp(bus_str, desc.dirname)) continue; } - for (dev = bus->devices; dev; dev = dev->next) { - if (connstring_decode_level > 2) { - // A specific dev have been specified - if (0 != strcmp(dev->filename, desc.filename)) - continue; - } - // Open the USB device - if ((data.pudh = usb_open(dev)) == NULL) + if (connstring_decode_level > 2) { + // A specific device has been specified + char dev_str[4]; + snprintf(dev_str, sizeof(dev_str), "%03d", libusb_get_device_address(dev)); + if (0 != strcmp(dev_str, desc.filename)) continue; - // Reset device - usb_reset(data.pudh); - // Retrieve end points - acr122_usb_get_end_points(dev, &data); - // Claim interface - int res = usb_claim_interface(data.pudh, 0); - if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror(res)); - usb_close(data.pudh); - // we failed to use the specified device - goto free_mem; - } + } + // Open the USB device + if (libusb_open(dev, &data.pudh) != 0) + continue; + // Reset device + libusb_reset_device(data.pudh); + // Retrieve end points + acr122_usb_get_end_points(dev, &data); + // Claim interface + int res = libusb_claim_interface(data.pudh, 0); + if (res < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", libusb_strerror(res)); + libusb_close(data.pudh); + // we failed to use the specified device + goto free_mem; + } - // Check if there are more than 0 alternative interfaces and claim the first one - if (dev->config->interface->altsetting->bAlternateSetting > 0) { - res = usb_set_altinterface(data.pudh, 0); + // Check if there are more than 0 alternative interfaces and claim the first one + struct libusb_config_descriptor *config; + if (libusb_get_config_descriptor(dev, 0, &config) == 0) { + if (config->interface[0].altsetting[0].bAlternateSetting > 0) { + res = libusb_set_interface_alt_setting(data.pudh, 0, 0); if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", _usb_strerror(res)); - usb_close(data.pudh); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set alternate setting on USB interface (%s)", libusb_strerror(res)); + libusb_free_config_descriptor(config); + libusb_close(data.pudh); // we failed to use the specified device goto free_mem; } } + libusb_free_config_descriptor(config); + } - // Allocate memory for the device info and specification, fill it and return the info - pnd = nfc_device_new(context, connstring); - if (!pnd) { - perror("malloc"); - goto error; - } - acr122_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name)); + // Allocate memory for the device info and specification, fill it and return the info + pnd = nfc_device_new(context, connstring); + if (!pnd) { + perror("malloc"); + goto error; + } + acr122_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name)); - pnd->driver_data = malloc(sizeof(struct acr122_usb_data)); - if (!pnd->driver_data) { - perror("malloc"); - goto error; - } - *DRIVER_DATA(pnd) = data; + pnd->driver_data = malloc(sizeof(struct acr122_usb_data)); + if (!pnd->driver_data) { + perror("malloc"); + goto error; + } + *DRIVER_DATA(pnd) = data; - // Alloc and init chip's data - if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) { - perror("malloc"); - goto error; - } + // Alloc and init chip's data + if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) { + perror("malloc"); + goto error; + } - memcpy(&(DRIVER_DATA(pnd)->tama_frame), acr122_usb_frame_template, sizeof(acr122_usb_frame_template)); - memcpy(&(DRIVER_DATA(pnd)->apdu_frame), acr122_usb_frame_template, sizeof(acr122_usb_frame_template)); - CHIP_DATA(pnd)->timer_correction = 46; // empirical tuning - pnd->driver = &acr122_usb_driver; + memcpy(&(DRIVER_DATA(pnd)->tama_frame), acr122_usb_frame_template, sizeof(acr122_usb_frame_template)); + memcpy(&(DRIVER_DATA(pnd)->apdu_frame), acr122_usb_frame_template, sizeof(acr122_usb_frame_template)); + CHIP_DATA(pnd)->timer_correction = 46; // empirical tuning + pnd->driver = &acr122_usb_driver; - if (acr122_usb_init(pnd) < 0) { - usb_close(data.pudh); - goto error; - } - DRIVER_DATA(pnd)->abort_flag = false; - goto free_mem; + if (acr122_usb_init(pnd) < 0) { + libusb_close(data.pudh); + goto error; } + DRIVER_DATA(pnd)->abort_flag = false; + goto free_mem; } // We ran out of devices before the index required goto free_mem; @@ -485,6 +518,8 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) nfc_device_free(pnd); pnd = NULL; free_mem: + if (devs) + libusb_free_device_list(devs, 1); free(desc.dirname); free(desc.filename); return pnd; @@ -497,13 +532,11 @@ acr122_usb_close(nfc_device *pnd) pn53x_idle(pnd); int res; - if ((res = usb_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", _usb_strerror(res)); + if ((res = libusb_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", libusb_strerror(res)); } - if ((res = usb_close(DRIVER_DATA(pnd)->pudh)) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to close USB connection (%s)", _usb_strerror(res)); - } + libusb_close(DRIVER_DATA(pnd)->pudh); pn53x_data_free(pnd); nfc_device_free(pnd); } diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 52c40f082..6f8a274c4 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -77,7 +77,7 @@ typedef enum { // Internal data struct struct pn53x_usb_data { - usb_dev_handle *pudh; + libusb_device_handle *pudh; pn53x_usb_model model; uint32_t uiEndPointIn; uint32_t uiEndPointOut; @@ -90,36 +90,40 @@ struct pn53x_usb_data { const struct pn53x_io pn53x_usb_io; // Prototypes -bool pn53x_usb_get_usb_device_name(struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len); +bool pn53x_usb_get_usb_device_name(libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len); int pn53x_usb_init(nfc_device *pnd); static int pn53x_usb_bulk_read(struct pn53x_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout) { - int res = usb_bulk_read(data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, timeout); - if (res > 0) { - LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, res); - } else if (res < 0) { - if (res != -USB_TIMEDOUT) - log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", _usb_strerror(res)); - } - return res; + int transferred; + int res = libusb_bulk_transfer(data->pudh, data->uiEndPointIn, abtRx, szRx, &transferred, timeout); + if (res == 0) { + LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, transferred); + return transferred; + } else { + if (res != LIBUSB_ERROR_TIMEOUT) + log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", libusb_strerror(res)); + return res; + } } static int pn53x_usb_bulk_write(struct pn53x_usb_data *data, uint8_t abtTx[], const size_t szTx, const int timeout) { LOG_HEX(NFC_LOG_GROUP_COM, "TX", abtTx, szTx); - int res = usb_bulk_write(data->pudh, data->uiEndPointOut, (char *) abtTx, szTx, timeout); - if (res > 0) { + int transferred; + int res = libusb_bulk_transfer(data->pudh, data->uiEndPointOut, abtTx, szTx, &transferred, timeout); + if (res == 0) { // HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details - if ((res % data->uiMaxPacketSize) == 0) { - usb_bulk_write(data->pudh, data->uiEndPointOut, "\0", 0, timeout); + if ((transferred % data->uiMaxPacketSize) == 0) { + libusb_bulk_transfer(data->pudh, data->uiEndPointOut, (unsigned char *)"\0", 0, &transferred, timeout); } + return transferred; } else { - log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", _usb_strerror(res)); + log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", libusb_strerror(res)); + return res; } - return res; } struct pn53x_usb_supported_device { @@ -239,11 +243,13 @@ pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id) } static bool -pn53x_usb_get_end_points_default(struct usb_device *dev, struct pn53x_usb_data *data) +pn53x_usb_get_end_points_default(libusb_device *dev, struct pn53x_usb_data *data) { + struct libusb_device_descriptor desc; + libusb_get_device_descriptor(dev, &desc); for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) { - if ((dev->descriptor.idVendor == pn53x_usb_supported_devices[n].vendor_id) && - (dev->descriptor.idProduct == pn53x_usb_supported_devices[n].product_id)) { + if ((desc.idVendor == pn53x_usb_supported_devices[n].vendor_id) && + (desc.idProduct == pn53x_usb_supported_devices[n].product_id)) { if (pn53x_usb_supported_devices[n].uiMaxPacketSize != 0) { data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn; data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut; @@ -261,32 +267,37 @@ int pn53x_usb_ack(nfc_device *pnd); // Find transfer endpoints for bulk transfers static void -pn53x_usb_get_end_points(struct usb_device *dev, struct pn53x_usb_data *data) +pn53x_usb_get_end_points(libusb_device *dev, struct pn53x_usb_data *data) { uint32_t uiIndex; uint32_t uiEndPoint; - struct usb_interface_descriptor *puid = dev->config->interface->altsetting; + struct libusb_config_descriptor *config; + if (libusb_get_config_descriptor(dev, 0, &config) != 0) + return; + const struct libusb_interface_descriptor *puid = &config->interface[0].altsetting[0]; // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out for (uiIndex = 0; uiIndex < puid->bNumEndpoints; uiIndex++) { // Only accept bulk transfer endpoints (ignore interrupt endpoints) - if (puid->endpoint[uiIndex].bmAttributes != USB_ENDPOINT_TYPE_BULK) + if ((puid->endpoint[uiIndex].bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) != LIBUSB_TRANSFER_TYPE_BULK) continue; // Copy the endpoint to a local var, makes it more readable code uiEndPoint = puid->endpoint[uiIndex].bEndpointAddress; // Test if we dealing with a bulk IN endpoint - if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_IN) { + if ((uiEndPoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { data->uiEndPointIn = uiEndPoint; data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize; } // Test if we dealing with a bulk OUT endpoint - if ((uiEndPoint & USB_ENDPOINT_DIR_MASK) == USB_ENDPOINT_OUT) { + if ((uiEndPoint & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { data->uiEndPointOut = uiEndPoint; data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize; } } + + libusb_free_config_descriptor(config); } static size_t @@ -294,91 +305,94 @@ pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const s { (void)context; - usb_prepare(); - size_t device_found = 0; - uint32_t uiBusIndex = 0; - struct usb_bus *bus; - for (bus = usb_get_busses(); bus; bus = bus->next) { - struct usb_device *dev; - - for (dev = bus->devices; dev; dev = dev->next, uiBusIndex++) { - for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) { - if ((pn53x_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) && - (pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { - // Make sure there are 2 endpoints available - // libusb-win32 may return a NULL dev->config, - // or the descriptors may be corrupted, hence - // let us assume we will use hardcoded defaults - // from pn53x_usb_supported_devices if available. - // otherwise get data from the descriptors. - if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) { - if (dev->config->interface == NULL || dev->config->interface->altsetting == NULL) { - // Nope, we maybe want the next one, let's try to find another - continue; - } - if (dev->config->interface->altsetting->bNumEndpoints < 2) { - // Nope, we maybe want the next one, let's try to find another - continue; - } - } - - usb_dev_handle *udev = usb_open(dev); - if (udev == NULL) - continue; - // Set configuration - int res = usb_set_configuration(udev, 1); - if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror(res)); - usb_close(udev); - // we failed to use the device - continue; - } + libusb_context *ctx = usb_get_context(); + if (ctx == NULL) + return 0; + + libusb_device **devs; + ssize_t cnt = libusb_get_device_list(ctx, &devs); + if (cnt < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to get USB device list (%s)", libusb_strerror((int)cnt)); + return 0; + } - // pn53x_usb_get_usb_device_name (dev, udev, pnddDevices[device_found].acDevice, sizeof (pnddDevices[device_found].acDevice)); - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %s Device %s", bus->dirname, dev->filename); - usb_close(udev); - if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%s:%s", PN53X_USB_DRIVER_NAME, bus->dirname, dev->filename) >= (int)sizeof(nfc_connstring)) { - // truncation occurred, skipping that one + for (ssize_t i = 0; i < cnt; i++) { + libusb_device *dev = devs[i]; + struct libusb_device_descriptor desc; + if (libusb_get_device_descriptor(dev, &desc) != 0) + continue; + + for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) { + if ((pn53x_usb_supported_devices[n].vendor_id == desc.idVendor) && + (pn53x_usb_supported_devices[n].product_id == desc.idProduct)) { + // Make sure there are 2 endpoints available + // If no hardcoded defaults exist, verify from descriptors. + if (pn53x_usb_supported_devices[n].uiMaxPacketSize == 0) { + struct libusb_config_descriptor *config; + if (libusb_get_config_descriptor(dev, 0, &config) != 0) continue; - } - device_found++; - // Test if we reach the maximum "wanted" devices - if (device_found == connstrings_len) { - return device_found; - } + bool valid = (config->interface != NULL && + config->interface->altsetting != NULL && + config->interface->altsetting->bNumEndpoints >= 2); + libusb_free_config_descriptor(config); + if (!valid) + continue; + } + + libusb_device_handle *udev; + if (libusb_open(dev, &udev) != 0) + continue; + + uint8_t bus_number = libusb_get_bus_number(dev); + uint8_t device_address = libusb_get_device_address(dev); + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Bus %03d Device %03d", bus_number, device_address); + libusb_close(udev); + if (snprintf(connstrings[device_found], sizeof(nfc_connstring), "%s:%03d:%03d", PN53X_USB_DRIVER_NAME, bus_number, device_address) >= (int)sizeof(nfc_connstring)) { + // truncation occurred, skipping that one + continue; + } + device_found++; + // Test if we reach the maximum "wanted" devices + if (device_found == connstrings_len) { + libusb_free_device_list(devs, 1); + return device_found; } } } } + libusb_free_device_list(devs, 1); return device_found; } struct pn53x_usb_descriptor { - char *dirname; - char *filename; + char *dirname; // bus number formatted as "%03d" + char *filename; // device address formatted as "%03d" }; bool -pn53x_usb_get_usb_device_name(struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len) +pn53x_usb_get_usb_device_name(libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) { *buffer = '\0'; - if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) { + struct libusb_device_descriptor desc; + libusb_get_device_descriptor(dev, &desc); + + if (desc.iManufacturer || desc.iProduct) { if (udev) { - usb_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len); + libusb_get_string_descriptor_ascii(udev, desc.iManufacturer, (unsigned char *)buffer, len); if (strlen(buffer) > 0) strcpy(buffer + strlen(buffer), " / "); - usb_get_string_simple(udev, dev->descriptor.iProduct, buffer + strlen(buffer), len - strlen(buffer)); + libusb_get_string_descriptor_ascii(udev, desc.iProduct, (unsigned char *)(buffer + strlen(buffer)), len - strlen(buffer)); } } if (!*buffer) { for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) { - if ((pn53x_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) && - (pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) { + if ((pn53x_usb_supported_devices[n].vendor_id == desc.idVendor) && + (pn53x_usb_supported_devices[n].product_id == desc.idProduct)) { strncpy(buffer, pn53x_usb_supported_devices[n].name, len); buffer[len - 1] = '\0'; return true; @@ -406,113 +420,123 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) .uiEndPointOut = 0, .possibly_corrupted_usbdesc = false, }; - struct usb_bus *bus; - struct usb_device *dev; - usb_prepare(); + libusb_context *ctx = usb_get_context(); + if (ctx == NULL) + goto free_mem; + + libusb_device **devs = NULL; + ssize_t cnt = libusb_get_device_list(ctx, &devs); + if (cnt < 0) + goto free_mem; - for (bus = usb_get_busses(); bus; bus = bus->next) { - if (connstring_decode_level > 1) { - // A specific bus have been specified - if (0 != strcmp(bus->dirname, desc.dirname)) + for (ssize_t i = 0; i < cnt; i++) { + libusb_device *dev = devs[i]; + + if (connstring_decode_level > 1) { + // A specific bus has been specified + char bus_str[4]; + snprintf(bus_str, sizeof(bus_str), "%03d", libusb_get_bus_number(dev)); + if (0 != strcmp(bus_str, desc.dirname)) continue; } - for (dev = bus->devices; dev; dev = dev->next) { - if (connstring_decode_level > 2) { - // A specific dev have been specified - if (0 != strcmp(dev->filename, desc.filename)) - continue; - } - // Open the USB device - if ((data.pudh = usb_open(dev)) == NULL) + if (connstring_decode_level > 2) { + // A specific device has been specified + char dev_str[4]; + snprintf(dev_str, sizeof(dev_str), "%03d", libusb_get_device_address(dev)); + if (0 != strcmp(dev_str, desc.filename)) continue; + } - //To retrieve real USB endpoints configuration: - //pn53x_usb_get_end_points(dev, &data); - //printf("DEBUG ENDPOINTS In:0x%x Out:0x%x Size:0x%x\n", data.uiEndPointIn, data.uiEndPointOut, data.uiMaxPacketSize); + struct libusb_device_descriptor device_desc; + if (libusb_get_device_descriptor(dev, &device_desc) != 0) + continue; - // Retrieve end points, using hardcoded defaults if available - // or using the descriptors otherwise. - if (pn53x_usb_get_end_points_default(dev, &data) == false) { - pn53x_usb_get_end_points(dev, &data); - } - // Set configuration - int res = usb_set_configuration(data.pudh, 1); - if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", _usb_strerror(res)); - if (EPERM == -res) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: Please double check USB permissions for device %04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct); - } - usb_close(data.pudh); - // we failed to use the specified device - goto free_mem; - } + // Open the USB device + if (libusb_open(dev, &data.pudh) != 0) + continue; - res = usb_claim_interface(data.pudh, 0); - if (res < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", _usb_strerror(res)); - usb_close(data.pudh); - // we failed to use the specified device - goto free_mem; - } - data.model = pn53x_usb_get_device_model(dev->descriptor.idVendor, dev->descriptor.idProduct); - // Allocate memory for the device info and specification, fill it and return the info - pnd = nfc_device_new(context, connstring); - if (!pnd) { - perror("malloc"); - goto error; + // Retrieve end points, using hardcoded defaults if available + // or using the descriptors otherwise. + if (pn53x_usb_get_end_points_default(dev, &data) == false) { + pn53x_usb_get_end_points(dev, &data); + } + // Set configuration + int res = libusb_set_configuration(data.pudh, 1); + if (res < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", libusb_strerror(res)); + if (LIBUSB_ERROR_ACCESS == res) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "Warning: Please double check USB permissions for device %04x:%04x", device_desc.idVendor, device_desc.idProduct); } - pn53x_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name)); + libusb_close(data.pudh); + // we failed to use the specified device + goto free_mem; + } - pnd->driver_data = malloc(sizeof(struct pn53x_usb_data)); - if (!pnd->driver_data) { - perror("malloc"); - goto error; - } - *DRIVER_DATA(pnd) = data; + res = libusb_claim_interface(data.pudh, 0); + if (res < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", libusb_strerror(res)); + libusb_close(data.pudh); + // we failed to use the specified device + goto free_mem; + } + data.model = pn53x_usb_get_device_model(device_desc.idVendor, device_desc.idProduct); + // Allocate memory for the device info and specification, fill it and return the info + pnd = nfc_device_new(context, connstring); + if (!pnd) { + perror("malloc"); + goto error; + } + pn53x_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name)); - // Alloc and init chip's data - if (pn53x_data_new(pnd, &pn53x_usb_io) == NULL) { - perror("malloc"); - goto error; - } + pnd->driver_data = malloc(sizeof(struct pn53x_usb_data)); + if (!pnd->driver_data) { + perror("malloc"); + goto error; + } + *DRIVER_DATA(pnd) = data; - switch (DRIVER_DATA(pnd)->model) { - // empirical tuning - case ASK_LOGO: - CHIP_DATA(pnd)->timer_correction = 50; - CHIP_DATA(pnd)->progressive_field = true; - break; - case SCM_SCL3711: - case SCM_SCL3712: - case NXP_PN533: - CHIP_DATA(pnd)->timer_correction = 46; - break; - case NXP_PN531: - CHIP_DATA(pnd)->timer_correction = 50; - break; - case SONY_PN531: - CHIP_DATA(pnd)->timer_correction = 54; - break; - case SONY_RCS360: - case UNKNOWN: - CHIP_DATA(pnd)->timer_correction = 0; // TODO: allow user to know if timed functions are available - break; - } - pnd->driver = &pn53x_usb_driver; + // Alloc and init chip's data + if (pn53x_data_new(pnd, &pn53x_usb_io) == NULL) { + perror("malloc"); + goto error; + } - // HACK1: Send first an ACK as Abort command, to reset chip before talking to it: - pn53x_usb_ack(pnd); + switch (DRIVER_DATA(pnd)->model) { + // empirical tuning + case ASK_LOGO: + CHIP_DATA(pnd)->timer_correction = 50; + CHIP_DATA(pnd)->progressive_field = true; + break; + case SCM_SCL3711: + case SCM_SCL3712: + case NXP_PN533: + CHIP_DATA(pnd)->timer_correction = 46; + break; + case NXP_PN531: + CHIP_DATA(pnd)->timer_correction = 50; + break; + case SONY_PN531: + CHIP_DATA(pnd)->timer_correction = 54; + break; + case SONY_RCS360: + case UNKNOWN: + CHIP_DATA(pnd)->timer_correction = 0; // TODO: allow user to know if timed functions are available + break; + } + pnd->driver = &pn53x_usb_driver; - // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device - // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do - if (pn53x_usb_init(pnd) < 0) { - usb_close(data.pudh); - goto error; - } - DRIVER_DATA(pnd)->abort_flag = false; - goto free_mem; + // HACK1: Send first an ACK as Abort command, to reset chip before talking to it: + pn53x_usb_ack(pnd); + + // HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device + // in case host used set_configuration and expects the device to have reset its toggle bit, which PN53x doesn't do + if (pn53x_usb_init(pnd) < 0) { + libusb_close(data.pudh); + goto error; } + DRIVER_DATA(pnd)->abort_flag = false; + goto free_mem; } // We ran out of devices before the index required goto free_mem; @@ -522,6 +546,8 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) nfc_device_free(pnd); pnd = NULL; free_mem: + if (devs) + libusb_free_device_list(devs, 1); free(desc.dirname); free(desc.filename); return pnd; @@ -544,13 +570,11 @@ pn53x_usb_close(nfc_device *pnd) pn53x_idle(pnd); int res; - if ((res = usb_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", _usb_strerror(res)); + if ((res = libusb_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) { + log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", libusb_strerror(res)); } - if ((res = usb_close(DRIVER_DATA(pnd)->pudh)) < 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to close USB connection (%s)", _usb_strerror(res)); - } + libusb_close(DRIVER_DATA(pnd)->pudh); pn53x_data_free(pnd); nfc_device_free(pnd); } @@ -635,7 +659,7 @@ pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, con res = pn53x_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usb_timeout); - if (res == -USB_TIMEDOUT) { + if (res == LIBUSB_ERROR_TIMEOUT) { if (DRIVER_DATA(pnd)->abort_flag) { DRIVER_DATA(pnd)->abort_flag = false; pn53x_usb_ack(pnd); diff --git a/m4/libnfc_check_libusb.m4 b/m4/libnfc_check_libusb.m4 index 0d5b197fb..1bbf54f14 100644 --- a/m4/libnfc_check_libusb.m4 +++ b/m4/libnfc_check_libusb.m4 @@ -7,66 +7,30 @@ AC_DEFUN([LIBNFC_CHECK_LIBUSB], if test x"$libusb_required" = "xyes"; then HAVE_LIBUSB=0 - AC_ARG_WITH([libusb-win32], - [AS_HELP_STRING([--with-libusb-win32], [use libusb-win32 from the following location])], - [LIBUSB_WIN32_DIR=$withval], - [LIBUSB_WIN32_DIR=""]) - - # --with-libusb-win32 directory have been set - if test "x$LIBUSB_WIN32_DIR" != "x"; then - AC_MSG_NOTICE(["use libusb-win32 from $LIBUSB_WIN32_DIR"]) - libusb_CFLAGS="-I$LIBUSB_WIN32_DIR/include" - libusb_LIBS="-L$LIBUSB_WIN32_DIR/lib/gcc -lusb" - HAVE_LIBUSB=1 - fi - - # Search using libusb module using pkg-config - if test x"$HAVE_LIBUSB" = "x0"; then - if test x"$PKG_CONFIG" != "x"; then - PKG_CHECK_MODULES([libusb], [libusb], [HAVE_LIBUSB=1], [HAVE_LIBUSB=0]) - if test x"$HAVE_LIBUSB" = "x1"; then - if test x"$PKG_CONFIG_REQUIRES" != x""; then - PKG_CONFIG_REQUIRES="$PKG_CONFIG_REQUIRES," - fi - PKG_CONFIG_REQUIRES="$PKG_CONFIG_REQUIRES libusb" - fi - fi - fi - - # Search using libusb-legacy module using pkg-config - if test x"$HAVE_LIBUSB" = "x0"; then + # Search using libusb-1.0 module using pkg-config + if test x"$HAVE_LIBUSB" = "x0"; then if test x"$PKG_CONFIG" != "x"; then - PKG_CHECK_MODULES([libusb], [libusb-legacy], [HAVE_LIBUSB=1], [HAVE_LIBUSB=0]) + PKG_CHECK_MODULES([libusb], [libusb-1.0], [HAVE_LIBUSB=1], [HAVE_LIBUSB=0]) if test x"$HAVE_LIBUSB" = "x1"; then if test x"$PKG_CONFIG_REQUIRES" != x""; then PKG_CONFIG_REQUIRES="$PKG_CONFIG_REQUIRES," fi - PKG_CONFIG_REQUIRES="$PKG_CONFIG_REQUIRES libusb" + PKG_CONFIG_REQUIRES="$PKG_CONFIG_REQUIRES libusb-1.0" fi fi fi - # Search using libusb-config - if test x"$HAVE_LIBUSB" = "x0"; then - AC_PATH_PROG(libusb_CONFIG,libusb-config) - if test x"$libusb_CONFIG" != "x" ; then - libusb_CFLAGS=`$libusb_CONFIG --cflags` - libusb_LIBS=`$libusb_CONFIG --libs` - HAVE_LIBUSB=1 - fi - fi - # Search the library and headers directly (last chance) if test x"$HAVE_LIBUSB" = "x0"; then - AC_CHECK_HEADER(usb.h, [], [AC_MSG_ERROR([The libusb headers are missing])]) - AC_CHECK_LIB(usb, libusb_init, [], [AC_MSG_ERROR([The libusb library is missing])]) - - libusb_LIBS="-lusb" + AC_CHECK_HEADER(libusb.h, [], [AC_MSG_ERROR([The libusb-1.0 headers are missing])]) + AC_CHECK_LIB(usb-1.0, libusb_init, [], [AC_MSG_ERROR([The libusb-1.0 library is missing])]) + + libusb_LIBS="-lusb-1.0" HAVE_LIBUSB=1 fi if test x"$HAVE_LIBUSB" = "x0"; then - AC_MSG_ERROR([libusb is mandatory.]) + AC_MSG_ERROR([libusb-1.0 is mandatory.]) fi AC_SUBST(libusb_LIBS)