diff --git a/NEWS.md b/NEWS.md
deleted file mode 100644
index 2e38d06..0000000
--- a/NEWS.md
+++ /dev/null
@@ -1,394 +0,0 @@
-New in 1.8.0:
-
-API Changes:
- - Restore nfc_modulation_type enum order to keep compatibility with libnfc 1.7.1
- - Bump library version to 6.0.0
-
-New in 1.7.2:
-
-Drivers:
-
- * New driver for pn71xx NXP's NFC Controllers through Linux Libnfc-nci (untested)
- * New driver for contactless PC/SC readers (only as initiator)
-
-API Changes:
-
- * nfc_device_get_supported_baud_rate() now takes also "mode" as argument
- * New nfc_device_get_supported_baud_rate_target_mode()
- * New NFC modulation type NMT_BARCODE and nfc_barcode_info struct to support Thinfilm NFC Barcode protocol
- * New NFC modulation type NMT_ISO14443BICLASS and NMT_ISO14443BICLASS struct to support HID iClass (Picopass)
- * pn53x_transceive() is now part of public API
-
-New in 1.7.1:
-
-API Changes:
-
- * nfc_initiator_select_passive_target() provides defaults if pbtInitData=NULL
- * nfc_initiator_target_is_present() allow NULL pointer to tag
-
-New in 1.7.0:
-
-Drivers:
-
- * New PN532 over I2C driver, see contrib/libnfc/pn532_i2c_on_rpi.conf.sample
-
-API Changes:
-
- * New function iso14443b_crc_append()
-
-New in 1.7.0-rc7:
-
-Drivers:
-
- * New PN532 over SPI driver, see contrib/libnfc/pn532_spi_on_rpi.conf.sample
-
-API Changes:
-
- * Functions
- - nfc_initiator_target_is_present() & str_nfc_target():
- now take a pointer to nfc_target as argument
- - nfc_init(): upon malloc error, doesn't force exit() anymore
- so now you should test if context != NULL after nfc_init() call
-
-New in 1.7.0-rc5:
-
-API Changes:
-
- * Functions
- - New nfc_register_driver() function allowing to hook custom drivers.
-
-New in 1.7.0-rc3:
-
-API Changes:
-
- * Functions
- - Add timeout param to nfc_emulate_target()
-
-New in 1.7.0-rc2:
-
-Configuration:
- libnfc can now use a configuration file for special setups, or features
- activation. This file (/etc/nfc/libnfc.conf under GNU/Linux systems)
- supports already some keywords:
- - "allow_autoscan" to enable/disable device auto-detection feature;
- - "allow_intrusive_scan" to enable/disable intrusive auto-detection
- (ie. serial port probing);
- - "log_level" to select library verbosity;
- - "device.name" and "device.connstring" to define a user device,
- this is the recommended method if user has a not easily detectable
- device (ie. a serial one).
- It is also possible to define devices using dedicated configuration files and
- put them into device search directory (/etc/nfc/devices.d under GNU/Linux).
- Example for the OpenPCD2: create /etc/nfc/devices.d/openpcd2.conf with:
- name = "OpenPCD2"
- connstring = "pn532_uart:/dev/ttyACM0"
- optional = true
- The keyword "optional" does not mandate the device to be present always
- (it detects if the reader is indeed present before using it)
-
-API Changes:
-
- * Types
- - New NFC_ESOFT error to handle software errors (allocations, pipe
- creation, etc.)
-
- * Functions
- - Remove nfc_get_default_device() function: the default device is now the
- first in nfc_list_devices() or could be open using NULL connstring with
- nfc_open() function.
- - New enum-to-string converter functions str_nfc_modulation_type() and
- str_nfc_baud_rate()
- - New str_nfc_target() to convert nfc_target struct into allocated string
- - New nfc_device_get_information_about() function to retreive some device's
- information
- - No more in/out function parameter: nfc_initiator_transceive_*() now
- take a constant size for Rx buffer
- - New nfc_initiator_target_is_present() to test is the previously selected
- target is available in the field
- - nfc_initiator_transceive_bytes() returns NFC_EMFCAUTHFAIL when AUTH
- command failed on a Mifare Classic
- - New nfc_initiator_init_secure_element() to initiate a connection with
- secure element (Only supported with a PN532 with SAM equipped)
-
-New in 1.6.0-rc1:
-
-API Changes:
-
- * Types
- - '_t' suffix removed from all types (e.g. nfc_device_t is now nfc_device)
- - All errors removed in flavour of NFC_EIO, NFC_EINVARG, NFC_EDEVNOTSUPP,
- NFC_ENOTSUCHDEV, NFC_EOVFLOW, NFC_ETIMEOUT, NFC_EOPABORTED, NFC_ENOTIMPL,
- NFC_ETGRELEASED, NFC_ERFTRANS, NFC_ECHIP and NFC_SUCCESS
- - nfc_device_desc_t replaced by nfc_connstring: libnfc now uses connection
- strings to describe a device
- - byte_t typedef removed, libnfc now uses uint8_t from C99
- - nfc_device is now an opaque type
- - nfc_properties replaces nfc_options
-
- * Functions
- - New nfc_get_default_device() function that allows to grab the connstring
- stored in LIBNFC_DEFAULT_DEVICE environnement variable or returns the
- first available device if not set
- - New nfc_device_get_connstring() accessor function to know the device
- connstring
- - New nfc_device_set_property_bool() function that replace nfc_configure()
- - New nfc_device_set_property_int() function to set integer property
- - nfc_device_name() renamed to nfc_device_get_name() for the sake of
- consistency
- - New nfc_device_get_last_error() function, an accessor to last error occured
- - Whole libnfc's functions now return 0 (NFC_SUCCESS) or positive value if
- appropriated on success and libnfc's error code on failure
- - nfc_connect(), nfc_disconnect() renamed to nfc_open(), nfc_close()
- respectively
- - Add 2 new functions: initialization and deinitialization functions:
- nfc_init() and nfc_exit()
- - New nfc_device_get_supported_modulation() and
- nfc_device_get_supported_baud_rate() functions
-
- * Dependencies
- - log4c is not anymore used for debugging facility. It was a bad choice,
- sorry for inconvenience.
-
-New in 1.5.1:
-
-API Changes
-
- * Types
- - Communication-level errors DEIO and DETIMEOUT are now know as ECOMIO,
- ECOMTIMEOUT respectively
- - Common device-level errors DEINVAL and DEABORT are now know as EINVALARG,
- EOPABORT respectively
- - New errors: EFRAACKMISMATCH, EFRAISERRFRAME, EDEVNOTSUP and ENOTIMPL
-
- * Functions
- - nfc_abort_command() returns a boolean
- - timeout (struct timeval) pointer added to
- nfc_initiator_transceive_bytes(), nfc_target_send_bytes() and
- nfc_target_receive_bytes()
- - timed functions nfc_initiator_transceive_bytes_timed() and
- nfc_initiator_transceive_bits_timed() now takes uint32_t as cycles
- pointer
- - nfc_initiator_poll_targets() renamed to nfc_initiator_poll_target() and
- only return one target
-
-New in 1.5.0:
-
-Installed files
- - nfc-message.h have been removed, internal macros are not part of API.
- - New nfc-emulation.h file offers a middle level API to handle emulation (see
- nfc-emulate-forum-tag4 example)
-
-API Changes
-
- * Types
- - New error: DEABORT raised when operation is aborted by user (using
- nfc_abort_command())
- - nfc_chip_t type removed from public API (have been renamed to pn53x_type
- in chips/pn53x)
- - nfc_device_spec_t removed, each driver can use his own way to keep a
- connection pointer
-
- * Structures
- - nfc_device_t now have a nfc_driver_t struct pointer (named .driver) and
- void pointer (.driver_data) to handle device specific wrapping
- - nfc_device_t now have a void pointer (.chip_data) to keep some chip
- specific data
- - nfc_device_t now have an file descriptor array to manage to abort request
- - nfc_device_t does have .nc member (nfc_chip_t) anymore (different chips
- handling in now in chip level)
- - nfc_device_t does have .nds member (nfc_device_spec_t) anymore, each
- driver handle its communication using driver_data pointer
- - nfc_device_t does have .bActive member (bool) anymore, this variable was
- almost not used and was not efficient
- - nfc_device_t does have chip's register caches anymore, this is handle in
- chip level (using chip_data pointer)
- - driver_callbacks structure have been removed from public API
- - New nfc_emulator structure used by the new emulation API (see
- nfc_emulate_target())
- - New nfc_emulation_state_machine structure used by the new emulation API,
- it handles an I/O function and data pointer to create a software based
- state-machine.
-
- * Functions
- - New nfc_abort_command() function to abort current running command.
- - New nfc_initiator_transceive_bits_timed() and
- nfc_initiator_transceive_bytes_timed() to transceive bits/bytes and
- measure the time to have a reply
- - New nfc_emulate_target() function to start a target emulation using an
- nfc_emulator structure (it contains a custom state-machine
- (nfc_emulation_state_machine struct) and a custom target (nfc_target_t)
- (see nfc-emulate-forum-tag4 to have a look on how-to use it)
-
-
-
-New in 1.4.1:
-
-API Changes
-
- * Types
- - New error: ETGUIDNOTSUP raised when UID is not 4 bytes long or does not
- start with 0x08 (Security restriction present in the NXP PN53x chips)
-
-
-
-New in 1.4.0:
-
-API Changes
-
- * Types
- - New nfc_device_option value (enum): NDO_FORCE_ISO14443_A to force the
- chip to switch in ISO14443-A
- - New nfc_dep_mode_t (enum) for DEP mode:
- NDM_UNDEFINED, NDM_PASSIVE, NDM_ACTIVE
- - New nfc_modulation_type_t (enum) that lists modulation types:
- NMT_ISO14443A, NMT_ISO14443B, NMT_FELICA, NMT_JEWEL, NMT_DEP
- - New nfc_baud_rate_t (enum): list of baud rates:
- NBR_UNDEFINED, NBR_106, NBR_212, NBR_424, NBR_847
- - nfc_target_type_t have been removed from API (use nfc_modulation_t
- instead)
-
- * Structures
- - nfc_device_t now have a boolean bAutoIso14443_4 to keep the locally the
- state of NDO_AUTO_ISO14443_4 (should not be directly set, use
- nfc_configure() with NDO_AUTO_ISO14443_4)
- - nfc_device_t now have an uint8_t ui8Parameters to cache PN53x parameters
- - nfc_device_t now have a byte_t btSupportByte to cache supported
- modulations
- - nfc_dep_info_t have completely changed, please see API documentation
- - nfc_iso14443b_info_t have completely changed, please see API
- documentation
- - nfc_modulation_t have completely changed: it now contains a
- nfc_modulation_type_t and nfc_baud_rate_t couple. Initialization example:
- nfc_modulation_t nm = {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106,
- };
- - nfc_target_t now contains new nfc_modulation_t instead of
- nfc_target_type_t. Initialization example:
- nfc_target_t nt = {
- .nm.nmt = NMT_ISO14443A,
- .nm.nbr = NBR_UNDEFINED,
- .nti.nai.abtAtqa = { 0x03, 0x44 },
- .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
- .nti.nai.btSak = 0x20,
- .nti.nai.szUidLen = 4,
- .nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
- .nti.nai.szAtsLen = 5,
- };
-
- * Functions
- - nfc_initiator_select_passive_target() now use new nfc_modulation_t and
- nfc_target_t instead of nfc_target_info_t
- - nfc_initiator_list_passive_targets() now use new nfc_modulation_t and
- nfc_target_t instead of nfc_target_info_t
- - nfc_initiator_poll_targets() use new nfc_modulation_t instead of
- nfc_target_type_t
- - nfc_initiator_select_dep_target() completely changed, use now
- nfc_dep_mode_t, nfc_baudrate_t, nfc_dep_info_t and nfc_target_t, please
- see API documentation
- - nfc_target_init() have an additional argument: nfc_target_t to describe
- the wanted target
- - append_iso14443a_crc() was renamed to iso14443a_crc_append()
- - New iso14443a_locate_historical_bytes() to locate historical bytes in ATS
-
-
-
-New in 1.3.9 (since 1.3.4):
-
-Installed files
-
- - mifaretag.h and mifareultag.h are removed, Mifare features are not a part
- of libnfc API anymore (these features are always available in examples/)
-
-API Changes
-
- * Types
- - New nfc_device_option_t value (enum): NDO_AUTO_14443_4, an option to
- enable/disable auto-switching to ISO/IEC 14443-4 if device is compliliant
- - New nfc_device_option_t value (enum): NDO_EASY_FRAMING, an option to
- enable/disable automatic frames encapsulation and chaining
- - New nfc_target_type_t (enum), with values like NTT_MIFARE,
- NTT_ISO14443B_106, NTT_DEP_ACTIVE_424, etc.
- - Mifare related types have been removed from API: mifare_cmd,
- mifare_param_auth, mifare_param_data, mifare_param_value, mifare_param
-
- * Structures
- - nfc_device_t now have boolean bEasyFraming to enable/disable "easy
- framing" feature (should not be directly set, use nfc_configure() with
- NDO_EASY_FRAMING)
- - nfc_device_t now have integer iLastError to handle last error
- - New chip_callbacks to handle error lookup per chip
- - driver_callbacks now have a pointer to chip_callbacks
- - New nfc_target_t that contains nfc_target_info_t and nfc_target_type_t
-
- * Functions
- - nfc_initiator_select_tag() became nfc_initiator_select_passive_target()
- - New nfc_initiator_list_passive_targets() returns a list of detected
- target on desired modulation
- - (experimental) New nfc_initiator_poll_targets() returns targets that are
- detected during hardware polling (available only with PN532)
- - nfc_initiator_transceive_dep_bytes(), nfc_target_receive_dep_bytes() and
- nfc_target_send_dep_bytes() have been removed from API, use
- NDO_EASY_FRAMING option to switch from raw mode to "easy framing"
- - nfc_initiator_mifare_cmd() have been removed: no more Mifare related
- stuff in libnfc's API
- - New nfc_strerror(), nfc_strerror_r() and nfc_perror() to report errors
- - New append_iso14443a_crc() to append iso14443a_crc() to a string
-
-
-New in 1.3.4 (since 1.2.1):
-
-Installed files
-
- - Headers are now installed in include/nfc instead of include/libnfc
- - libnfc.h have been renamed to nfc.h
- - defines.h and types.h have been merge into nfc-types.h
- - bitutils.h is not installed anymore, some functions are now in
- examples/nfc-utils.c
- - devices.h, dev_acr122.h, dev_arygon.h, dev_pn531.h, dev_pn533.h and rs232.h
- are not installed anymore
- - New header mifareultag.h, like mifaretag.h for Mifare UltraLight
- - New header nfc-messages.h with messages macros (DBG, ERR, INFO)
-
-API Changes
-
- * Types
- - uint32_t which was used as size now are size_t
- - chip_type became nfc_chip_t (enum)
- - init_modulation became nfc_modulation_t (enum), and now have
- NM_ACTIVE_DEP and NM_PASSIVE_DEP modulation values added
-
- * Structures
- - dev_info became nfc_device_t
- - dev_config_option became nfc_device_option_t
- - New nfc_device_desc_t to describe the way to access to a NFC device.
- Initialisation example:
- nfc_device_desc_t ndd = {
- ndd.pcDriver = "ARYGON";
- ndd.pcPort = "/dev/ttyUSB0";
- ndd.uiSpeed = 115200;
- };
- - dev_callbacks became driver_callbacks and now have two function pointers
- more: pick_device() and list_devices()
- - New nfc_dep_info_t to handle DEP targets info
- - tag_info_iso14443a became nfc_iso14443a_info_t
- - tag_info_iso14443b became nfc_iso14443b_info_t
- - tag_info_felica became nfc_felica_info_t
- - tag_info_jewel became nfc_jewel_info_t
- - tag_info became nfc_target_info_t, and now have extended union to
- nfc_dep_info_t
-
- * Functions
- - nfc_connect() now takes 1 nfc_devive_desc_t argument (can be NULL)
- - New nfc_list_devices(), it find available NFC devices using all know
- drivers
- - (experimental) New nfc_initiator_select_dep(), it looks for DEP targets
- - (experimental) New nfc_initiator_transceive_dep_bytes(), like
- nfc_initiator_transceive_bytes() for DEP targets
- - (experimental) New nfc_target_receive_dep_bytes() and
- nfc_target_send_dep_bytes(), to receive/send bytes to DEP target
- (configured as initiator) while local NFC device is configured as target
- - New nfc_device_name() returns the device's name
- - New iso14443a_crc() computes CRC as described in ISO/IEC 14443
- - New nfc_version() returns the actual version of libnfc (with SVN
- revision, if available)
diff --git a/libnfc/buses/usbbus.c b/libnfc/buses/usbbus.c
index e894340..120090a 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,634 +25,300 @@
* along with this program. If not, see
*
*/
-
-/**
- * @file usbbus.c
- * @brief libusb 0.1 driver wrapper
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif // HAVE_CONFIG_H
-
+#include
+#include
#include
-#include
-#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
-/*
- * This file embeds partially libusb-compat-0.1 by:
- * Copyright (C) 2008 Daniel Drake
- * Copyright (c) 2000-2003 Johannes Erdfelt
- * This layer will be removed ASAP before integration in the main trunk
- */
-
-
-#define LIST_ADD(begin, ent) \
- do { \
- if (begin) { \
- ent->next = begin; \
- ent->next->prev = ent; \
- } else \
- ent->next = NULL; \
- ent->prev = NULL; \
- begin = ent; \
- } while(0)
-
-#define LIST_DEL(begin, ent) \
- do { \
- if (ent->prev) \
- ent->prev->next = ent->next; \
- else \
- begin = ent->next; \
- if (ent->next) \
- ent->next->prev = ent->prev; \
- ent->prev = NULL; \
- ent->next = NULL; \
- } while (0)
-
-#define USBBUS_DT_CONFIG_SIZE 9
-#define USBBUS_DT_INTERFACE_SIZE 9
-#define USBBUS_DT_ENDPOINT_AUDIO_SIZE 9
-
static libusb_context *ctx = NULL;
-struct usbbus_bus *usb_busses = NULL;
+uint8_t get_usb_num_configs(struct libusb_device *dev);
-static void _usb_finalize(void)
-{
- if (ctx) {
- libusb_exit(ctx);
- ctx = NULL;
- }
-}
-
-static void usb_init(void)
-{
- if (!ctx) {
- int r;
- r = libusb_init(&ctx);
- if (r < 0) {
- return;
- }
-
- atexit(_usb_finalize);
- }
-}
-
-static int find_busses(struct usbbus_bus **ret)
-{
- libusb_device **dev_list = NULL;
- struct usbbus_bus *busses = NULL;
- struct usbbus_bus *bus;
- int dev_list_len = 0;
- int i;
- int r;
-
- r = libusb_get_device_list(ctx, &dev_list);
- if (r < 0) {
- return r;
- }
-
- if (r == 0) {
- libusb_free_device_list(dev_list, 1);
- /* no buses */
- return 0;
- }
-
- /* iterate over the device list, identifying the individual busses.
- * we use the location field of the usbbus_bus structure to store the
- * bus number. */
-
- dev_list_len = r;
- for (i = 0; i < dev_list_len; i++) {
- libusb_device *dev = dev_list[i];
- uint8_t bus_num = libusb_get_bus_number(dev);
-
- /* if we already know about it, continue */
- if (busses) {
- bus = busses;
- int found = 0;
- do {
- if (bus_num == bus->location) {
- found = 1;
- break;
- }
- } while ((bus = bus->next) != NULL);
- if (found)
- continue;
- }
-
- /* add it to the list of busses */
- bus = malloc(sizeof(*bus));
- if (!bus)
- goto err;
-
- memset(bus, 0, sizeof(*bus));
- bus->location = bus_num;
- snprintf(bus->dirname, USBBUS_PATH_MAX, "%03d", bus_num);
- LIST_ADD(busses, bus);
- }
-
- libusb_free_device_list(dev_list, 1);
- *ret = busses;
- return 0;
-
-err:
- bus = busses;
- while (bus) {
- struct usbbus_bus *tbus = bus->next;
- free(bus);
- bus = tbus;
- }
- return LIBUSB_ERROR_NO_MEM;
-}
-
-static int usb_find_busses(void)
-{
- struct usbbus_bus *new_busses = NULL;
- struct usbbus_bus *bus;
- int changes = 0;
- int r;
-
- /* libusb-1.0 initialization might have failed, but we can't indicate
- * this with libusb-0.1, so trap that situation here */
- if (!ctx)
- return 0;
-
- r = find_busses(&new_busses);
- if (r < 0) {
- return r;
- }
-
- /* walk through all busses we already know about, removing duplicates
- * from the new list. if we do not find it in the new list, the bus
- * has been removed. */
-
- bus = usb_busses;
- while (bus) {
- struct usbbus_bus *tbus = bus->next;
- struct usbbus_bus *nbus = new_busses;
- int found = 0;
-
- while (nbus) {
- struct usbbus_bus *tnbus = nbus->next;
-
- if (bus->location == nbus->location) {
- LIST_DEL(new_busses, nbus);
- free(nbus);
- found = 1;
- break;
- }
- nbus = tnbus;
- }
-
- if (!found) {
- /* bus removed */
- changes++;
- LIST_DEL(usb_busses, bus);
- free(bus);
- }
-
- bus = tbus;
- }
-
- /* anything remaining in new_busses is a new bus */
- bus = new_busses;
- while (bus) {
- struct usbbus_bus *tbus = bus->next;
- LIST_DEL(new_busses, bus);
- LIST_ADD(usb_busses, bus);
- changes++;
- bus = tbus;
- }
-
- return changes;
-}
-
-static int find_devices(libusb_device **dev_list, int dev_list_len,
- struct usbbus_bus *bus, struct usbbus_device **ret)
-{
- struct usbbus_device *devices = NULL;
- struct usbbus_device *dev;
- int i;
-
- for (i = 0; i < dev_list_len; i++) {
- libusb_device *newlib_dev = dev_list[i];
- uint8_t bus_num = libusb_get_bus_number(newlib_dev);
-
- if (bus_num != bus->location)
- continue;
-
- dev = malloc(sizeof(*dev));
- if (!dev)
- goto err;
-
- /* No need to reference the device now, just take the pointer. We
- * increase the reference count later if we keep the device. */
- dev->dev = newlib_dev;
-
- dev->bus = bus;
- dev->devnum = libusb_get_device_address(newlib_dev);
- snprintf(dev->filename, USBBUS_PATH_MAX, "%03d", dev->devnum);
- LIST_ADD(devices, dev);
- }
-
- *ret = devices;
- return 0;
-
-err:
- dev = devices;
- while (dev) {
- struct usbbus_device *tdev = dev->next;
- free(dev);
- dev = tdev;
- }
- return LIBUSB_ERROR_NO_MEM;
-}
-
-static void clear_endpoint_descriptor(struct usbbus_endpoint_descriptor *ep)
-{
- if (ep->extra)
- free(ep->extra);
-}
-
-static void clear_interface_descriptor(struct usbbus_interface_descriptor *iface)
-{
- if (iface->extra)
- free(iface->extra);
- if (iface->endpoint) {
- int i;
- for (i = 0; i < iface->bNumEndpoints; i++)
- clear_endpoint_descriptor(iface->endpoint + i);
- free(iface->endpoint);
- }
-}
-
-static void clear_interface(struct usbbus_interface *iface)
-{
- if (iface->altsetting) {
- int i;
- for (i = 0; i < iface->num_altsetting; i++)
- clear_interface_descriptor(iface->altsetting + i);
- free(iface->altsetting);
- }
-}
-
-static void clear_config_descriptor(struct usbbus_config_descriptor *config)
-{
- if (config->extra)
- free(config->extra);
- if (config->interface) {
- int i;
- for (i = 0; i < config->bNumInterfaces; i++)
- clear_interface(config->interface + i);
- free(config->interface);
- }
-}
-
-static void clear_device(struct usbbus_device *dev)
-{
- int i;
- for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
- clear_config_descriptor(dev->config + i);
-}
-
-static int copy_endpoint_descriptor(struct usbbus_endpoint_descriptor *dest,
- const struct libusb_endpoint_descriptor *src)
-{
- memcpy(dest, src, USBBUS_DT_ENDPOINT_AUDIO_SIZE);
-
- dest->extralen = src->extra_length;
- if (src->extra_length) {
- dest->extra = malloc(src->extra_length);
- if (!dest->extra)
- return LIBUSB_ERROR_NO_MEM;
- memcpy(dest->extra, src->extra, src->extra_length);
- }
-
- return 0;
-}
-
-static int copy_interface_descriptor(struct usbbus_interface_descriptor *dest,
- const struct libusb_interface_descriptor *src)
-{
- int i;
- int num_endpoints = src->bNumEndpoints;
- size_t alloc_size = sizeof(struct usbbus_endpoint_descriptor) * num_endpoints;
-
- memcpy(dest, src, USBBUS_DT_INTERFACE_SIZE);
- dest->endpoint = malloc(alloc_size);
- if (!dest->endpoint)
- return LIBUSB_ERROR_NO_MEM;
- memset(dest->endpoint, 0, alloc_size);
-
- for (i = 0; i < num_endpoints; i++) {
- int r = copy_endpoint_descriptor(dest->endpoint + i, &src->endpoint[i]);
- if (r < 0) {
- clear_interface_descriptor(dest);
- return r;
- }
- }
-
- dest->extralen = src->extra_length;
- if (src->extra_length) {
- dest->extra = malloc(src->extra_length);
- if (!dest->extra) {
- clear_interface_descriptor(dest);
- return LIBUSB_ERROR_NO_MEM;
- }
- memcpy(dest->extra, src->extra, src->extra_length);
- }
-
- return 0;
-}
-
-static int copy_interface(struct usbbus_interface *dest,
- const struct libusb_interface *src)
-{
- int i;
- int num_altsetting = src->num_altsetting;
- size_t alloc_size = sizeof(struct usbbus_interface_descriptor)
- * num_altsetting;
-
- dest->num_altsetting = num_altsetting;
- dest->altsetting = malloc(alloc_size);
- if (!dest->altsetting)
- return LIBUSB_ERROR_NO_MEM;
- memset(dest->altsetting, 0, alloc_size);
-
- for (i = 0; i < num_altsetting; i++) {
- int r = copy_interface_descriptor(dest->altsetting + i,
- &src->altsetting[i]);
- if (r < 0) {
- clear_interface(dest);
- return r;
- }
- }
-
- return 0;
-}
-
-static int copy_config_descriptor(struct usbbus_config_descriptor *dest,
- const struct libusb_config_descriptor *src)
-{
- int i;
- int num_interfaces = src->bNumInterfaces;
- size_t alloc_size = sizeof(struct usbbus_interface) * num_interfaces;
-
- memcpy(dest, src, USBBUS_DT_CONFIG_SIZE);
- dest->interface = malloc(alloc_size);
- if (!dest->interface)
- return LIBUSB_ERROR_NO_MEM;
- memset(dest->interface, 0, alloc_size);
-
- for (i = 0; i < num_interfaces; i++) {
- int r = copy_interface(dest->interface + i, &src->interface[i]);
- if (r < 0) {
- clear_config_descriptor(dest);
- return r;
- }
- }
-
- dest->extralen = src->extra_length;
- if (src->extra_length) {
- dest->extra = malloc(src->extra_length);
- if (!dest->extra) {
- clear_config_descriptor(dest);
- return LIBUSB_ERROR_NO_MEM;
- }
- memcpy(dest->extra, src->extra, src->extra_length);
- }
-
- return 0;
-}
-
-static int initialize_device(struct usbbus_device *dev)
-{
- libusb_device *newlib_dev = dev->dev;
- int num_configurations;
- size_t alloc_size;
- int r;
- int i;
-
- /* device descriptor is identical in both libs */
- r = libusb_get_device_descriptor(newlib_dev,
- (struct libusb_device_descriptor *) &dev->descriptor);
- if (r < 0) {
- return r;
- }
-
- num_configurations = dev->descriptor.bNumConfigurations;
- alloc_size = sizeof(struct usbbus_config_descriptor) * num_configurations;
- dev->config = malloc(alloc_size);
- if (!dev->config)
- return LIBUSB_ERROR_NO_MEM;
- memset(dev->config, 0, alloc_size);
-
- for (i = 0; i < num_configurations; i++) {
- struct libusb_config_descriptor *newlib_config;
- r = libusb_get_config_descriptor(newlib_dev, i, &newlib_config);
- if (r < 0) {
- clear_device(dev);
- free(dev->config);
- return r;
- }
- r = copy_config_descriptor(dev->config + i, newlib_config);
- libusb_free_config_descriptor(newlib_config);
- if (r < 0) {
- clear_device(dev);
- free(dev->config);
- return r;
- }
- }
- dev->num_children = 0;
- dev->children = NULL;
-
- libusb_ref_device(newlib_dev);
- return 0;
-}
-
-static void free_device(struct usbbus_device *dev)
-{
- clear_device(dev);
- libusb_unref_device(dev->dev);
- free(dev);
-}
-
-static int usb_find_devices(void)
-{
- struct usbbus_bus *bus;
- libusb_device **dev_list;
- int dev_list_len;
- int changes = 0;
-
- /* libusb-1.0 initialization might have failed, but we can't indicate
- * this with libusb-0.1, so trap that situation here */
- if (!ctx)
- return 0;
-
- dev_list_len = libusb_get_device_list(ctx, &dev_list);
- if (dev_list_len < 0)
- return dev_list_len;
-
- for (bus = usb_busses; bus; bus = bus->next) {
- int r;
- struct usbbus_device *new_devices = NULL;
- struct usbbus_device *dev;
-
- r = find_devices(dev_list, dev_list_len, bus, &new_devices);
- if (r < 0) {
- libusb_free_device_list(dev_list, 1);
- return r;
- }
-
- /* walk through the devices we already know about, removing duplicates
- * from the new list. if we do not find it in the new list, the device
- * has been removed. */
- dev = bus->devices;
- while (dev) {
- int found = 0;
- struct usbbus_device *tdev = dev->next;
- struct usbbus_device *ndev = new_devices;
-
- while (ndev) {
- if (ndev->devnum == dev->devnum) {
- LIST_DEL(new_devices, ndev);
- free(ndev);
- found = 1;
- break;
- }
- ndev = ndev->next;
- }
-
- if (!found) {
- LIST_DEL(bus->devices, dev);
- free_device(dev);
- changes++;
- }
-
- dev = tdev;
- }
-
- /* anything left in new_devices is a new device */
- dev = new_devices;
- while (dev) {
- struct usbbus_device *tdev = dev->next;
- r = initialize_device(dev);
- if (r < 0) {
- dev = tdev;
- continue;
- }
- LIST_DEL(new_devices, dev);
- LIST_ADD(bus->devices, dev);
- changes++;
- dev = tdev;
- }
- }
-
- libusb_free_device_list(dev_list, 1);
- return changes;
-}
-
-int usbbus_prepare(void)
-{
- static bool usb_initialized = false;
- if (!usb_initialized) {
+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)) {
- setenv("USB_DEBUG", "255", 1);
- }
+ 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)) {
+ setenv("USB_DEBUG", "255", 1);
+ }
#endif
- usb_init();
- usb_initialized = true;
- }
+ 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)", usbbus_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)", usbbus_strerror(res));
- return -1;
- }
- return 0;
+ // 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).
+ 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;
}
-usbbus_device_handle *usbbus_open(struct usbbus_device *dev)
-{
- int r;
- usbbus_device_handle *udev;
- r = libusb_open((libusb_device *) dev->dev, (libusb_device_handle **)&udev);
- if (r < 0) {
- return NULL;
- }
- return (usbbus_device_handle *)udev;
+
+TODO kenspeckle
+beim ende vom programm libusb dinge wieder freigeben
+
+size_t usbbus_usb_scan(char **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) {
+ continue;
+ }
+ }
+
+ libusb_device_handle *udev;
+ int res = libusb_open(dev, &udev);
+ if (res < 0 && udev == NULL) {
+ 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);
+ // 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);
+ size_t size_new_str = snprintf(
+ connstrings[device_found],
+ sizeof(nfc_connstring),
+ "%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
+ continue;
+ }
+ device_found++;
+ // Test if we reach the maximum "wanted" devices
+ if (device_found == connstrings_len) {
+ return device_found;
+ }
+ }
+ }
+ }
+
+ return device_found;
}
-void usbbus_close(usbbus_device_handle *dev)
-{
- libusb_close((libusb_device_handle *)dev);
+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);
+ }
}
-int usbbus_set_configuration(usbbus_device_handle *dev, int configuration)
-{
- return libusb_set_configuration((libusb_device_handle *)dev, configuration);
+uint8_t get_usb_num_configs(struct libusb_device *dev) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(dev, &descriptor);
+ return descriptor.bNumConfigurations;
}
-int usbbus_get_string_simple(usbbus_device_handle *dev, int index, char *buf, size_t buflen)
-{
- return libusb_get_string_descriptor_ascii((libusb_device_handle *)dev, index & 0xff,
- (unsigned char *) buf, (int) buflen);
+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));
+ }
+ }
}
-int usbbus_bulk_transfer(usbbus_device_handle *dev, int ep, char *bytes, int size, int *actual_length, int timeout)
-{
- return libusb_bulk_transfer((libusb_device_handle *)dev, ep & 0xff, (unsigned char *)bytes, size, actual_length, timeout);
+
+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);
+
}
-int usbbus_claim_interface(usbbus_device_handle *dev, int interface)
-{
- return libusb_claim_interface((libusb_device_handle *)dev, interface);
+
+uint16_t usbbus_get_vendor_id(struct libusb_device *dev) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(dev, &descriptor);
+ return descriptor.idVendor;
}
-int usbbus_release_interface(usbbus_device_handle *dev, int interface)
-{
- return libusb_release_interface((libusb_device_handle *)dev, interface);
+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_set_interface_alt_setting(usbbus_device_handle *dev, int interface, int alternate)
-{
- return libusb_set_interface_alt_setting((libusb_device_handle *)dev, interface, alternate);
+
+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;
}
-int usbbus_reset(usbbus_device_handle *dev)
-{
- return libusb_reset_device((libusb_device_handle *)dev);
-}
-const char *usbbus_strerror(int errcode)
-{
- return libusb_strerror((enum libusb_error)errcode);
-}
-
-struct usbbus_bus *usbbus_get_busses(void)
-{
- return usb_busses;
-}
diff --git a/libnfc/buses/usbbus.h b/libnfc/buses/usbbus.h
index abf71fc..8da762d 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,150 +26,29 @@
*
*/
-/**
- * @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__
+#include
-#include
-#include
-
-#define USBBUS_ERROR_ACCESS -3
-#define USBBUS_ERROR_TIMEOUT -7
-
-int usbbus_prepare(void);
-
-// Libusb-0.1 API:
-#define USBBUS_ENDPOINT_DIR_MASK 0x80
-#define USBBUS_ENDPOINT_TYPE_BULK 2
-#define USBBUS_ENDPOINT_IN 0x80
-#define USBBUS_ENDPOINT_OUT 0x00
-
-#ifdef PATH_MAX
-#define USBBUS_PATH_MAX PATH_MAX
-#else
-#define USBBUS_PATH_MAX 4096
-#endif
-
-struct usbbus_device_handle;
-typedef struct usbbus_device_handle usbbus_device_handle;
-
-struct usbbus_endpoint_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bEndpointAddress;
- uint8_t bmAttributes;
- uint16_t wMaxPacketSize;
- uint8_t bInterval;
- uint8_t bRefresh;
- uint8_t bSynchAddress;
-
- unsigned char *extra;
- int extralen;
-};
-
-struct usbbus_interface_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint8_t bInterfaceNumber;
- uint8_t bAlternateSetting;
- uint8_t bNumEndpoints;
- uint8_t bInterfaceClass;
- uint8_t bInterfaceSubClass;
- uint8_t bInterfaceProtocol;
- uint8_t iInterface;
-
- struct usbbus_endpoint_descriptor *endpoint;
-
- unsigned char *extra;
- int extralen;
-};
-
-struct usbbus_interface {
- struct usbbus_interface_descriptor *altsetting;
- int num_altsetting;
-};
-
-struct usbbus_config_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint16_t wTotalLength;
- uint8_t bNumInterfaces;
- uint8_t bConfigurationValue;
- uint8_t iConfiguration;
- uint8_t bmAttributes;
- uint8_t MaxPower;
-
- struct usbbus_interface *interface;
-
- unsigned char *extra;
- int extralen;
-};
-
-/* Device descriptor */
-struct usbbus_device_descriptor {
- uint8_t bLength;
- uint8_t bDescriptorType;
- uint16_t bcdUSB;
- uint8_t bDeviceClass;
- uint8_t bDeviceSubClass;
- uint8_t bDeviceProtocol;
- uint8_t bMaxPacketSize0;
- uint16_t idVendor;
- uint16_t idProduct;
- uint16_t bcdDevice;
- uint8_t iManufacturer;
- uint8_t iProduct;
- uint8_t iSerialNumber;
- uint8_t bNumConfigurations;
-};
-
-
-struct usbbus_bus;
+#define EMPTY_STRING "\0";
struct usbbus_device {
- struct usbbus_device *next, *prev;
-
- char filename[USBBUS_PATH_MAX + 1];
-
- struct usbbus_bus *bus;
-
- struct usbbus_device_descriptor descriptor;
- struct usbbus_config_descriptor *config;
-
- void *dev;
-
- uint8_t devnum;
-
- unsigned char num_children;
- struct usbbus_device **children;
-};
-
-struct usbbus_bus {
- struct usbbus_bus *next, *prev;
-
- char dirname[USBBUS_PATH_MAX + 1];
-
- struct usbbus_device *devices;
- uint32_t location;
-
- struct usbbus_device *root_dev;
+ uint16_t vendor_id;
+ uint16_t product_id;
+ const char *name;
+ uint16_t max_packet_size;
};
-usbbus_device_handle *usbbus_open(struct usbbus_device *dev);
-void usbbus_close(usbbus_device_handle *dev);
-int usbbus_set_configuration(usbbus_device_handle *dev, int configuration);
-int usbbus_get_string_simple(usbbus_device_handle *dev, int index, char *buf, size_t buflen);
-int usbbus_bulk_transfer(usbbus_device_handle *dev, int ep, char *bytes, int size, int *actual_length, int timeout);
-int usbbus_claim_interface(usbbus_device_handle *dev, int interface);
-int usbbus_release_interface(usbbus_device_handle *dev, int interface);
-int usbbus_set_interface_alt_setting(usbbus_device_handle *dev, int interface, int alternate);
-int usbbus_reset(usbbus_device_handle *dev);
-const char *usbbus_strerror(int errcode);
-struct usbbus_bus *usbbus_get_busses(void);
-#endif // __NFC_BUS_USB_H__
+int usbbus_prepare();
+
+size_t usbbus_usb_scan(char ** 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);
+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 cbe0bb2..3438c6c 100644
--- a/libnfc/drivers/acr122_usb.c
+++ b/libnfc/drivers/acr122_usb.c
@@ -48,6 +48,7 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
+
#endif // HAVE_CONFIG_H
/*
@@ -59,16 +60,18 @@ Thanks to d18c7db and Okko for example code
#include
#include
#include
+
#ifdef _MSC_VER
#include
#endif
#include
+#include
#include "nfc-internal.h"
-#include "buses/usbbus.h"
#include "chips/pn53x.h"
#include "chips/pn53x-internal.h"
#include "drivers/acr122_usb.h"
+#include "buses/usbbus.h"
#define ACR122_USB_DRIVER_NAME "acr122_usb"
@@ -142,65 +145,67 @@ PC_to_RDR_XfrBlock APDU
#pragma pack(1)
struct ccid_header {
- uint8_t bMessageType;
- uint32_t dwLength;
- uint8_t bSlot;
- uint8_t bSeq;
- uint8_t bMessageSpecific[3];
+ uint8_t bMessageType;
+ uint32_t dwLength;
+ uint8_t bSlot;
+ uint8_t bSeq;
+ uint8_t bMessageSpecific[3];
};
struct apdu_header {
- uint8_t bClass;
- uint8_t bIns;
- uint8_t bP1;
- uint8_t bP2;
- uint8_t bLen;
+ uint8_t bClass;
+ uint8_t bIns;
+ uint8_t bP1;
+ uint8_t bP2;
+ uint8_t bLen;
};
struct acr122_usb_tama_frame {
- struct ccid_header ccid_header;
- struct apdu_header apdu_header;
- uint8_t tama_header;
- uint8_t tama_payload[254]; // According to ACR122U manual: Pseudo APDUs (Section 6.0), Lc is 1-byte long (Data In: 255-bytes).
+ struct ccid_header ccid_header;
+ struct apdu_header apdu_header;
+ uint8_t tama_header;
+ uint8_t tama_payload[254
+ ]; // According to ACR122U manual: Pseudo APDUs (Section 6.0), Lc is 1-byte long (Data In: 255-bytes).
};
struct acr122_usb_apdu_frame {
- struct ccid_header ccid_header;
- struct apdu_header apdu_header;
- uint8_t apdu_payload[255]; // APDU Lc is 1-byte long
+ struct ccid_header ccid_header;
+ struct apdu_header apdu_header;
+ uint8_t apdu_payload[255]; // APDU Lc is 1-byte long
};
#pragma pack()
// Internal data struct
struct acr122_usb_data {
- usbbus_device_handle *pudh;
- uint32_t uiEndPointIn;
- uint32_t uiEndPointOut;
- uint32_t uiMaxPacketSize;
- volatile bool abort_flag;
- // Keep some buffers to reduce memcpy() usage
- struct acr122_usb_tama_frame tama_frame;
- struct acr122_usb_apdu_frame apdu_frame;
+ 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;
+ struct acr122_usb_apdu_frame apdu_frame;
};
// CCID Bulk-Out messages type
-#define PC_to_RDR_IccPowerOn 0x62
-#define PC_to_RDR_XfrBlock 0x6f
+#define PC_to_RDR_IccPowerOn 0x62
+#define PC_to_RDR_XfrBlock 0x6f
-#define RDR_to_PC_DataBlock 0x80
+#define RDR_to_PC_DataBlock 0x80
// ISO 7816-4
#define SW1_More_Data_Available 0x61
#define SW1_Warning_with_NV_changed 0x63
#define PN53x_Specific_Application_Level_Error_Code 0x7f
-
// This frame template is copied at init time
// Its designed for TAMA sending but is also used for simple ADPU frame: acr122_build_frame_from_apdu() will overwrite needed bytes
const uint8_t acr122_usb_frame_template[] = {
- PC_to_RDR_XfrBlock, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CCID header
- 0xff, 0x00, 0x00, 0x00, 0x00, // ADPU header
- 0xd4, // PN532 direction
+ PC_to_RDR_XfrBlock, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // CCID header
+ 0xff, 0x00, 0x00, 0x00, 0x00, // ADPU header
+ 0xd4, // PN532 direction
};
// APDUs instructions
@@ -213,299 +218,230 @@ const struct pn53x_io acr122_usb_io;
static int acr122_usb_init(nfc_device *pnd);
static int acr122_usb_ack(nfc_device *pnd);
static int acr122_usb_send_apdu(nfc_device *pnd,
- const uint8_t ins, const uint8_t p1, const uint8_t p2, const uint8_t *const data, size_t data_len, const uint8_t le,
- uint8_t *out, const size_t out_size);
+ const uint8_t ins,
+ const uint8_t p1,
+ const uint8_t p2,
+ const uint8_t *const data,
+ size_t data_len,
+ const uint8_t le,
+ uint8_t *out,
+ const size_t out_size);
static int
-acr122_usb_bulk_read(struct acr122_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout)
-{
- int actual_length;
- int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointIn, (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 != USBBUS_ERROR_TIMEOUT) {
- res = NFC_EIO;
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", usbbus_strerror(res));
- } else {
- res = NFC_ETIMEOUT;
- }
- }
- return res;
+acr122_usb_bulk_read(struct acr122_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, (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)",
+ libusb_strerror(res));
+ } else {
+ res = NFC_ETIMEOUT;
+ }
+ }
+ 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 actual_length;
- int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, (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 ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
- usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, "\0", 0, &actual_length, timeout);
- }
- } else {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", usbbus_strerror(res));
- if (res == USBBUS_ERROR_TIMEOUT) {
- res = NFC_ETIMEOUT;
- } else {
- res = NFC_EIO;
- }
- }
- return res;
+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 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 ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
+ libusb_bulk_transfer(data->pudh, data->uiEndPointOut, EMPTY_STRING, 0, &actual_length, timeout);
+ }
+ } 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;
+ }
+ }
+ return res;
}
struct acr122_usb_supported_device {
- uint16_t vendor_id;
- uint16_t product_id;
- const char *name;
+ 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" },
+ //TODO find real max_packet_sizes
+ {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 usbbus_device *dev, struct acr122_usb_data *data)
-{
- uint32_t uiIndex;
- uint32_t uiEndPoint;
- struct usbbus_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 != USBBUS_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 & USBBUS_ENDPOINT_DIR_MASK) == USBBUS_ENDPOINT_IN) {
- data->uiEndPointIn = uiEndPoint;
- data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
- }
- // Test if we dealing with a bulk OUT endpoint
- if ((uiEndPoint & USBBUS_ENDPOINT_DIR_MASK) == USBBUS_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;
-
- usbbus_prepare();
-
- size_t device_found = 0;
- uint32_t uiBusIndex = 0;
- struct usbbus_bus *bus;
- for (bus = usbbus_get_busses(); bus; bus = bus->next) {
- struct usbbus_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;
- }
-
- usbbus_device_handle *udev = usbbus_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);
- usbbus_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;
- }
- }
- }
- }
- }
-
- return device_found;
+acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) {
+ (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 usbbus_usb_scan((char **) 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 usbbus_device *dev, usbbus_device_handle *udev, char *buffer, size_t len)
-{
- *buffer = '\0';
+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) {
- usbbus_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len);
- if (strlen(buffer) > 0)
- strcpy(buffer + strlen(buffer), " / ");
- usbbus_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)) {
- strncpy(buffer, acr122_usb_supported_devices[n].name, len);
- buffer[len - 1] = '\0';
- return true;
- }
- }
- }
+ if (!*buffer) {
+ 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;
+ }
+ }
+ }
- return false;
+ return false;
}
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;
- }
+acr122_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, 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) {
+ return NULL;
+ }
- struct acr122_usb_data data = {
- .pudh = NULL,
- .uiEndPointIn = 0,
- .uiEndPointOut = 0,
- };
- struct usbbus_bus *bus;
- struct usbbus_device *dev;
+ uint8_t dev_addres = atoi(dev_address_str);
+ uint8_t config_idx = atoi(config_idx_str);
- usbbus_prepare();
+ usbbus_prepare();
- for (bus = usbbus_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 = usbbus_open(dev)) == NULL)
- continue;
- // Reset device
- usbbus_reset(data.pudh);
- // Retrieve end points
- acr122_usb_get_end_points(dev, &data);
- // Claim interface
- int res = usbbus_claim_interface(data.pudh, 0);
- if (res < 0) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", usbbus_strerror(res));
- usbbus_close(data.pudh);
- // we failed to use the specified device
- goto free_mem;
- }
+ struct acr122_usb_data data = {
+ .dev = NULL,
+ .pudh = NULL,
+ .configIdx = config_idx,
+ .uiEndPointIn = 0,
+ .uiEndPointOut = 0,
+ };
+ usbbus_get_device(dev_addres, data.dev, data.pudh);
+ // Reset device
+ libusb_reset_device(data.pudh);
- // Check if there are more than 0 alternative interfaces and claim the first one
- if (dev->config->interface->altsetting->bAlternateSetting > 0) {
- res = usbbus_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)", usbbus_strerror(res));
- usbbus_close(data.pudh);
- // we failed to use the specified device
- goto free_mem;
- }
- }
+ // 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
+ return NULL;
+ }
- // 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));
+ // Check if there are more than 0 alternative interfaces and claim the first one
+ // TODO would it not be better to iterate the alterative interfaces (and alternative settings) and check each 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
+ return NULL;
+ }
+ }
- pnd->driver_data = malloc(sizeof(struct acr122_usb_data));
- if (!pnd->driver_data) {
- perror("malloc");
- goto error;
- }
- *DRIVER_DATA(pnd) = data;
+ // Allocate memory for the device info and specification, fill it and return the info
+ pnd = nfc_device_new(context, connstring);
+ if (!pnd) {
+ perror("malloc");
+ return NULL;
+ }
+ acr122_usb_get_usb_device_name(data.dev, data.pudh, pnd->name, sizeof(pnd->name));
- // Alloc and init chip's data
- if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) {
- perror("malloc");
- goto error;
- }
+ pnd->driver_data = malloc(sizeof(struct acr122_usb_data));
+ if (!pnd->driver_data) {
+ perror("malloc");
+ nfc_device_free(pnd);
+ return NULL;
+ }
+ *DRIVER_DATA(pnd) = data;
- 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;
+ // Alloc and init chip's data
+ if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) {
+ perror("malloc");
+ nfc_device_free(pnd);
+ return NULL;
+ }
- if (acr122_usb_init(pnd) < 0) {
- usbbus_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;
+ 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;
-error:
- // Free allocated structure on error.
- nfc_device_free(pnd);
- pnd = NULL;
-free_mem:
- free(desc.dirname);
- free(desc.filename);
- return pnd;
+ if (acr122_usb_init(pnd) < 0) {
+ libusb_close(data.pudh);
+ nfc_device_free(pnd);
+ return NULL;
+ }
+ DRIVER_DATA(pnd)->abort_flag = false;
+
+ return pnd;
}
static void
-acr122_usb_close(nfc_device *pnd)
-{
- acr122_usb_ack(pnd);
- pn53x_idle(pnd);
+acr122_usb_close(nfc_device *pnd) {
+ acr122_usb_ack(pnd);
+ pn53x_idle(pnd);
- int res;
- if ((res = usbbus_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", usbbus_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));
+ }
- usbbus_close(DRIVER_DATA(pnd)->pudh);
- pn53x_data_free(pnd);
- nfc_device_free(pnd);
+ libusb_close(DRIVER_DATA(pnd)->pudh);
+ pn53x_data_free(pnd);
+ nfc_device_free(pnd);
}
#if !defined(htole32)
@@ -513,357 +449,395 @@ acr122_usb_close(nfc_device *pnd)
uint32_t htole32(uint32_t u32);
uint32_t
-htole32(uint32_t u32)
-{
- union {
- uint8_t arr[4];
- uint32_t u32;
- } u;
- for (int i = 0; i < 4; i++) {
- u.arr[i] = (u32 & 0xff);
- u32 >>= 8;
- }
- return u.u32;
+htole32(uint32_t u32) {
+ union {
+ uint8_t arr[4];
+ uint32_t u32;
+ } u;
+ for (int i = 0; i < 4; i++) {
+ u.arr[i] = (u32 & 0xff);
+ u32 >>= 8;
+ }
+ return u.u32;
}
#endif /* !defined(htole32) */
static int
-acr122_build_frame_from_apdu(nfc_device *pnd, const uint8_t ins, const uint8_t p1, const uint8_t p2, const uint8_t *data, const size_t data_len, const uint8_t le)
-{
- if (data_len > sizeof(DRIVER_DATA(pnd)->apdu_frame.apdu_payload))
- return NFC_EINVARG;
- if ((data == NULL) && (data_len != 0))
- return NFC_EINVARG;
+acr122_build_frame_from_apdu(nfc_device *pnd,
+ const uint8_t ins,
+ const uint8_t p1,
+ const uint8_t p2,
+ const uint8_t *data,
+ const size_t data_len,
+ const uint8_t le) {
+ if (data_len > sizeof(DRIVER_DATA(pnd)->apdu_frame.apdu_payload))
+ return NFC_EINVARG;
+ if ((data == NULL) && (data_len != 0))
+ return NFC_EINVARG;
- DRIVER_DATA(pnd)->apdu_frame.ccid_header.dwLength = htole32(data_len + sizeof(struct apdu_header));
- DRIVER_DATA(pnd)->apdu_frame.apdu_header.bIns = ins;
- DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP1 = p1;
- DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP2 = p2;
- if (data) {
- // bLen is Lc when data != NULL
- DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = data_len;
- memcpy(DRIVER_DATA(pnd)->apdu_frame.apdu_payload, data, data_len);
- } else {
- // bLen is Le when no data.
- DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = le;
- }
- return (sizeof(struct ccid_header) + sizeof(struct apdu_header) + data_len);
+ DRIVER_DATA(pnd)->apdu_frame.ccid_header.dwLength = htole32(data_len + sizeof(struct apdu_header));
+ DRIVER_DATA(pnd)->apdu_frame.apdu_header.bIns = ins;
+ DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP1 = p1;
+ DRIVER_DATA(pnd)->apdu_frame.apdu_header.bP2 = p2;
+ if (data) {
+ // bLen is Lc when data != NULL
+ DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = data_len;
+ memcpy(DRIVER_DATA(pnd)->apdu_frame.apdu_payload, data, data_len);
+ } else {
+ // bLen is Le when no data.
+ DRIVER_DATA(pnd)->apdu_frame.apdu_header.bLen = le;
+ }
+ return (sizeof(struct ccid_header) + sizeof(struct apdu_header) + data_len);
}
static int
-acr122_build_frame_from_tama(nfc_device *pnd, const uint8_t *tama, const size_t tama_len)
-{
- if (tama_len > sizeof(DRIVER_DATA(pnd)->tama_frame.tama_payload))
- return NFC_EINVARG;
+acr122_build_frame_from_tama(nfc_device *pnd, const uint8_t *tama, const size_t tama_len) {
+ if (tama_len > sizeof(DRIVER_DATA(pnd)->tama_frame.tama_payload))
+ return NFC_EINVARG;
- DRIVER_DATA(pnd)->tama_frame.ccid_header.dwLength = htole32(tama_len + sizeof(struct apdu_header) + 1);
- DRIVER_DATA(pnd)->tama_frame.apdu_header.bLen = tama_len + 1;
- memcpy(DRIVER_DATA(pnd)->tama_frame.tama_payload, tama, tama_len);
- return (sizeof(struct ccid_header) + sizeof(struct apdu_header) + 1 + tama_len);
+ DRIVER_DATA(pnd)->tama_frame.ccid_header.dwLength = htole32(tama_len + sizeof(struct apdu_header) + 1);
+ DRIVER_DATA(pnd)->tama_frame.apdu_header.bLen = tama_len + 1;
+ memcpy(DRIVER_DATA(pnd)->tama_frame.tama_payload, tama, tama_len);
+ return (sizeof(struct ccid_header) + sizeof(struct apdu_header) + 1 + tama_len);
}
static int
-acr122_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout)
-{
- int res;
- if ((res = acr122_build_frame_from_tama(pnd, pbtData, szData)) < 0) {
- pnd->last_error = NFC_EINVARG;
- return pnd->last_error;
- }
+acr122_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout) {
+ int res;
+ if ((res = acr122_build_frame_from_tama(pnd, pbtData, szData)) < 0) {
+ pnd->last_error = NFC_EINVARG;
+ return pnd->last_error;
+ }
- if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->tama_frame), res, timeout)) < 0) {
- pnd->last_error = res;
- return pnd->last_error;
- }
- return NFC_SUCCESS;
+ if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) &(DRIVER_DATA(pnd)->tama_frame), res, timeout))
+ < 0) {
+ pnd->last_error = res;
+ return pnd->last_error;
+ }
+ return NFC_SUCCESS;
}
#define USBBUS_TIMEOUT_PER_PASS 200
+
static int
-acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout)
-{
- off_t offset = 0;
+acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout) {
+ off_t offset = 0;
- uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
- int res;
+ uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
+ 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);
- }
- }
+ /*
+ * 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 = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usbbus_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;
+ uint8_t attempted_response = RDR_to_PC_DataBlock;
+ size_t len;
- if (res == NFC_ETIMEOUT) {
- if (DRIVER_DATA(pnd)->abort_flag) {
- DRIVER_DATA(pnd)->abort_flag = false;
- acr122_usb_ack(pnd);
- pnd->last_error = NFC_EOPABORTED;
- return pnd->last_error;
- } else {
- goto read;
- }
- }
- if (res < 12) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Invalid RDR_to_PC_DataBlock frame");
- // try to interrupt current device state
- acr122_usb_ack(pnd);
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- if (abtRxBuf[offset] != attempted_response) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame header mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset++;
+ if (res == NFC_ETIMEOUT) {
+ if (DRIVER_DATA(pnd)->abort_flag) {
+ DRIVER_DATA(pnd)->abort_flag = false;
+ acr122_usb_ack(pnd);
+ pnd->last_error = NFC_EOPABORTED;
+ return pnd->last_error;
+ } else {
+ goto read;
+ }
+ }
+ if (res < 12) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Invalid RDR_to_PC_DataBlock frame");
+ // try to interrupt current device state
+ acr122_usb_ack(pnd);
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ if (abtRxBuf[offset] != attempted_response) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame header mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset++;
- len = abtRxBuf[offset++];
- if (!((len > 1) && (abtRxBuf[10] == 0xd5))) { // In case we didn't get an immediate answer:
- if (len != 2) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Wrong reply");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- if (abtRxBuf[10] != SW1_More_Data_Available) {
- if ((abtRxBuf[10] == SW1_Warning_with_NV_changed) && (abtRxBuf[11] == PN53x_Specific_Application_Level_Error_Code)) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 has detected an error at the application level");
- } else if ((abtRxBuf[10] == SW1_Warning_with_NV_changed) && (abtRxBuf[11] == 0x00)) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 didn't reply");
- } else {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unexpected Status Word (SW1: %02x SW2: %02x)", abtRxBuf[10], abtRxBuf[11]);
- }
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- res = acr122_usb_send_apdu(pnd, APDU_GetAdditionnalData, 0x00, 0x00, NULL, 0, abtRxBuf[11], abtRxBuf, sizeof(abtRxBuf));
- if (res == NFC_ETIMEOUT) {
- if (DRIVER_DATA(pnd)->abort_flag) {
- DRIVER_DATA(pnd)->abort_flag = false;
- acr122_usb_ack(pnd);
- pnd->last_error = NFC_EOPABORTED;
- return pnd->last_error;
- } else {
- goto read; // FIXME May cause some trouble on Touchatag, right ?
- }
- }
- if (res < 12) {
- // try to interrupt current device state
- acr122_usb_ack(pnd);
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- }
- offset = 0;
- if (abtRxBuf[offset] != attempted_response) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame header mismatch");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset++;
+ len = abtRxBuf[offset++];
+ if (!((len > 1) && (abtRxBuf[10] == 0xd5))) { // In case we didn't get an immediate answer:
+ if (len != 2) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Wrong reply");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ if (abtRxBuf[10] != SW1_More_Data_Available) {
+ if ((abtRxBuf[10] == SW1_Warning_with_NV_changed)
+ && (abtRxBuf[11] == PN53x_Specific_Application_Level_Error_Code)) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "%s",
+ "PN532 has detected an error at the application level");
+ } else if ((abtRxBuf[10] == SW1_Warning_with_NV_changed) && (abtRxBuf[11] == 0x00)) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 didn't reply");
+ } else {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "Unexpected Status Word (SW1: %02x SW2: %02x)",
+ abtRxBuf[10],
+ abtRxBuf[11]);
+ }
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ res = acr122_usb_send_apdu(pnd,
+ APDU_GetAdditionnalData,
+ 0x00,
+ 0x00,
+ NULL,
+ 0,
+ abtRxBuf[11],
+ abtRxBuf,
+ sizeof(abtRxBuf));
+ if (res == NFC_ETIMEOUT) {
+ if (DRIVER_DATA(pnd)->abort_flag) {
+ DRIVER_DATA(pnd)->abort_flag = false;
+ acr122_usb_ack(pnd);
+ pnd->last_error = NFC_EOPABORTED;
+ return pnd->last_error;
+ } else {
+ goto read; // FIXME May cause some trouble on Touchatag, right ?
+ }
+ }
+ if (res < 12) {
+ // try to interrupt current device state
+ acr122_usb_ack(pnd);
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ }
+ offset = 0;
+ if (abtRxBuf[offset] != attempted_response) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame header mismatch");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset++;
- // XXX In CCID specification, len is a 32-bits (dword), do we need to decode more than 1 byte ? (0-255 bytes for PN532 reply)
- len = abtRxBuf[offset++];
- if ((abtRxBuf[offset] != 0x00) && (abtRxBuf[offset + 1] != 0x00) && (abtRxBuf[offset + 2] != 0x00)) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Not implemented: only 1-byte length is supported, please report this bug with a full trace.");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- offset += 3;
+ // XXX In CCID specification, len is a 32-bits (dword), do we need to decode more than 1 byte ? (0-255 bytes for PN532 reply)
+ len = abtRxBuf[offset++];
+ if ((abtRxBuf[offset] != 0x00) && (abtRxBuf[offset + 1] != 0x00) && (abtRxBuf[offset + 2] != 0x00)) {
+ log_put(LOG_GROUP,
+ LOG_CATEGORY,
+ NFC_LOG_PRIORITY_ERROR,
+ "%s",
+ "Not implemented: only 1-byte length is supported, please report this bug with a full trace.");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ offset += 3;
- if (len < 4) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Too small reply");
- pnd->last_error = NFC_EIO;
- return pnd->last_error;
- }
- len -= 4; // We skip 2 bytes for PN532 direction byte (D5) and command byte (CMD+1), then 2 bytes for APDU status (90 00).
+ if (len < 4) {
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Too small reply");
+ pnd->last_error = NFC_EIO;
+ return pnd->last_error;
+ }
+ len -=
+ 4; // We skip 2 bytes for PN532 direction byte (D5) and command byte (CMD+1), then 2 bytes for APDU status (90 00).
- 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_EOVFLOW;
- return pnd->last_error;
- }
+ 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_EOVFLOW;
+ return pnd->last_error;
+ }
- // Skip CCID remaining bytes
- offset += 2; // bSlot and bSeq are not used
- offset += 2; // XXX bStatus and bError should maybe checked ?
- offset += 1; // bRFU should be 0x00
+ // Skip CCID remaining bytes
+ offset += 2; // bSlot and bSeq are not used
+ offset += 2; // XXX bStatus and bError should maybe checked ?
+ offset += 1; // bRFU should be 0x00
- // 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;
+ // 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;
+ 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);
+ memcpy(pbtData, abtRxBuf + offset, len);
- return len;
+ return len;
}
int
-acr122_usb_ack(nfc_device *pnd)
-{
- (void) pnd;
- int res = 0;
- uint8_t acr122_ack_frame[] = { GetFirmwareVersion }; // We can't send a PN532's ACK frame, so we use a normal command to cancel current command
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 Abort");
- if ((res = acr122_build_frame_from_tama(pnd, acr122_ack_frame, sizeof(acr122_ack_frame))) < 0)
- return res;
- if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->tama_frame), res, 1000)) < 0)
- return res;
- uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
- res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000);
- return res;
+acr122_usb_ack(nfc_device *pnd) {
+ (void) pnd;
+ int res = 0;
+ uint8_t acr122_ack_frame[] =
+ {GetFirmwareVersion}; // We can't send a PN532's ACK frame, so we use a normal command to cancel current command
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 Abort");
+ if ((res = acr122_build_frame_from_tama(pnd, acr122_ack_frame, sizeof(acr122_ack_frame))) < 0)
+ return res;
+ if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) &(DRIVER_DATA(pnd)->tama_frame), res, 1000))
+ < 0)
+ return res;
+ uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
+ res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000);
+ return res;
}
static int
acr122_usb_send_apdu(nfc_device *pnd,
- const uint8_t ins, const uint8_t p1, const uint8_t p2, const uint8_t *const data, size_t data_len, const uint8_t le,
- uint8_t *out, const size_t out_size)
-{
- int res;
- size_t frame_len = acr122_build_frame_from_apdu(pnd, ins, p1, p2, data, data_len, le);
- if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->apdu_frame), frame_len, 1000)) < 0)
- return res;
- if ((res = acr122_usb_bulk_read(DRIVER_DATA(pnd), out, out_size, 1000)) < 0)
- return res;
- return res;
+ const uint8_t ins,
+ const uint8_t p1,
+ const uint8_t p2,
+ const uint8_t *const data,
+ size_t data_len,
+ const uint8_t le,
+ uint8_t *out,
+ const size_t out_size) {
+ int res;
+ size_t frame_len = acr122_build_frame_from_apdu(pnd, ins, p1, p2, data, data_len, le);
+ if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd),
+ (unsigned char *) &(DRIVER_DATA(pnd)->apdu_frame),
+ frame_len,
+ 1000)) < 0)
+ return res;
+ if ((res = acr122_usb_bulk_read(DRIVER_DATA(pnd), out, out_size, 1000)) < 0)
+ return res;
+ return res;
}
int
-acr122_usb_init(nfc_device *pnd)
-{
- int res = 0;
- int i;
- uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
+acr122_usb_init(nfc_device *pnd) {
+ int res = 0;
+ int i;
+ uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
- /*
- // See ACR122 manual: "Bi-Color LED and Buzzer Control" section
- uint8_t acr122u_get_led_state_frame[] = {
- 0x6b, // CCID
- 0x09, // lenght of frame
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding
- // frame:
- 0xff, // Class
- 0x00, // INS
- 0x40, // P1: Get LED state command
- 0x00, // P2: LED state control
- 0x04, // Lc
- 0x00, 0x00, 0x00, 0x00, // Blinking duration control
- };
+ /*
+ // See ACR122 manual: "Bi-Color LED and Buzzer Control" section
+ uint8_t acr122u_get_led_state_frame[] = {
+ 0x6b, // CCID
+ 0x09, // lenght of frame
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // padding
+ // frame:
+ 0xff, // Class
+ 0x00, // INS
+ 0x40, // P1: Get LED state command
+ 0x00, // P2: LED state control
+ 0x04, // Lc
+ 0x00, 0x00, 0x00, 0x00, // Blinking duration control
+ };
- log_put (LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 Get LED state");
- if ((res = acr122_usb_bulk_write (DRIVER_DATA (pnd), (uint8_t *) acr122u_get_led_state_frame, sizeof (acr122u_get_led_state_frame), 1000)) < 0)
- return res;
+ log_put (LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 Get LED state");
+ if ((res = acr122_usb_bulk_write (DRIVER_DATA (pnd), (uint8_t *) acr122u_get_led_state_frame, sizeof (acr122u_get_led_state_frame), 1000)) < 0)
+ return res;
- if ((res = acr122_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), 1000)) < 0)
- return res;
- */
+ if ((res = acr122_usb_bulk_read (DRIVER_DATA (pnd), abtRxBuf, sizeof (abtRxBuf), 1000)) < 0)
+ return res;
+ */
- if ((res = pn53x_set_property_int(pnd, NP_TIMEOUT_COMMAND, 1000)) < 0)
- return res;
+ if ((res = pn53x_set_property_int(pnd, NP_TIMEOUT_COMMAND, 1000)) < 0)
+ return res;
- // Power On ICC
- uint8_t ccid_frame[] = {
- PC_to_RDR_IccPowerOn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
- };
+ // Power On ICC
+ uint8_t ccid_frame[] = {
+ PC_to_RDR_IccPowerOn, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
+ };
- if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), ccid_frame, sizeof(struct ccid_header), 1000)) < 0)
- return res;
- if ((res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000)) < 0)
- return res;
+ if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), ccid_frame, sizeof(struct ccid_header), 1000)) < 0)
+ return res;
+ if ((res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000)) < 0)
+ return res;
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 PICC Operating Parameters");
- if ((res = acr122_usb_send_apdu(pnd, 0x00, 0x51, 0x00, NULL, 0, 0, abtRxBuf, sizeof(abtRxBuf))) < 0)
- return res;
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ACR122 PICC Operating Parameters");
+ if ((res = acr122_usb_send_apdu(pnd, 0x00, 0x51, 0x00, NULL, 0, 0, abtRxBuf, sizeof(abtRxBuf))) < 0)
+ return res;
- res = 0;
- for (i = 0; i < 3; i++) {
- if (res < 0)
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 init failed, trying again...");
- if ((res = pn53x_init(pnd)) >= 0)
- break;
- }
- if (res < 0)
- return res;
+ res = 0;
+ for (i = 0; i < 3; i++) {
+ if (res < 0)
+ log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 init failed, trying again...");
+ if ((res = pn53x_init(pnd)) >= 0)
+ break;
+ }
+ if (res < 0)
+ return res;
- return NFC_SUCCESS;
+ return NFC_SUCCESS;
}
static int
-acr122_usb_abort_command(nfc_device *pnd)
-{
- DRIVER_DATA(pnd)->abort_flag = true;
- return NFC_SUCCESS;
+acr122_usb_abort_command(nfc_device *pnd) {
+ DRIVER_DATA(pnd)->abort_flag = true;
+ return NFC_SUCCESS;
}
const struct pn53x_io acr122_usb_io = {
- .send = acr122_usb_send,
- .receive = acr122_usb_receive,
+ .send = acr122_usb_send,
+ .receive = acr122_usb_receive,
};
const struct nfc_driver acr122_usb_driver = {
- .name = ACR122_USB_DRIVER_NAME,
- .scan_type = NOT_INTRUSIVE,
- .scan = acr122_usb_scan,
- .open = acr122_usb_open,
- .close = acr122_usb_close,
- .strerror = pn53x_strerror,
+ .name = ACR122_USB_DRIVER_NAME,
+ .scan_type = NOT_INTRUSIVE,
+ .scan = acr122_usb_scan,
+ .open = acr122_usb_open,
+ .close = acr122_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,
+ .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,
+ .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_set_property_bool,
- .device_set_property_int = pn53x_set_property_int,
- .get_supported_modulation = pn53x_get_supported_modulation,
- .get_supported_baud_rate = pn53x_get_supported_baud_rate,
- .device_get_information_about = pn53x_get_information_about,
+ .device_set_property_bool = pn53x_set_property_bool,
+ .device_set_property_int = pn53x_set_property_int,
+ .get_supported_modulation = pn53x_get_supported_modulation,
+ .get_supported_baud_rate = pn53x_get_supported_baud_rate,
+ .device_get_information_about = pn53x_get_information_about,
- .abort_command = acr122_usb_abort_command,
- .idle = pn53x_idle,
- /* Even if PN532, PowerDown is not recommended on those devices */
- .powerdown = NULL,
+ .abort_command = acr122_usb_abort_command,
+ .idle = pn53x_idle,
+ /* Even if PN532, PowerDown is not recommended on those devices */
+ .powerdown = NULL,
};
diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c
index 71b3670..8c23e68 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
/*
@@ -42,11 +43,12 @@ Thanks to d18c7db and Okko for example code
#include
#include
#include
+
#ifdef _MSC_VER
#include
#endif
#include
-
+#include
#include "nfc-internal.h"
#include "buses/usbbus.h"
#include "chips/pn53x.h"
@@ -64,845 +66,758 @@ Thanks to d18c7db and Okko for example code
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 {
- usbbus_device_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 usbbus_device *dev, usbbus_device_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 actual_length;
- int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointIn, (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 != USBBUS_ERROR_TIMEOUT)
- log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", usbbus_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 actual_length;
- int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, (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 ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
- usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, "\0", 0, &actual_length, timeout);
- }
- } else {
- log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", usbbus_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;
- }
+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;
+ return UNKNOWN;
}
static bool
-pn53x_usb_get_end_points_default(struct usbbus_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;
+pn53x_usb_get_end_points_default(struct pn53x_usb_data *data) {
+ struct libusb_device_descriptor descriptor;
+ libusb_get_device_descriptor(data->dev, &descriptor);
- return true;
- }
- }
- }
+ 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 false;
+ 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 usbbus_device *dev, struct pn53x_usb_data *data)
-{
- uint32_t uiIndex;
- uint32_t uiEndPoint;
- struct usbbus_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 != USBBUS_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 & USBBUS_ENDPOINT_DIR_MASK) == USBBUS_ENDPOINT_IN) {
- data->uiEndPointIn = uiEndPoint;
- data->uiMaxPacketSize = puid->endpoint[uiIndex].wMaxPacketSize;
- }
- // Test if we dealing with a bulk OUT endpoint
- if ((uiEndPoint & USBBUS_ENDPOINT_DIR_MASK) == USBBUS_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;
-
- usbbus_prepare();
-
- size_t device_found = 0;
- uint32_t uiBusIndex = 0;
- struct usbbus_bus *bus;
- for (bus = usbbus_get_busses(); bus; bus = bus->next) {
- struct usbbus_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;
- }
- }
-
- usbbus_device_handle *udev = usbbus_open(dev);
- if (udev == NULL)
- continue;
-
- // Set configuration
- int res = usbbus_set_configuration(udev, 1);
- if (res < 0) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", usbbus_strerror(res));
- usbbus_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);
- usbbus_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((char **) 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 usbbus_device *dev, usbbus_device_handle *udev, char *buffer, size_t len)
-{
- *buffer = '\0';
+pn53x_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) {
- usbbus_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len);
- if (strlen(buffer) > 0)
- strcpy(buffer + strlen(buffer), " / ");
- usbbus_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(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;
- }
- }
- }
+ 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;
+ 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;
- }
+pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) {
+ nfc_device *pnd = NULL;
- struct pn53x_usb_data data = {
- .pudh = NULL,
- .uiEndPointIn = 0,
- .uiEndPointOut = 0,
- .possibly_corrupted_usbdesc = false,
- };
- struct usbbus_bus *bus;
- struct usbbus_device *dev;
+ 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;
+ }
- usbbus_prepare();
+ uint8_t dev_addres = atoi(dev_address_str);
+ uint8_t config_idx = atoi(config_idx_str);
- for (bus = usbbus_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 = usbbus_open(dev)) == NULL)
- continue;
+ usbbus_prepare();
- //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 = usbbus_set_configuration(data.pudh, 1);
- if (res < 0) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", usbbus_strerror(res));
- if (res == USBBUS_ERROR_ACCESS) {
- 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);
- }
- usbbus_close(data.pudh);
- // we failed to use the specified device
- goto free_mem;
- }
+ struct pn53x_usb_data data = {
+ .dev = NULL,
+ .pudh = NULL,
+ .configIdx = config_idx,
+ .uiEndPointIn = 0,
+ .uiEndPointOut = 0,
+ .possibly_corrupted_usbdesc = false,
+ };
- res = usbbus_claim_interface(data.pudh, 0);
- if (res < 0) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", usbbus_strerror(res));
- usbbus_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));
+ usbbus_get_device(dev_addres, data.dev, data.pudh);
- 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);
+ // 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));
- // 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) {
- usbbus_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;
+ }
+ // 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);
+ }
+ libusb_close(data.pudh);
+ // we failed to use the specified device
+ return NULL;
+ }
-error:
- // Free allocated structure on error.
- nfc_device_free(pnd);
- pnd = NULL;
-free_mem:
- free(desc.dirname);
- free(desc.filename);
- return pnd;
+ 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
+ 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");
+ 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);
+ 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);
+ 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) {
+ libusb_close(data.pudh);
+ nfc_device_free(pnd);
+ return NULL;
+ }
+ DRIVER_DATA(pnd)->abort_flag = false;
+ return pnd;
}
static void
-pn53x_usb_close(nfc_device *pnd)
-{
- pn53x_usb_ack(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)->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);
+ if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc) {
+ pn533_fix_usbdesc(pnd);
+ }
- pn53x_idle(pnd);
+ pn53x_idle(pnd);
- int res;
- if ((res = usbbus_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) {
- log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", usbbus_strerror(res));
- }
-
- usbbus_close(DRIVER_DATA(pnd)->pudh);
- pn53x_data_free(pnd);
- nfc_device_free(pnd);
+ libusb_close(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;
+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;
- }
+ 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;
- }
+ 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;
- }
+ 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;
+ 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 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;
+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;
+ 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);
- }
- }
+ /*
+ * 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);
+ res = pn53x_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), usbbus_timeout);
- if (res == USBBUS_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 == 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;
- }
+ 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;
+ 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;
+ 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[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;
- }
+ // 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;
- }
+ 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;
+ // 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;
+ 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;
+ 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];
- }
+ 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 (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;
+ 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);
- }
+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 ((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);
+ 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);
+ /* 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.
+ /*
+ 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'.
- */
+ 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);
+ /* 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;
+ 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;
+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;
+ 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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .abort_command = pn53x_usb_abort_command,
+ .idle = pn53x_idle,
+ .powerdown = pn53x_PowerDown,
};