diff --git a/cmake/modules/FindLIBUSB.cmake b/cmake/modules/FindLIBUSB.cmake
index 4afd8afa..bf8fa22a 100644
--- a/cmake/modules/FindLIBUSB.cmake
+++ b/cmake/modules/FindLIBUSB.cmake
@@ -32,7 +32,7 @@ IF(NOT LIBUSB_FOUND)
SET(LIBUSB_LIBRARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibUSB-Win32/bin/x86/")
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")
+ FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0 libusb-1.0 libusb PATHS "$ENV{ProgramW6432}/libusb-win32/lib/msvc_x64")
SET(LIBUSB_LIBRARY_DIR "$ENV{ProgramW6432}/libusb-win32/bin/amd64/")
ENDIF(MINGW)
# Must fix up variable to avoid backslashes during packaging
@@ -41,7 +41,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/libnfc/buses/usbbus.c b/libnfc/buses/usbbus.c
index d2477f5a..fed730e4 100644
--- a/libnfc/buses/usbbus.c
+++ b/libnfc/buses/usbbus.c
@@ -7,6 +7,7 @@
* Copyright (C) 2010-2012 Romain Tartière
* Copyright (C) 2010-2013 Philippe Teuwen
* Copyright (C) 2012-2013 Ludovic Rousseau
+ * Copyright (C) 2022 Kenspeckle
* See AUTHORS file for a more comprehensive list of contributors.
* Additional contributors of this file:
*
@@ -24,56 +25,315 @@
* along with this program. If not, see
*
*/
-
-/**
- * @file usbbus.c
- * @brief libusb 0.1 driver wrapper
- */
+#include
+#include
+#include
+#include "usbbus.h"
+#include "log.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif // HAVE_CONFIG_H
-#include
-
-#include "usbbus.h"
-#include "log.h"
-#define LOG_CATEGORY "libnfc.buses.usbbus"
+#define LOG_CATEGORY "libnfc.bus.usbbus"
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
-int usb_prepare(void)
-{
+static libusb_context *ctx = NULL;
+
+uint8_t get_usb_num_configs(struct libusb_device *dev);
+
+int usbbus_prepare() {
static bool usb_initialized = false;
+ int res;
if (!usb_initialized) {
#ifdef ENVVARS
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
// Set libusb debug only if asked explicitely:
// 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)) {
+ if (env_log_level
+ && (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
setenv("USB_DEBUG", "255", 1);
}
#endif
- usb_init();
+ res = libusb_init(&ctx);
+ if (res != 0) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unable to init libusb (%s)",
+ libusb_strerror(res));
+ return res;
+ }
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));
+ libusb_device **tmp_devices;
+ ssize_t num_devices = libusb_get_device_list(ctx, &tmp_devices);
+ libusb_free_device_list(tmp_devices, (int) num_devices);
+ if (num_devices <= 0) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unable to find USB devices (%s)",
+ libusb_strerror((int) num_devices));
return -1;
}
return 0;
}
+size_t usbbus_usb_scan(nfc_connstring connstrings[],
+ const size_t connstrings_len,
+ struct usbbus_device *nfc_usb_devices,
+ const size_t num_nfc_usb_devices,
+ char *usb_driver_name) {
+ usbbus_prepare();
+
+ size_t device_found = 0;
+ struct libusb_device **devices;
+ ssize_t num_devices = libusb_get_device_list(ctx, &devices);
+ for (size_t i = 0; i < num_devices; i++) {
+ struct libusb_device *dev = devices[i];
+
+ for (size_t nfc_dev_idx = 0; nfc_dev_idx < num_nfc_usb_devices; nfc_dev_idx++) {
+ if (nfc_usb_devices[nfc_dev_idx].vendor_id == usbbus_get_vendor_id(dev)
+ && nfc_usb_devices[nfc_dev_idx].product_id == usbbus_get_product_id(dev)) {
+
+ size_t valid_config_idx = 1;
+
+ // Make sure there are 2 endpoints available
+ // with libusb-win32 we got some null pointers so be robust before looking at endpoints
+ if (nfc_usb_devices[nfc_dev_idx].max_packet_size == 0) {
+
+ bool found_valid_config = false;
+
+ for (size_t config_idx = 0; config_idx < get_usb_num_configs(dev); i++) {
+ struct libusb_config_descriptor *usb_config;
+ int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
+
+ if (r != 0
+ || usb_config->interface == NULL
+ || usb_config->interface->altsetting == NULL
+ || usb_config->interface->altsetting->bNumEndpoints < 2) {
+ // Nope, we maybe want the next one, let's try to find another
+ libusb_free_config_descriptor(usb_config);
+ continue;
+ }
+
+ libusb_free_config_descriptor(usb_config);
+
+ found_valid_config = true;
+ valid_config_idx = config_idx;
+ break;
+ }
+ if (!found_valid_config) {
+ libusb_unref_device(dev);
+ continue;
+ }
+ }
+
+ libusb_device_handle *udev;
+ int res = libusb_open(dev, &udev);
+ if (res < 0 && udev == NULL) {
+ libusb_unref_device(dev);
+ continue;
+ }
+
+ // Set configuration
+ res = libusb_set_configuration(udev, (int) valid_config_idx);
+ if (res < 0) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unable to set USB configuration (%s)",
+ libusb_strerror(res));
+ libusb_close(udev);
+ libusb_unref_device(dev);
+ // we failed to use the device
+ continue;
+ }
+
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Vendor-Id: %d Product-Id %d",
+ usbbus_get_vendor_id(dev), usbbus_get_product_id(dev));
+ libusb_close(udev);
+
+ uint8_t dev_address = libusb_get_device_address(dev);
+ printf("%s:%03d:%03d",
+ "Test",
+ dev_address,
+ (int) valid_config_idx);
+ size_t size_new_str = snprintf(
+ connstrings[device_found],
+ sizeof(connstrings[device_found]),
+ "%s:%03d:%03d",
+ usb_driver_name,
+ dev_address,
+ (int) valid_config_idx);
+
+ if (size_new_str >= (int) sizeof(nfc_connstring)) {
+ // truncation occurred, skipping that one
+ libusb_unref_device(dev);
+ continue;
+ }
+ device_found++;
+ // Test if we reach the maximum "wanted" devices
+ if (device_found == connstrings_len) {
+ libusb_free_device_list(devices, 0);
+ return device_found;
+ }
+ }
+ }
+ }
+ libusb_free_device_list(devices, 0);
+ return device_found;
+}
+
+void usbbus_get_usb_endpoints(struct libusb_device *dev,
+ uint8_t *endpoint_in,
+ uint8_t *endpoint_out,
+ uint16_t *max_packet_size) {
+
+ bool endpoint_in_set = false;
+ bool endpoint_out_set = false;
+ size_t num_configs = get_usb_num_configs(dev);
+ for (size_t config_idx = 0; config_idx < num_configs; config_idx++) {
+ struct libusb_config_descriptor *usb_config;
+
+ int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
+ if (r != 0) {
+ continue;
+ }
+
+ if (!usb_config->interface) {
+ continue;
+ }
+ for (size_t interface_idx = 0; interface_idx < usb_config->bNumInterfaces; interface_idx++) {
+ struct libusb_interface interface = usb_config->interface[interface_idx];
+ if (!interface.altsetting) {
+ continue;
+ }
+ for (size_t settings_idx = 0; settings_idx < interface.num_altsetting; settings_idx++) {
+ struct libusb_interface_descriptor settings = interface.altsetting[settings_idx];
+ if (!settings.endpoint) {
+ continue;
+ }
+
+ // 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
+ for (size_t endpoint_idx = 0; endpoint_idx < settings.bNumEndpoints; endpoint_idx++) {
+ struct libusb_endpoint_descriptor endpoint = settings.endpoint[endpoint_idx];
+
+ // Only accept bulk transfer endpoints (ignore interrupt endpoints)
+ if (endpoint.bmAttributes != LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK) {
+ continue;
+ }
+
+ // Copy the endpoint to a local var, makes it more readable code
+ uint8_t endpoint_address = endpoint.bEndpointAddress;
+
+ // Test if we dealing with a bulk IN endpoint
+ if ((endpoint_address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN && !endpoint_in_set) {
+ *endpoint_in = endpoint_address;
+ *max_packet_size = endpoint.wMaxPacketSize;
+ endpoint_in_set = true;
+ }
+ // Test if we dealing with a bulk OUT endpoint
+ if ((endpoint_address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT && !endpoint_out_set) {
+ *endpoint_out = endpoint_address;
+ *max_packet_size = endpoint.wMaxPacketSize;
+ endpoint_out_set = true;
+ }
+
+ if (endpoint_in_set && endpoint_out_set) {
+ libusb_free_config_descriptor(usb_config);
+ return;
+ }
+ }
+ }
+ }
+
+ libusb_free_config_descriptor(usb_config);
+ }
+}
+
+uint8_t get_usb_num_configs(struct libusb_device *dev) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(dev, &descriptor);
+ return descriptor.bNumConfigurations;
+}
+
+void usbbus_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(dev, &descriptor);
+ if (descriptor.iManufacturer || descriptor.iProduct) {
+ if (udev) {
+ libusb_get_string_descriptor_ascii(udev, descriptor.iManufacturer & 0xff, (unsigned char *) buffer, len);
+ if (strlen(buffer) > 0) {
+ strncpy(buffer + strlen(buffer), " / ", 4);
+ }
+ libusb_get_string_descriptor_ascii(udev,
+ descriptor.iProduct & 0xff,
+ (unsigned char *) buffer + strlen(buffer),
+ len - strlen(buffer));
+ }
+ }
+}
+
+
+void usbbus_get_device(uint8_t dev_address, struct libusb_device ** dev, struct libusb_device_handle ** dev_handle) {
+ struct libusb_device ** device_list;
+ ssize_t num_devices = libusb_get_device_list(ctx, &device_list);
+ for (size_t i = 0; i < num_devices; i++) {
+ if (libusb_get_device_address(device_list[i]) != dev_address) {
+ continue;
+ } else {
+ *dev = device_list[i];
+ int res = libusb_open(*dev, dev_handle);
+ if (res != 0 || dev_handle == NULL) {
+ log_put(LOG_GROUP,LOG_CATEGORY,NFC_LOG_PRIORITY_ERROR,
+ "Unable to open libusb device (%s)",libusb_strerror(res));
+ continue;
+ }
+ }
+ }
+
+ // libusb works with a reference counter which is set to 1 for each device when calling libusb_get_device_list and increased
+ // by libusb_open. Thus we decrease the counter by 1 for all devices and only the "real" device will survive
+ libusb_free_device_list(device_list, num_devices);
+}
+
+
+void usbbus_close(struct libusb_device * dev, struct libusb_device_handle * dev_handle) {
+ libusb_close(dev_handle);
+ libusb_unref_device(dev);
+ libusb_exit(ctx);
+}
+
+uint16_t usbbus_get_vendor_id(struct libusb_device *dev) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(dev, &descriptor);
+ return descriptor.idVendor;
+}
+
+uint16_t usbbus_get_product_id(struct libusb_device *dev) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(dev, &descriptor);
+ return descriptor.idProduct;
+}
+
+
+int usbbus_get_num_alternate_settings(struct libusb_device *dev, uint8_t config_idx) {
+ struct libusb_config_descriptor *usb_config;
+ int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
+ if (r != 0 || usb_config == NULL) {
+ return -1;
+ }
+ libusb_free_config_descriptor(usb_config);
+ return usb_config->interface->num_altsetting;
+}
+
+
+
diff --git a/libnfc/buses/usbbus.h b/libnfc/buses/usbbus.h
index 3c0381a8..8ac87091 100644
--- a/libnfc/buses/usbbus.h
+++ b/libnfc/buses/usbbus.h
@@ -7,6 +7,7 @@
* Copyright (C) 2010-2012 Romain Tartière
* Copyright (C) 2010-2013 Philippe Teuwen
* Copyright (C) 2012-2013 Ludovic Rousseau
+ * Copyright (C) 2022 Kenspeckle
* See AUTHORS file for a more comprehensive list of contributors.
* Additional contributors of this file:
*
@@ -25,30 +26,32 @@
*
*/
-/**
- * @file usbbus.h
- * @brief libusb 0.1 driver header
- */
+#ifndef __NFC_BUS_USBBUS_H__
+#define __NFC_BUS_USBBUS_H__
-#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 "nfc/nfc-types.h"
+
+#define EMPTY_STRING ((unsigned char *)"\0")
-#include
-#include
+struct usbbus_device {
+ uint16_t vendor_id;
+ uint16_t product_id;
+ const char *name;
+ uint16_t max_packet_size;
+};
-int usb_prepare(void);
-#endif // __NFC_BUS_USB_H__
+
+int usbbus_prepare();
+
+size_t usbbus_usb_scan(nfc_connstring connstrings[], size_t connstrings_len, struct usbbus_device * nfc_usb_devices, size_t num_nfc_usb_devices, char * usb_driver_name);
+void usbbus_get_usb_endpoints(struct libusb_device *dev, uint8_t * endpoint_in, uint8_t * endpoint_out, uint16_t * max_packet_size);
+void usbbus_get_usb_device_name(struct libusb_device * dev, libusb_device_handle *udev, char *buffer, size_t len);
+void usbbus_get_device(uint8_t dev_address, struct libusb_device ** dev, struct libusb_device_handle ** dev_handle);
+void usbbus_close(struct libusb_device * dev, struct libusb_device_handle * dev_handle);
+uint16_t usbbus_get_vendor_id(struct libusb_device * dev);
+uint16_t usbbus_get_product_id(struct libusb_device * dev);
+int usbbus_get_num_alternate_settings(struct libusb_device *dev, uint8_t config_idx);
+#endif
diff --git a/libnfc/drivers/acr122_usb.c b/libnfc/drivers/acr122_usb.c
index fc545014..4e662d48 100644
--- a/libnfc/drivers/acr122_usb.c
+++ b/libnfc/drivers/acr122_usb.c
@@ -76,7 +76,7 @@ Thanks to d18c7db and Okko for example code
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
#define LOG_CATEGORY "libnfc.driver.acr122_usb"
-#define USB_INFINITE_TIMEOUT 0
+#define USBBUS_INFINITE_TIMEOUT 0
#define DRIVER_DATA(pnd) ((struct acr122_usb_data*)(pnd->driver_data))
@@ -174,10 +174,12 @@ struct acr122_usb_apdu_frame {
// Internal data struct
struct acr122_usb_data {
- usb_dev_handle *pudh;
- uint32_t uiEndPointIn;
- uint32_t uiEndPointOut;
- uint32_t uiMaxPacketSize;
+ libusb_device * dev;
+ libusb_device_handle *pudh;
+ uint8_t configIdx;
+ uint8_t uiEndPointIn;
+ uint8_t uiEndPointOut;
+ uint16_t uiMaxPacketSize;
volatile bool abort_flag;
// Keep some buffers to reduce memcpy() usage
struct acr122_usb_tama_frame tama_frame;
@@ -220,13 +222,15 @@ 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) {
+ int actual_length;
+ int res = libusb_bulk_transfer(data->pudh, data->uiEndPointIn, (unsigned char *) abtRx, szRx, &actual_length, timeout);
+ if (res == 0) {
+ LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, actual_length);
+ res = actual_length;
+ } else {
+ if (res != LIBUSB_ERROR_TIMEOUT) {
res = NFC_EIO;
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", _usb_strerror(res));
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", libusb_strerror(res));
} else {
res = NFC_ETIMEOUT;
}
@@ -238,15 +242,16 @@ 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 actual_length;
+ int res = libusb_bulk_transfer(data->pudh, data->uiEndPointOut, (unsigned char *) abtTx, szTx, &actual_length, 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 ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
+ libusb_bulk_transfer(data->pudh, data->uiEndPointOut, EMPTY_STRING, 0, &actual_length, 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) {
+ } 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) {
res = NFC_ETIMEOUT;
} else {
res = NFC_EIO;
@@ -259,120 +264,46 @@ struct acr122_usb_supported_device {
uint16_t vendor_id;
uint16_t product_id;
const char *name;
+ uint16_t max_packet_size;
};
const struct acr122_usb_supported_device acr122_usb_supported_devices[] = {
- { 0x072F, 0x2200, "ACS ACR122" },
- { 0x072F, 0x90CC, "Touchatag" },
- { 0x072F, 0x2214, "ACS ACR1222" },
+ { 0x072F, 0x2200, "ACS ACR122", 0x40 },
+ { 0x072F, 0x90CC, "Touchatag", 0x40 },
+ { 0x072F, 0x2214, "ACS ACR1222", 0x40 },
};
-// Find transfer endpoints for bulk transfers
-static void
-acr122_usb_get_end_points(struct usb_device *dev, struct acr122_usb_data *data)
-{
- uint32_t uiIndex;
- uint32_t uiEndPoint;
- struct usb_interface_descriptor *puid = dev->config->interface->altsetting;
-
- // 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)
- 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) {
- 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) {
- data->uiEndPointOut = uiEndPoint;
- data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
- }
- }
-}
+const size_t num_acr122_usb_supported_device = sizeof(acr122_usb_supported_devices) / sizeof(struct acr122_usb_supported_device);
+
+
static size_t
acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
{
- (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;
- }
- }
- }
- }
+ (void) context;
+ struct usbbus_device devices[num_acr122_usb_supported_device];
+ for (size_t i = 0; i < num_acr122_usb_supported_device; i++) {
+ devices[i].product_id = acr122_usb_supported_devices[i].product_id;
+ devices[i].vendor_id = acr122_usb_supported_devices[i].vendor_id;
+ devices[i].name = acr122_usb_supported_devices[i].name;
+ devices[i].max_packet_size = acr122_usb_supported_devices[i].max_packet_size;
}
-
- return device_found;
+ return usbbus_usb_scan(connstrings, connstrings_len, devices, num_acr122_usb_supported_device, ACR122_USB_DRIVER_NAME);
}
-struct acr122_usb_descriptor {
- char *dirname;
- char *filename;
-};
-
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(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len)
{
*buffer = '\0';
- if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
- if (udev) {
- usb_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len);
- if (strlen(buffer) > 0)
- strcpy(buffer + strlen(buffer), " / ");
- usb_get_string_simple(udev, dev->descriptor.iProduct, buffer + strlen(buffer), len - strlen(buffer));
- }
- }
+ usbbus_get_usb_device_name(dev, udev, buffer, len);
+ uint16_t vendor_id = usbbus_get_vendor_id(dev);
+ uint16_t product_id = usbbus_get_product_id(dev);
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)) {
+ for (size_t n = 0; n < num_acr122_usb_supported_device; n++) {
+ if ((acr122_usb_supported_devices[n].vendor_id == vendor_id) &&
+ (acr122_usb_supported_devices[n].product_id == product_id)) {
strncpy(buffer, acr122_usb_supported_devices[n].name, len);
buffer[len - 1] = '\0';
return true;
@@ -387,106 +318,115 @@ static nfc_device *
acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
{
nfc_device *pnd = NULL;
- struct acr122_usb_descriptor desc = { NULL, NULL };
- int connstring_decode_level = connstring_decode(connstring, ACR122_USB_DRIVER_NAME, "usb", &desc.dirname, &desc.filename);
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%d element(s) have been decoded from \"%s\"", connstring_decode_level, connstring);
- if (connstring_decode_level < 1) {
- goto free_mem;
+ char *dev_address_str;
+ char *config_idx_str;
+ int connstring_decode_level = connstring_decode(connstring, ACR122_USB_DRIVER_NAME, "usb", &dev_address_str, &config_idx_str);
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_DEBUG,
+ "%d element(s) have been decoded from \"%s\"",
+ connstring_decode_level,
+ connstring);
+ if (connstring_decode_level < 2) {
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
}
+ uint8_t dev_addres = atoi(dev_address_str);
+ uint8_t config_idx = atoi(config_idx_str);
+
+ usbbus_prepare();
struct acr122_usb_data data = {
+ .dev = NULL,
.pudh = NULL,
+ .configIdx = config_idx,
.uiEndPointIn = 0,
.uiEndPointOut = 0,
};
- struct usb_bus *bus;
- struct usb_device *dev;
-
- usb_prepare();
+ usbbus_get_device(dev_addres, &data.dev, &data.pudh);
+ // Reset device
+ libusb_reset_device(data.pudh);
+
+ // Retrieve end points
+ usbbus_get_usb_endpoints(data.dev, &(data.uiEndPointIn), &(data.uiEndPointOut), &(data.uiMaxPacketSize));
+ // 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
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
- 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))
- continue;
+ // Check if there are more than 0 alternative interfaces and claim the first one
+ if (usbbus_get_num_alternate_settings(data.dev, data.configIdx) > 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)",
+ libusb_strerror(res));
+ libusb_close(data.pudh);
+ // we failed to use the specified device
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
}
- 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)
- 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;
- }
-
- // 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);
- 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);
- // we failed to use the specified device
- goto free_mem;
- }
- }
-
- // 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;
-
- // 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;
+ // Allocate memory for the device info and specification, fill it and return the info
+ pnd = nfc_device_new(context, connstring);
+ if (!pnd) {
+ perror("malloc");
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+ acr122_usb_get_usb_device_name(data.dev, data.pudh, pnd->name, sizeof(pnd->name));
+
+ pnd->driver_data = malloc(sizeof(struct acr122_usb_data));
+ if (!pnd->driver_data) {
+ perror("malloc");
+ nfc_device_free(pnd);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+ *DRIVER_DATA(pnd) = data;
+
+ // Alloc and init chip's data
+ if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) {
+ perror("malloc");
+ nfc_device_free(pnd);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
- if (acr122_usb_init(pnd) < 0) {
- usb_close(data.pudh);
- goto error;
- }
- DRIVER_DATA(pnd)->abort_flag = false;
- goto free_mem;
- }
+ 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) {
+ libusb_close(data.pudh);
+ nfc_device_free(pnd);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
}
- // We ran out of devices before the index required
- goto free_mem;
+ DRIVER_DATA(pnd)->abort_flag = false;
-error:
- // Free allocated structure on error.
- nfc_device_free(pnd);
- pnd = NULL;
-free_mem:
- free(desc.dirname);
- free(desc.filename);
+ free(dev_address_str);
+ free(config_idx_str);
return pnd;
}
@@ -496,14 +436,17 @@ acr122_usb_close(nfc_device *pnd)
acr122_usb_ack(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));
+ int res = libusb_release_interface(DRIVER_DATA(pnd)->pudh, 0);
+ if (res < 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));
- }
+ usbbus_close(DRIVER_DATA(pnd)->dev, DRIVER_DATA(pnd)->pudh);
+
pn53x_data_free(pnd);
nfc_device_free(pnd);
}
@@ -579,7 +522,8 @@ acr122_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, co
return NFC_SUCCESS;
}
-#define USB_TIMEOUT_PER_PASS 200
+#define USBBUS_TIMEOUT_PER_PASS 200
+
static int
acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout)
{
@@ -589,26 +533,26 @@ acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, co
int res;
/*
- * If no timeout is specified but the command is blocking, force a 200ms (USB_TIMEOUT_PER_PASS)
+ * If no timeout is specified but the command is blocking, force a 200ms (USBBUS_TIMEOUT_PER_PASS)
* timeout to allow breaking the loop if the user wants to stop it.
*/
- int usb_timeout;
+ int usbbus_timeout;
int remaining_time = timeout;
read:
- if (timeout == USB_INFINITE_TIMEOUT) {
- usb_timeout = USB_TIMEOUT_PER_PASS;
+ if (timeout == USBBUS_INFINITE_TIMEOUT) {
+ usbbus_timeout = USBBUS_TIMEOUT_PER_PASS;
} else {
// A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
- remaining_time -= USB_TIMEOUT_PER_PASS;
+ remaining_time -= USBBUS_TIMEOUT_PER_PASS;
if (remaining_time <= 0) {
pnd->last_error = NFC_ETIMEOUT;
return pnd->last_error;
} else {
- usb_timeout = MIN(remaining_time, USB_TIMEOUT_PER_PASS);
+ usbbus_timeout = MIN(remaining_time, USBBUS_TIMEOUT_PER_PASS);
}
}
- res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usb_timeout);
+ res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usbbus_timeout);
uint8_t attempted_response = RDR_to_PC_DataBlock;
size_t len;
diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c
index 52c40f08..2bed980e 100644
--- a/libnfc/drivers/pn53x_usb.c
+++ b/libnfc/drivers/pn53x_usb.c
@@ -31,6 +31,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
+
#endif // HAVE_CONFIG_H
/*
@@ -41,13 +42,13 @@ Thanks to d18c7db and Okko for example code
#include
#include
#include
-#include
#include
+
#ifdef _MSC_VER
#include
#endif
#include
-
+#include
#include "nfc-internal.h"
#include "buses/usbbus.h"
#include "chips/pn53x.h"
@@ -58,851 +59,778 @@ Thanks to d18c7db and Okko for example code
#define LOG_CATEGORY "libnfc.driver.pn53x_usb"
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
-#define USB_INFINITE_TIMEOUT 0
+#define USBBUS_INFINITE_TIMEOUT 0
#define DRIVER_DATA(pnd) ((struct pn53x_usb_data*)(pnd->driver_data))
const nfc_modulation_type no_target_support[] = {0};
typedef enum {
- UNKNOWN,
- NXP_PN531,
- SONY_PN531,
- NXP_PN533,
- ASK_LOGO,
- SCM_SCL3711,
- SCM_SCL3712,
- SONY_RCS360
+ UNKNOWN,
+ NXP_PN531,
+ SONY_PN531,
+ NXP_PN533,
+ ASK_LOGO,
+ SCM_SCL3711,
+ SCM_SCL3712,
+ SONY_RCS360
} pn53x_usb_model;
// Internal data struct
struct pn53x_usb_data {
- usb_dev_handle *pudh;
- pn53x_usb_model model;
- uint32_t uiEndPointIn;
- uint32_t uiEndPointOut;
- uint32_t uiMaxPacketSize;
- volatile bool abort_flag;
- bool possibly_corrupted_usbdesc;
+ libusb_device * dev;
+ libusb_device_handle *pudh;
+ uint8_t configIdx;
+ pn53x_usb_model model;
+ uint8_t uiEndPointIn;
+ uint8_t uiEndPointOut;
+ uint16_t uiMaxPacketSize;
+ volatile bool abort_flag;
+ bool possibly_corrupted_usbdesc;
};
// Internal io struct
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(struct 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;
+pn53x_usb_bulk_read(struct pn53x_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout) {
+ int actual_length;
+ int res = libusb_bulk_transfer(data->pudh, data->uiEndPointIn & 0xff, abtRx, szRx, &actual_length, timeout);
+ if (res == 0) {
+ LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, actual_length);
+ res = actual_length;
+ } 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) {
- // 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);
- }
- } else {
- log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", _usb_strerror(res));
- }
- return res;
+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 actual_length;
+ int res = libusb_bulk_transfer(data->pudh, data->uiEndPointOut & 0xff, abtTx, szTx, &actual_length, 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 ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
+ libusb_bulk_transfer(data->pudh, data->uiEndPointOut & 0xff, EMPTY_STRING, 0, &actual_length, timeout);
+ }
+ } else {
+ log_put(NFC_LOG_GROUP_COM,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unable to write to USB (%s)",
+ libusb_strerror(res));
+ }
+ return res;
}
struct pn53x_usb_supported_device {
- uint16_t vendor_id;
- uint16_t product_id;
- pn53x_usb_model model;
- const char *name;
- /* hardcoded known values for buggy hardware whose configuration vanishes */
- uint32_t uiEndPointIn;
- uint32_t uiEndPointOut;
- uint32_t uiMaxPacketSize;
+ uint16_t vendor_id;
+ uint16_t product_id;
+ pn53x_usb_model model;
+ const char *name;
+ /* hardcoded known values for buggy hardware whose configuration vanishes */
+ uint32_t uiEndPointIn;
+ uint32_t uiEndPointOut;
+ uint32_t uiMaxPacketSize;
};
const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = {
- { 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40 },
- { 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x84, 0x04, 0x40 },
- { 0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x84, 0x04, 0x40 },
- { 0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0 }, // to check on real device
- { 0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0x84, 0x04, 0x40 },
- { 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40 },
- { 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0x84, 0x04, 0x40 }
+ {0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40},
+ {0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 0x84, 0x04, 0x40},
+ {0x04E6, 0x5591, SCM_SCL3711, "SCM Micro / SCL3711-NFC&RW", 0x84, 0x04, 0x40},
+ {0x04E6, 0x5594, SCM_SCL3712, "SCM Micro / SCL3712-NFC&RW", 0, 0, 0}, // to check on real device
+ {0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0x84, 0x04, 0x40},
+ {0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40},
+ {0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 0x84, 0x04, 0x40}
};
+const size_t num_pn53x_usb_supported_devices = sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device);
+
// PN533 USB descriptors backup buffers
const uint8_t btXramUsbDesc_scl3711[] = {
- 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00,
- 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
- 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x1e, 0x03, 0x53, 0x00,
- 0x43, 0x00, 0x4c, 0x00, 0x33, 0x00, 0x37, 0x00, 0x31, 0x00, 0x31, 0x00,
- 0x2d, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x43, 0x00, 0x26, 0x00, 0x52, 0x00,
- 0x57,
+ 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00,
+ 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
+ 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x1e, 0x03, 0x53, 0x00,
+ 0x43, 0x00, 0x4c, 0x00, 0x33, 0x00, 0x37, 0x00, 0x31, 0x00, 0x31, 0x00,
+ 0x2d, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x43, 0x00, 0x26, 0x00, 0x52, 0x00,
+ 0x57,
};
const uint8_t btXramUsbDesc_nxppn533[] = {
- 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00,
- 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
- 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0c, 0x03, 0x50, 0x00,
- 0x4e, 0x00, 0x35, 0x00, 0x33, 0x00, 0x33, 0x00, 0x04, 0x03, 0x09, 0x04,
- 0x08, 0x03, 0x4e, 0x00, 0x58, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
+ 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00,
+ 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
+ 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0c, 0x03, 0x50, 0x00,
+ 0x4e, 0x00, 0x35, 0x00, 0x33, 0x00, 0x33, 0x00, 0x04, 0x03, 0x09, 0x04,
+ 0x08, 0x03, 0x4e, 0x00, 0x58, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
};
const uint8_t btXramUsbDesc_asklogo[] = {
- 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, 0x04, 0x00,
- 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
- 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0a, 0x03, 0x4c, 0x00,
- 0x6f, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x04, 0x03, 0x09, 0x04, 0x08, 0x03,
- 0x41, 0x00, 0x53, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
+ 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x96, 0x09, 0x04, 0x00,
+ 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00,
+ 0x04, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x04, 0x0a, 0x03, 0x4c, 0x00,
+ 0x6f, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x04, 0x03, 0x09, 0x04, 0x08, 0x03,
+ 0x41, 0x00, 0x53, 0x00, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
};
-static void pn533_fix_usbdesc(nfc_device *pnd)
-{
- // PN533 USB descriptors may have been corrupted by large commands/responses
- // so they need to be restored before closing usb connection.
- // cf PN5331B3HNC270 Release Note
- uint32_t szXramUsbDesc = 0;
- uint8_t *btXramUsbDesc = NULL;
- if (DRIVER_DATA(pnd)->model == NXP_PN533) {
- btXramUsbDesc = (uint8_t *)btXramUsbDesc_nxppn533;
- szXramUsbDesc = sizeof(btXramUsbDesc_nxppn533);
- } else if (DRIVER_DATA(pnd)->model == SCM_SCL3711) {
- btXramUsbDesc = (uint8_t *)btXramUsbDesc_scl3711;
- szXramUsbDesc = sizeof(btXramUsbDesc_scl3711);
- } else if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
- btXramUsbDesc = (uint8_t *)btXramUsbDesc_asklogo;
- szXramUsbDesc = sizeof(btXramUsbDesc_asklogo);
- }
+static void pn533_fix_usbdesc(nfc_device *pnd) {
+ // PN533 USB descriptors may have been corrupted by large commands/responses
+ // so they need to be restored before closing usb connection.
+ // cf PN5331B3HNC270 Release Note
+ uint32_t szXramUsbDesc = 0;
+ uint8_t *btXramUsbDesc = NULL;
+ if (DRIVER_DATA(pnd)->model == NXP_PN533) {
+ btXramUsbDesc = (uint8_t *) btXramUsbDesc_nxppn533;
+ szXramUsbDesc = sizeof(btXramUsbDesc_nxppn533);
+ } else if (DRIVER_DATA(pnd)->model == SCM_SCL3711) {
+ btXramUsbDesc = (uint8_t *) btXramUsbDesc_scl3711;
+ szXramUsbDesc = sizeof(btXramUsbDesc_scl3711);
+ } else if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
+ btXramUsbDesc = (uint8_t *) btXramUsbDesc_asklogo;
+ szXramUsbDesc = sizeof(btXramUsbDesc_asklogo);
+ }
#define MAXSZXRAMUSBDESC 61
- if ((szXramUsbDesc == 0) || (MAXSZXRAMUSBDESC > 61))
- return;
+ if ((szXramUsbDesc == 0) || (MAXSZXRAMUSBDESC > 61))
+ return;
#if 0
- // Debug routine to check if corruption occurred:
- // Don't read more regs at once or it will trigger the bug and corrupt what we're busy reading!
- uint8_t abtCmdRR[] = { ReadRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
- uint8_t nRRreg = ((sizeof(abtCmdRR) - 1) / 2);
- uint8_t abtRxRR[1 + nRRreg];
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Checking USB descriptors corruption in XRAM");
- for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) {
- for (uint8_t k = 0; k < nRRreg; k++) {
- abtCmdRR[(2 * k) + 2] = i++;
- }
- if (pn53x_transceive(pnd, abtCmdRR, sizeof(abtCmdRR), abtRxRR, sizeof(abtRxRR), -1) < 0) {
- return; // void
- }
- for (int k = 0; (k < nRRreg) && (j < szXramUsbDesc); k++) {
- //printf("0x%02x, ", abtRxRR[1 + k]);
- if (btXramUsbDesc[j] != abtRxRR[1 + k])
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "XRAM corruption @ addr 0x00%02X: got %02x, expected %02x", 0x0019 + (j - 1), abtRxRR[1 + k], btXramUsbDesc[j]);
- j++;
- }
- }
+ // Debug routine to check if corruption occurred:
+ // Don't read more regs at once or it will trigger the bug and corrupt what we're busy reading!
+ uint8_t abtCmdRR[] = { ReadRegister, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ uint8_t nRRreg = ((sizeof(abtCmdRR) - 1) / 2);
+ uint8_t abtRxRR[1 + nRRreg];
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Checking USB descriptors corruption in XRAM");
+ for (uint8_t i = 0x19, j = 0; i < 0x19 + szXramUsbDesc;) {
+ for (uint8_t k = 0; k < nRRreg; k++) {
+ abtCmdRR[(2 * k) + 2] = i++;
+ }
+ if (pn53x_transceive(pnd, abtCmdRR, sizeof(abtCmdRR), abtRxRR, sizeof(abtRxRR), -1) < 0) {
+ return; // void
+ }
+ for (int k = 0; (k < nRRreg) && (j < szXramUsbDesc); k++) {
+ //printf("0x%02x, ", abtRxRR[1 + k]);
+ if (btXramUsbDesc[j] != abtRxRR[1 + k])
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "XRAM corruption @ addr 0x00%02X: got %02x, expected %02x", 0x0019 + (j - 1), abtRxRR[1 + k], btXramUsbDesc[j]);
+ j++;
+ }
+ }
#endif
- // Abuse the overflow bug to restore USB descriptors in one go
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption");
- uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = { GetFirmwareVersion };
- for (uint8_t i = 0; i < szXramUsbDesc; i++) {
- abtCmdWR[i + 19] = btXramUsbDesc[i];
- }
- size_t szCmdWR = sizeof(abtCmdWR);
- uint8_t abtRxWR[4];
- if (pn53x_transceive(pnd, abtCmdWR, szCmdWR, abtRxWR, sizeof(abtRxWR), -1) < 0) {
- return; // void
- }
- DRIVER_DATA(pnd)->possibly_corrupted_usbdesc = false;
+ // Abuse the overflow bug to restore USB descriptors in one go
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption");
+ uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = {GetFirmwareVersion};
+ for (size_t i = 0; i < szXramUsbDesc; i++) {
+ abtCmdWR[i + 19] = btXramUsbDesc[i];
+ }
+ size_t szCmdWR = sizeof(abtCmdWR);
+ uint8_t abtRxWR[4];
+ if (pn53x_transceive(pnd, abtCmdWR, szCmdWR, abtRxWR, sizeof(abtRxWR), -1) < 0) {
+ return; // void
+ }
+ DRIVER_DATA(pnd)->possibly_corrupted_usbdesc = false;
}
static pn53x_usb_model
-pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id)
-{
- for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) {
- if ((vendor_id == pn53x_usb_supported_devices[n].vendor_id) &&
- (product_id == pn53x_usb_supported_devices[n].product_id))
- return pn53x_usb_supported_devices[n].model;
- }
-
- return UNKNOWN;
+pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id) {
+ for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) {
+ if ((vendor_id == pn53x_usb_supported_devices[n].vendor_id) &&
+ (product_id == pn53x_usb_supported_devices[n].product_id))
+ return pn53x_usb_supported_devices[n].model;
+ }
+
+ return UNKNOWN;
}
static bool
-pn53x_usb_get_end_points_default(struct usb_device *dev, struct pn53x_usb_data *data)
-{
- 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 (pn53x_usb_supported_devices[n].uiMaxPacketSize != 0) {
- data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn;
- data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut;
- data->uiMaxPacketSize = pn53x_usb_supported_devices[n].uiMaxPacketSize;
-
- return true;
- }
- }
- }
-
- return false;
+pn53x_usb_get_end_points_default(struct pn53x_usb_data *data) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(data->dev, &descriptor);
+
+ for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) {
+ if ((descriptor.idVendor == pn53x_usb_supported_devices[n].vendor_id) &&
+ (descriptor.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;
+ data->uiMaxPacketSize = pn53x_usb_supported_devices[n].uiMaxPacketSize;
+
+ return true;
+ }
+ }
+ }
+
+ return false;
}
-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)
-{
- uint32_t uiIndex;
- uint32_t uiEndPoint;
- struct usb_interface_descriptor *puid = dev->config->interface->altsetting;
-
- // 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)
- 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) {
- 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) {
- data->uiEndPointOut = uiEndPoint;
- data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
- }
- }
-}
+int pn53x_usb_ack(nfc_device *pnd);
static size_t
-pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
-{
- (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;
- }
-
- // 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
- continue;
- }
- device_found++;
- // Test if we reach the maximum "wanted" devices
- if (device_found == connstrings_len) {
- return device_found;
- }
- }
- }
- }
- }
-
- return device_found;
+pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) {
+ struct usbbus_device devices[num_pn53x_usb_supported_devices];
+ for (size_t i = 0; i < num_pn53x_usb_supported_devices; i++) {
+ devices[i].product_id = pn53x_usb_supported_devices[i].product_id;
+ devices[i].vendor_id = pn53x_usb_supported_devices[i].vendor_id;
+ devices[i].name = pn53x_usb_supported_devices[i].name;
+ devices[i].max_packet_size = pn53x_usb_supported_devices[i].uiMaxPacketSize;
+ }
+ return usbbus_usb_scan(connstrings, connstrings_len, devices, num_pn53x_usb_supported_devices, PN53X_USB_DRIVER_NAME);
}
-struct pn53x_usb_descriptor {
- char *dirname;
- char *filename;
-};
-
bool
-pn53x_usb_get_usb_device_name(struct usb_device *dev, usb_dev_handle *udev, char *buffer, size_t len)
-{
- *buffer = '\0';
-
- if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
- if (udev) {
- usb_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len);
- if (strlen(buffer) > 0)
- strcpy(buffer + strlen(buffer), " / ");
- usb_get_string_simple(udev, dev->descriptor.iProduct, 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)) {
- strncpy(buffer, pn53x_usb_supported_devices[n].name, len);
- buffer[len - 1] = '\0';
- return true;
- }
- }
- }
-
- return false;
+pn53x_usb_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
+ *buffer = '\0';
+
+ usbbus_get_usb_device_name(dev, udev, buffer, len);
+ uint16_t vendor_id = usbbus_get_vendor_id(dev);
+ uint16_t product_id = usbbus_get_product_id(dev);
+
+ if (!*buffer) {
+ for (size_t n = 0; n < num_pn53x_usb_supported_devices; n++) {
+ if ((pn53x_usb_supported_devices[n].vendor_id == vendor_id) &&
+ (pn53x_usb_supported_devices[n].product_id == product_id)) {
+ strncpy(buffer, pn53x_usb_supported_devices[n].name, len);
+ buffer[len - 1] = '\0';
+ return true;
+ }
+ }
+ }
+
+ return false;
}
static nfc_device *
-pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
-{
- nfc_device *pnd = NULL;
- struct pn53x_usb_descriptor desc = { NULL, NULL };
- int connstring_decode_level = connstring_decode(connstring, PN53X_USB_DRIVER_NAME, "usb", &desc.dirname, &desc.filename);
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%d element(s) have been decoded from \"%s\"", connstring_decode_level, connstring);
- if (connstring_decode_level < 1) {
- goto free_mem;
- }
-
- struct pn53x_usb_data data = {
- .pudh = NULL,
- .uiEndPointIn = 0,
- .uiEndPointOut = 0,
- .possibly_corrupted_usbdesc = false,
- };
- struct usb_bus *bus;
- struct usb_device *dev;
-
- usb_prepare();
-
- 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))
- 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)
- 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);
-
- // 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;
- }
-
- 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;
- }
- pn53x_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name));
-
- pnd->driver_data = malloc(sizeof(struct pn53x_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, &pn53x_usb_io) == NULL) {
- perror("malloc");
- goto error;
- }
-
- 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;
-
- // 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) {
- usb_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;
-
-error:
- // Free allocated structure on error.
- nfc_device_free(pnd);
- pnd = NULL;
-free_mem:
- free(desc.dirname);
- free(desc.filename);
- return pnd;
+pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) {
+ nfc_device *pnd = NULL;
+
+ char *dev_address_str;
+ char *config_idx_str;
+ int connstring_decode_level =
+ connstring_decode(connstring, PN53X_USB_DRIVER_NAME, "usb", &dev_address_str, &config_idx_str);
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_DEBUG,
+ "%d element(s) have been decoded from \"%s\"",
+ connstring_decode_level,
+ connstring);
+ // At least the driver and the dev address need to be decoded
+ if (connstring_decode_level < 2) {
+ return NULL;
+ }
+
+ uint8_t dev_addres = atoi(dev_address_str);
+ uint8_t config_idx = atoi(config_idx_str);
+
+ usbbus_prepare();
+
+
+ struct pn53x_usb_data data = {
+ .dev = NULL,
+ .pudh = NULL,
+ .configIdx = config_idx,
+ .uiEndPointIn = 0,
+ .uiEndPointOut = 0,
+ .possibly_corrupted_usbdesc = false,
+ };
+
+ usbbus_get_device(dev_addres, &data.dev, &data.pudh);
+
+ // Retrieve end points, using hardcoded defaults if available
+ // or using the descriptors otherwise.
+ if (!pn53x_usb_get_end_points_default(&data)) {
+ // Find transfer endpoints for bulk transfers
+ usbbus_get_usb_endpoints(data.dev, &(data.uiEndPointIn), &(data.uiEndPointOut), &(data.uiMaxPacketSize));
+
+ }
+ // Set configuration
+ int res = libusb_set_configuration(data.pudh, data.configIdx);
+ if (res < 0) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unable to set USB configuration (%s)",
+ libusb_strerror(res));
+ if (res == LIBUSB_ERROR_ACCESS) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_INFO,
+ "Warning: Please double check USB permissions for device %04x:%04x:%03d",
+ usbbus_get_vendor_id(data.dev),
+ usbbus_get_product_id(data.dev),
+ data.configIdx);
+ }
+ // we failed to use the specified device
+ usbbus_close(data.dev, data.pudh);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+
+ 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));
+ // we failed to use the specified device
+ usbbus_close(data.dev, data.pudh);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+ data.model = pn53x_usb_get_device_model(usbbus_get_vendor_id(data.dev), usbbus_get_product_id(data.dev));
+ // Allocate memory for the device info and specification, fill it and return the info
+ pnd = nfc_device_new(context, connstring);
+ if (!pnd) {
+ perror("malloc");
+ usbbus_close(data.dev, data.pudh);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+ pn53x_usb_get_usb_device_name(data.dev, data.pudh, pnd->name, sizeof(pnd->name));
+
+ pnd->driver_data = malloc(sizeof(struct pn53x_usb_data));
+ if (!pnd->driver_data) {
+ perror("malloc");
+ nfc_device_free(pnd);
+ usbbus_close(data.dev, data.pudh);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+ *DRIVER_DATA(pnd) = data;
+
+ // Alloc and init chip's data
+ if (pn53x_data_new(pnd, &pn53x_usb_io) == NULL) {
+ perror("malloc");
+ nfc_device_free(pnd);
+ usbbus_close(data.dev, data.pudh);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+
+ 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;
+
+ // 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) {
+ nfc_device_free(pnd);
+ usbbus_close(data.dev, data.pudh);
+ free(dev_address_str);
+ free(config_idx_str);
+ return NULL;
+ }
+ DRIVER_DATA(pnd)->abort_flag = false;
+ return pnd;
}
static void
-pn53x_usb_close(nfc_device *pnd)
-{
- pn53x_usb_ack(pnd);
-
- if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
- /* Set P30, P31, P32, P33, P35 to logic 1 and P34 to 0 logic */
- /* ie. Switch all LEDs off and turn off progressive field */
- pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P32) | _BV(P33) | _BV(P35));
- }
-
- if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc)
- pn533_fix_usbdesc(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 = 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));
- }
- pn53x_data_free(pnd);
- nfc_device_free(pnd);
+pn53x_usb_close(nfc_device *pnd) {
+ pn53x_usb_ack(pnd);
+
+ if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
+ /* Set P30, P31, P32, P33, P35 to logic 1 and P34 to 0 logic */
+ /* ie. Switch all LEDs off and turn off progressive field */
+ pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P32) | _BV(P33) | _BV(P35));
+ }
+
+ if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc) {
+ pn533_fix_usbdesc(pnd);
+ }
+
+ pn53x_idle(pnd);
+
+ usbbus_close(DRIVER_DATA(pnd)->dev, DRIVER_DATA(pnd)->pudh);
+
+ pn53x_data_free(pnd);
+ nfc_device_free(pnd);
}
#define PN53X_USB_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
static int
-pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout)
-{
- uint8_t abtFrame[PN53X_USB_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
- size_t szFrame = 0;
- int res = 0;
-
- if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) {
- pnd->last_error = res;
- return pnd->last_error;
- }
-
- DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= szData > 17;
- if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), abtFrame, szFrame, timeout)) < 0) {
- pnd->last_error = res;
- return pnd->last_error;
- }
-
- uint8_t abtRxBuf[PN53X_USB_BUFFER_LEN];
- if ((res = pn53x_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), timeout)) < 0) {
- // try to interrupt current device state
- pn53x_usb_ack(pnd);
- pnd->last_error = res;
- return pnd->last_error;
- }
-
- if (pn53x_check_ack_frame(pnd, abtRxBuf, res) == 0) {
- // The PN53x is running the sent command
- } else {
- // For some reasons (eg. send another command while a previous one is
- // running), the PN533 sometimes directly replies the response packet
- // instead of ACK frame, so we send a NACK frame to force PN533 to resend
- // response packet. With this hack, the next executed function (ie.
- // pn53x_usb_receive()) will be able to retrieve the correct response
- // packet.
- // FIXME Sony reader is also affected by this bug but NACK is not supported
- if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *)pn53x_nack_frame, sizeof(pn53x_nack_frame), timeout)) < 0) {
- pnd->last_error = res;
- // try to interrupt current device state
- pn53x_usb_ack(pnd);
- return pnd->last_error;
- }
- }
- return NFC_SUCCESS;
+pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout) {
+ uint8_t abtFrame[PN53X_USB_BUFFER_LEN] = {0x00, 0x00, 0xff}; // Every packet must start with "00 00 ff"
+ size_t szFrame = 0;
+ int res = 0;
+
+ if ((res = pn53x_build_frame(abtFrame, &szFrame, pbtData, szData)) < 0) {
+ pnd->last_error = res;
+ return pnd->last_error;
+ }
+
+ DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= szData > 17;
+ if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd), abtFrame, szFrame, timeout)) < 0) {
+ pnd->last_error = res;
+ return pnd->last_error;
+ }
+
+ uint8_t abtRxBuf[PN53X_USB_BUFFER_LEN];
+ if ((res = pn53x_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), timeout)) < 0) {
+ // try to interrupt current device state
+ pn53x_usb_ack(pnd);
+ pnd->last_error = res;
+ return pnd->last_error;
+ }
+
+ if (pn53x_check_ack_frame(pnd, abtRxBuf, res) == 0) {
+ // The PN53x is running the sent command
+ } else {
+ // For some reasons (eg. send another command while a previous one is
+ // running), the PN533 sometimes directly replies the response packet
+ // instead of ACK frame, so we send a NACK frame to force PN533 to resend
+ // response packet. With this hack, the next executed function (ie.
+ // pn53x_usb_receive()) will be able to retrieve the correct response
+ // packet.
+ // FIXME Sony reader is also affected by this bug but NACK is not supported
+ if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd),
+ (uint8_t *) pn53x_nack_frame,
+ sizeof(pn53x_nack_frame),
+ timeout)) < 0) {
+ pnd->last_error = res;
+ // try to interrupt current device state
+ pn53x_usb_ack(pnd);
+ return pnd->last_error;
+ }
+ }
+ return NFC_SUCCESS;
}
-#define USB_TIMEOUT_PER_PASS 200
+#define USBBUS_TIMEOUT_PER_PASS 200
+
static int
-pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout)
-{
- size_t len;
- off_t offset = 0;
-
- uint8_t abtRxBuf[PN53X_USB_BUFFER_LEN];
- int res;
-
- /*
- * If no timeout is specified but the command is blocking, force a 200ms (USB_TIMEOUT_PER_PASS)
- * timeout to allow breaking the loop if the user wants to stop it.
- */
- int usb_timeout;
- int remaining_time = timeout;
-read:
- if (timeout == USB_INFINITE_TIMEOUT) {
- usb_timeout = USB_TIMEOUT_PER_PASS;
- } else {
- // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
- remaining_time -= USB_TIMEOUT_PER_PASS;
- if (remaining_time <= 0) {
- pnd->last_error = NFC_ETIMEOUT;
- return pnd->last_error;
- } else {
- usb_timeout = MIN(remaining_time, USB_TIMEOUT_PER_PASS);
- }
- }
-
- res = pn53x_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usb_timeout);
-
- if (res == -USB_TIMEDOUT) {
- if (DRIVER_DATA(pnd)->abort_flag) {
- DRIVER_DATA(pnd)->abort_flag = false;
- pn53x_usb_ack(pnd);
- pnd->last_error = NFC_EOPABORTED;
- return pnd->last_error;
- } else {
- goto read;
- }
- }
-
- if (res < 0) {
- // try to interrupt current device state
- pn53x_usb_ack(pnd);
- pnd->last_error = res;
- return pnd->last_error;
- }
-
- const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
- if (0 != (memcmp(abtRxBuf, pn53x_preamble, 3))) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset += 3;
-
- if ((0x01 == abtRxBuf[offset]) && (0xff == abtRxBuf[offset + 1])) {
- // Error frame
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Application level error detected");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- } else if ((0xff == abtRxBuf[offset]) && (0xff == abtRxBuf[offset + 1])) {
- // Extended frame
- offset += 2;
-
- // (abtRxBuf[offset] << 8) + abtRxBuf[offset + 1] (LEN) include TFI + (CC+1)
- len = (abtRxBuf[offset] << 8) + abtRxBuf[offset + 1] - 2;
- if (((abtRxBuf[offset] + abtRxBuf[offset + 1] + abtRxBuf[offset + 2]) % 256) != 0) {
- // TODO: Retry
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset += 3;
- } else {
- // Normal frame
- if (256 != (abtRxBuf[offset] + abtRxBuf[offset + 1])) {
- // TODO: Retry
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
-
- // abtRxBuf[3] (LEN) include TFI + (CC+1)
- len = abtRxBuf[offset] - 2;
- offset += 2;
- }
-
- if (len > szDataLen) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to receive data: buffer too small. (szDataLen: %" PRIuPTR ", len: %" PRIuPTR ")", szDataLen, len);
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
-
- // TFI + PD0 (CC+1)
- if (abtRxBuf[offset] != 0xD5) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "TFI Mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset += 1;
-
- if (abtRxBuf[offset] != CHIP_DATA(pnd)->last_command + 1) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Command Code verification failed");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset += 1;
-
- memcpy(pbtData, abtRxBuf + offset, len);
- offset += len;
-
- uint8_t btDCS = (256 - 0xD5);
- btDCS -= CHIP_DATA(pnd)->last_command + 1;
- for (size_t szPos = 0; szPos < len; szPos++) {
- btDCS -= pbtData[szPos];
- }
-
- if (btDCS != abtRxBuf[offset]) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Data checksum mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset += 1;
-
- if (0x00 != abtRxBuf[offset]) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- // The PN53x command is done and we successfully received the reply
- pnd->last_error = 0;
- DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= len > 16;
- return len;
+pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout) {
+ size_t len;
+ off_t offset = 0;
+
+ uint8_t abtRxBuf[PN53X_USB_BUFFER_LEN];
+ int res;
+
+ /*
+ * If no timeout is specified but the command is blocking, force a 200ms (USBBUS_TIMEOUT_PER_PASS)
+ * timeout to allow breaking the loop if the user wants to stop it.
+ */
+ int usbbus_timeout;
+ int remaining_time = timeout;
+ read:
+ if (timeout == USBBUS_INFINITE_TIMEOUT) {
+ usbbus_timeout = USBBUS_TIMEOUT_PER_PASS;
+ } else {
+ // A user-provided timeout is set, we have to cut it in multiple chunk to be able to keep an nfc_abort_command() mechanism
+ remaining_time -= USBBUS_TIMEOUT_PER_PASS;
+ if (remaining_time <= 0) {
+ pnd->last_error = NFC_ETIMEOUT;
+ return pnd->last_error;
+ } else {
+ usbbus_timeout = MIN(remaining_time, USBBUS_TIMEOUT_PER_PASS);
+ }
+ }
+
+ res = pn53x_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usbbus_timeout);
+
+ if (res == LIBUSB_ERROR_TIMEOUT) {
+ if (DRIVER_DATA(pnd)->abort_flag) {
+ DRIVER_DATA(pnd)->abort_flag = false;
+ pn53x_usb_ack(pnd);
+ pnd->last_error = NFC_EOPABORTED;
+ return pnd->last_error;
+ } else {
+ goto read;
+ }
+ }
+
+ if (res < 0) {
+ // try to interrupt current device state
+ pn53x_usb_ack(pnd);
+ pnd->last_error = res;
+ return pnd->last_error;
+ }
+
+ const uint8_t pn53x_preamble[3] = {0x00, 0x00, 0xff};
+ if (0 != (memcmp(abtRxBuf, pn53x_preamble, 3))) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset += 3;
+
+ if ((0x01 == abtRxBuf[offset]) && (0xff == abtRxBuf[offset + 1])) {
+ // Error frame
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Application level error detected");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ } else if ((0xff == abtRxBuf[offset]) && (0xff == abtRxBuf[offset + 1])) {
+ // Extended frame
+ offset += 2;
+
+ // (abtRxBuf[offset] << 8) + abtRxBuf[offset + 1] (LEN) include TFI + (CC+1)
+ len = (abtRxBuf[offset] << 8) + abtRxBuf[offset + 1] - 2;
+ if (((abtRxBuf[offset] + abtRxBuf[offset + 1] + abtRxBuf[offset + 2]) % 256) != 0) {
+ // TODO: Retry
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset += 3;
+ } else {
+ // Normal frame
+ if (256 != (abtRxBuf[offset] + abtRxBuf[offset + 1])) {
+ // TODO: Retry
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Length checksum mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+
+ // abtRxBuf[3] (LEN) include TFI + (CC+1)
+ len = abtRxBuf[offset] - 2;
+ offset += 2;
+ }
+
+ if (len > szDataLen) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unable to receive data: buffer too small. (szDataLen: %" PRIuPTR ", len: %" PRIuPTR ")",
+ szDataLen,
+ len);
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+
+ // TFI + PD0 (CC+1)
+ if (abtRxBuf[offset] != 0xD5) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "TFI Mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset += 1;
+
+ if (abtRxBuf[offset] != CHIP_DATA(pnd)->last_command + 1) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Command Code verification failed");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset += 1;
+
+ memcpy(pbtData, abtRxBuf + offset, len);
+ offset += len;
+
+ uint8_t btDCS = (256 - 0xD5);
+ btDCS -= CHIP_DATA(pnd)->last_command + 1;
+ for (size_t szPos = 0; szPos < len; szPos++) {
+ btDCS -= pbtData[szPos];
+ }
+
+ if (btDCS != abtRxBuf[offset]) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Data checksum mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset += 1;
+
+ if (0x00 != abtRxBuf[offset]) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame postamble mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ // The PN53x command is done and we successfully received the reply
+ pnd->last_error = 0;
+ DRIVER_DATA(pnd)->possibly_corrupted_usbdesc |= len > 16;
+ return len;
}
int
-pn53x_usb_ack(nfc_device *pnd)
-{
- return pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *) pn53x_ack_frame, sizeof(pn53x_ack_frame), 1000);
+pn53x_usb_ack(nfc_device *pnd) {
+ return pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *) pn53x_ack_frame, sizeof(pn53x_ack_frame), 1000);
}
int
-pn53x_usb_init(nfc_device *pnd)
-{
- int res = 0;
- // Sometimes PN53x USB doesn't reply ACK one the first frame, so we need to send a dummy one...
- //pn53x_check_communication (pnd); // Sony RC-S360 doesn't support this command for now so let's use a get_firmware_version instead:
- const uint8_t abtCmd[] = { GetFirmwareVersion };
- pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1);
- // ...and we don't care about error
- pnd->last_error = 0;
- if (SONY_RCS360 == DRIVER_DATA(pnd)->model) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "SONY RC-S360 initialization.");
- const uint8_t abtCmd2[] = { 0x18, 0x01 };
- pn53x_transceive(pnd, abtCmd2, sizeof(abtCmd2), NULL, 0, -1);
- pn53x_usb_ack(pnd);
- }
-
- if ((res = pn53x_init(pnd)) < 0)
- return res;
-
- if (ASK_LOGO == DRIVER_DATA(pnd)->model) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ASK LoGO initialization.");
- /* Internal registers */
- /* Disable 100mA current limit, Power on Secure IC (SVDD) */
- pn53x_write_register(pnd, PN53X_REG_Control_switch_rng, 0xFF, SYMBOL_CURLIMOFF | SYMBOL_SIC_SWITCH_EN | SYMBOL_RANDOM_DATAREADY);
- /* Select the signal to be output on SIGOUT: Modulation signal (envelope) from the internal coder */
- pn53x_write_register(pnd, PN53X_REG_CIU_TxSel, 0xFF, 0x14);
-
- /* SFR Registers */
- /* Setup push-pulls for pins from P30 to P35 */
- pn53x_write_register(pnd, PN53X_SFR_P3CFGB, 0xFF, 0x37);
-
- /*
- On ASK LoGO hardware:
- LEDs port bits definition:
- * LED 1: bit 2 (P32)
- * LED 2: bit 1 (P31)
- * LED 3: bit 0 or 3 (depending of hardware revision) (P30 or P33)
- * LED 4: bit 5 (P35)
- Notes:
- * Set logical 0 to switch LED on; logical 1 to switch LED off.
- * Bit 4 should be maintained at 1 to keep RF field on.
-
- Progressive field activation:
- The ASK LoGO hardware can progressively power-up the antenna.
- To use this feature we have to switch on the field by switching on
- the field on PN533 (RFConfiguration) then set P34 to '1', and cut-off the
- field by switching off the field on PN533 then set P34 to '0'.
- */
-
- /* Set P30, P31, P33, P35 to logic 1 and P32, P34 to 0 logic */
- /* ie. Switch LED1 on and turn off progressive field */
- pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P33) | _BV(P35));
- }
- if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc)
- pn533_fix_usbdesc(pnd);
-
- return NFC_SUCCESS;
+pn53x_usb_init(nfc_device *pnd) {
+ int res = 0;
+ // Sometimes PN53x USB doesn't reply ACK one the first frame, so we need to send a dummy one...
+ //pn53x_check_communication (pnd); // Sony RC-S360 doesn't support this command for now so let's use a get_firmware_version instead:
+ const uint8_t abtCmd[] = {GetFirmwareVersion};
+ pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1);
+ // ...and we don't care about error
+ pnd->last_error = 0;
+ if (SONY_RCS360 == DRIVER_DATA(pnd)->model) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "SONY RC-S360 initialization.");
+ const uint8_t abtCmd2[] = {0x18, 0x01};
+ pn53x_transceive(pnd, abtCmd2, sizeof(abtCmd2), NULL, 0, -1);
+ pn53x_usb_ack(pnd);
+ }
+
+ if ((res = pn53x_init(pnd)) < 0)
+ return res;
+
+ if (ASK_LOGO == DRIVER_DATA(pnd)->model) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ASK LoGO initialization.");
+ /* Internal registers */
+ /* Disable 100mA current limit, Power on Secure IC (SVDD) */
+ pn53x_write_register(pnd,
+ PN53X_REG_Control_switch_rng,
+ 0xFF,
+ SYMBOL_CURLIMOFF | SYMBOL_SIC_SWITCH_EN | SYMBOL_RANDOM_DATAREADY);
+ /* Select the signal to be output on SIGOUT: Modulation signal (envelope) from the internal coder */
+ pn53x_write_register(pnd, PN53X_REG_CIU_TxSel, 0xFF, 0x14);
+
+ /* SFR Registers */
+ /* Setup push-pulls for pins from P30 to P35 */
+ pn53x_write_register(pnd, PN53X_SFR_P3CFGB, 0xFF, 0x37);
+
+ /*
+ On ASK LoGO hardware:
+ LEDs port bits definition:
+ * LED 1: bit 2 (P32)
+ * LED 2: bit 1 (P31)
+ * LED 3: bit 0 or 3 (depending of hardware revision) (P30 or P33)
+ * LED 4: bit 5 (P35)
+ Notes:
+ * Set logical 0 to switch LED on; logical 1 to switch LED off.
+ * Bit 4 should be maintained at 1 to keep RF field on.
+
+ Progressive field activation:
+ The ASK LoGO hardware can progressively power-up the antenna.
+ To use this feature we have to switch on the field by switching on
+ the field on PN533 (RFConfiguration) then set P34 to '1', and cut-off the
+ field by switching off the field on PN533 then set P34 to '0'.
+ */
+
+ /* Set P30, P31, P33, P35 to logic 1 and P32, P34 to 0 logic */
+ /* ie. Switch LED1 on and turn off progressive field */
+ pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P33) | _BV(P35));
+ }
+ if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc)
+ pn533_fix_usbdesc(pnd);
+
+ return NFC_SUCCESS;
}
static int
-pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
-{
- int res = 0;
- if ((res = pn53x_set_property_bool(pnd, property, bEnable)) < 0)
- return res;
-
- switch (DRIVER_DATA(pnd)->model) {
- case ASK_LOGO:
- if (NP_ACTIVATE_FIELD == property) {
- /* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Switch progressive field %s", bEnable ? "On" : "Off");
- if (pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31)) < 0)
- return NFC_ECHIP;
- }
- break;
- case SCM_SCL3711:
- if (NP_ACTIVATE_FIELD == property) {
- // Switch on/off LED according to ACTIVATE_FIELD option
- if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0)
- return res;
- }
- break;
- case SCM_SCL3712:
- if (NP_ACTIVATE_FIELD == property) {
- // Switch on/off LED according to ACTIVATE_FIELD option
- if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0)
- return res;
- }
- break;
- case NXP_PN531:
- case NXP_PN533:
- case SONY_PN531:
- case SONY_RCS360:
- case UNKNOWN:
- // Nothing to do.
- break;
- }
- return NFC_SUCCESS;
+pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable) {
+ int res = 0;
+ if ((res = pn53x_set_property_bool(pnd, property, bEnable)) < 0)
+ return res;
+
+ switch (DRIVER_DATA(pnd)->model) {
+ case ASK_LOGO:
+ if (NP_ACTIVATE_FIELD == property) {
+ /* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_DEBUG,
+ "Switch progressive field %s",
+ bEnable ? "On" : "Off");
+ if (pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31)) < 0)
+ return NFC_ECHIP;
+ }
+ break;
+ case SCM_SCL3711:
+ case SCM_SCL3712:
+ if (NP_ACTIVATE_FIELD == property) {
+ // Switch on/off LED according to ACTIVATE_FIELD option
+ if ((res = pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P32), bEnable ? 0 : _BV(P32))) < 0)
+ return res;
+ }
+ break;
+ case NXP_PN531:
+ case NXP_PN533:
+ case SONY_PN531:
+ case SONY_RCS360:
+ case UNKNOWN:
+ // Nothing to do.
+ break;
+ }
+ return NFC_SUCCESS;
}
static int
-pn53x_usb_abort_command(nfc_device *pnd)
-{
- DRIVER_DATA(pnd)->abort_flag = true;
- return NFC_SUCCESS;
+pn53x_usb_abort_command(nfc_device *pnd) {
+ DRIVER_DATA(pnd)->abort_flag = true;
+ return NFC_SUCCESS;
}
static int
-pn53x_usb_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
-{
- if ((DRIVER_DATA(pnd)->model != ASK_LOGO) || (mode != N_TARGET))
- return pn53x_get_supported_modulation(pnd, mode, supported_mt);
- else // ASK_LOGO has no N_TARGET support
- *supported_mt = no_target_support;
- return NFC_SUCCESS;
+pn53x_usb_get_supported_modulation(nfc_device *pnd,
+ const nfc_mode mode,
+ const nfc_modulation_type **const supported_mt) {
+ if ((DRIVER_DATA(pnd)->model != ASK_LOGO) || (mode != N_TARGET))
+ return pn53x_get_supported_modulation(pnd, mode, supported_mt);
+ else // ASK_LOGO has no N_TARGET support
+ *supported_mt = no_target_support;
+ return NFC_SUCCESS;
}
const struct pn53x_io pn53x_usb_io = {
- .send = pn53x_usb_send,
- .receive = pn53x_usb_receive,
+ .send = pn53x_usb_send,
+ .receive = pn53x_usb_receive,
};
const struct nfc_driver pn53x_usb_driver = {
- .name = PN53X_USB_DRIVER_NAME,
- .scan_type = NOT_INTRUSIVE,
- .scan = pn53x_usb_scan,
- .open = pn53x_usb_open,
- .close = pn53x_usb_close,
- .strerror = pn53x_strerror,
-
- .initiator_init = pn53x_initiator_init,
- .initiator_init_secure_element = NULL, // No secure-element support
- .initiator_select_passive_target = pn53x_initiator_select_passive_target,
- .initiator_poll_target = pn53x_initiator_poll_target,
- .initiator_select_dep_target = pn53x_initiator_select_dep_target,
- .initiator_deselect_target = pn53x_initiator_deselect_target,
- .initiator_transceive_bytes = pn53x_initiator_transceive_bytes,
- .initiator_transceive_bits = pn53x_initiator_transceive_bits,
- .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed,
- .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed,
- .initiator_target_is_present = pn53x_initiator_target_is_present,
-
- .target_init = pn53x_target_init,
- .target_send_bytes = pn53x_target_send_bytes,
- .target_receive_bytes = pn53x_target_receive_bytes,
- .target_send_bits = pn53x_target_send_bits,
- .target_receive_bits = pn53x_target_receive_bits,
-
- .device_set_property_bool = pn53x_usb_set_property_bool,
- .device_set_property_int = pn53x_set_property_int,
- .get_supported_modulation = pn53x_usb_get_supported_modulation,
- .get_supported_baud_rate = pn53x_get_supported_baud_rate,
- .device_get_information_about = pn53x_get_information_about,
-
- .abort_command = pn53x_usb_abort_command,
- .idle = pn53x_idle,
- .powerdown = pn53x_PowerDown,
+ .name = PN53X_USB_DRIVER_NAME,
+ .scan_type = NOT_INTRUSIVE,
+ .scan = pn53x_usb_scan,
+ .open = pn53x_usb_open,
+ .close = pn53x_usb_close,
+ .strerror = pn53x_strerror,
+
+ .initiator_init = pn53x_initiator_init,
+ .initiator_init_secure_element = NULL, // No secure-element support
+ .initiator_select_passive_target = pn53x_initiator_select_passive_target,
+ .initiator_poll_target = pn53x_initiator_poll_target,
+ .initiator_select_dep_target = pn53x_initiator_select_dep_target,
+ .initiator_deselect_target = pn53x_initiator_deselect_target,
+ .initiator_transceive_bytes = pn53x_initiator_transceive_bytes,
+ .initiator_transceive_bits = pn53x_initiator_transceive_bits,
+ .initiator_transceive_bytes_timed = pn53x_initiator_transceive_bytes_timed,
+ .initiator_transceive_bits_timed = pn53x_initiator_transceive_bits_timed,
+ .initiator_target_is_present = pn53x_initiator_target_is_present,
+
+ .target_init = pn53x_target_init,
+ .target_send_bytes = pn53x_target_send_bytes,
+ .target_receive_bytes = pn53x_target_receive_bytes,
+ .target_send_bits = pn53x_target_send_bits,
+ .target_receive_bits = pn53x_target_receive_bits,
+
+ .device_set_property_bool = pn53x_usb_set_property_bool,
+ .device_set_property_int = pn53x_set_property_int,
+ .get_supported_modulation = pn53x_usb_get_supported_modulation,
+ .get_supported_baud_rate = pn53x_get_supported_baud_rate,
+ .device_get_information_about = pn53x_get_information_about,
+
+ .abort_command = pn53x_usb_abort_command,
+ .idle = pn53x_idle,
+ .powerdown = pn53x_PowerDown,
};
diff --git a/m4/libnfc_check_libusb.m4 b/m4/libnfc_check_libusb.m4
index 0d5b197f..02e8365b 100644
--- a/m4/libnfc_check_libusb.m4
+++ b/m4/libnfc_check_libusb.m4
@@ -7,23 +7,10 @@ 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])
+ 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,"
@@ -33,33 +20,10 @@ AC_DEFUN([LIBNFC_CHECK_LIBUSB],
fi
fi
- # Search using libusb-legacy 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])
- 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-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])])
+ AC_CHECK_HEADER(libusb.h, [], [AC_MSG_ERROR([The libusb headers are missing])])
+ AC_CHECK_LIB(usb-1.0, libusb_init, [], [AC_MSG_ERROR([The libusb library is missing])])
libusb_LIBS="-lusb"
HAVE_LIBUSB=1