Reimplementing usb code with libusb-1.0
This commit is contained in:
parent
c4e04d52d3
commit
1ac0d803da
394
NEWS.md
394
NEWS.md
@ -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)
|
|
||||||
@ -7,6 +7,7 @@
|
|||||||
* Copyright (C) 2010-2012 Romain Tartière
|
* Copyright (C) 2010-2012 Romain Tartière
|
||||||
* Copyright (C) 2010-2013 Philippe Teuwen
|
* Copyright (C) 2010-2013 Philippe Teuwen
|
||||||
* Copyright (C) 2012-2013 Ludovic Rousseau
|
* Copyright (C) 2012-2013 Ludovic Rousseau
|
||||||
|
* Copyright (C) 2022 Kenspeckle
|
||||||
* See AUTHORS file for a more comprehensive list of contributors.
|
* See AUTHORS file for a more comprehensive list of contributors.
|
||||||
* Additional contributors of this file:
|
* Additional contributors of this file:
|
||||||
*
|
*
|
||||||
@ -24,634 +25,300 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <stdbool.h>
|
||||||
/**
|
#include <string.h>
|
||||||
* @file usbbus.c
|
|
||||||
* @brief libusb 0.1 driver wrapper
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
# include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <libusb.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "usbbus.h"
|
#include "usbbus.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#define LOG_CATEGORY "libnfc.buses.usbbus"
|
|
||||||
|
|
||||||
|
#define LOG_CATEGORY "libnfc.bus.usbbus"
|
||||||
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
|
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
|
||||||
|
|
||||||
/*
|
|
||||||
* This file embeds partially libusb-compat-0.1 by:
|
|
||||||
* Copyright (C) 2008 Daniel Drake <dsd@gentoo.org>
|
|
||||||
* Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
|
|
||||||
* 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;
|
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)
|
int usbbus_prepare() {
|
||||||
{
|
|
||||||
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;
|
static bool usb_initialized = false;
|
||||||
|
int res;
|
||||||
if (!usb_initialized) {
|
if (!usb_initialized) {
|
||||||
|
|
||||||
#ifdef ENVVARS
|
#ifdef ENVVARS
|
||||||
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
|
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
|
||||||
// Set libusb debug only if asked explicitely:
|
// Set libusb debug only if asked explicitely:
|
||||||
// LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB)
|
// LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB)
|
||||||
if (env_log_level && (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
|
if (env_log_level
|
||||||
|
&& (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
|
||||||
setenv("USB_DEBUG", "255", 1);
|
setenv("USB_DEBUG", "255", 1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
usb_init();
|
res = libusb_init(&ctx);
|
||||||
|
if (res != 0) {
|
||||||
|
log_put(LOG_GROUP,
|
||||||
|
LOG_CATEGORY,
|
||||||
|
NFC_LOG_PRIORITY_ERROR,
|
||||||
|
"Unable to init libusb (%s)",
|
||||||
|
libusb_strerror(res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
usb_initialized = true;
|
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
|
// 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
|
// called after usb_find_busses. Returns the number of changes since the
|
||||||
// previous call to this function (total of new device and devices removed).
|
// previous call to this function (total of new device and devices removed).
|
||||||
if ((res = usb_find_devices()) < 0) {
|
libusb_device **tmp_devices;
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", usbbus_strerror(res));
|
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 -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
usbbus_device_handle *usbbus_open(struct usbbus_device *dev)
|
|
||||||
{
|
TODO kenspeckle
|
||||||
int r;
|
beim ende vom programm libusb dinge wieder freigeben
|
||||||
usbbus_device_handle *udev;
|
|
||||||
r = libusb_open((libusb_device *) dev->dev, (libusb_device_handle **)&udev);
|
size_t usbbus_usb_scan(char **connstrings,
|
||||||
if (r < 0) {
|
const size_t connstrings_len,
|
||||||
return NULL;
|
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;
|
||||||
}
|
}
|
||||||
return (usbbus_device_handle *)udev;
|
|
||||||
|
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)
|
void usbbus_get_usb_endpoints(struct libusb_device *dev,
|
||||||
{
|
uint8_t *endpoint_in,
|
||||||
libusb_close((libusb_device_handle *)dev);
|
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)
|
uint8_t get_usb_num_configs(struct libusb_device *dev) {
|
||||||
{
|
struct libusb_device_descriptor descriptor;
|
||||||
return libusb_set_configuration((libusb_device_handle *)dev, configuration);
|
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)
|
void usbbus_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
|
||||||
{
|
struct libusb_device_descriptor descriptor;
|
||||||
return libusb_get_string_descriptor_ascii((libusb_device_handle *)dev, index & 0xff,
|
libusb_get_device_descriptor(dev, &descriptor);
|
||||||
(unsigned char *) buf, (int) buflen);
|
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)
|
|
||||||
{
|
void usbbus_get_device(uint8_t dev_address, struct libusb_device * dev, struct libusb_device_handle * dev_handle) {
|
||||||
return libusb_bulk_transfer((libusb_device_handle *)dev, ep & 0xff, (unsigned char *)bytes, size, actual_length, timeout);
|
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)
|
|
||||||
{
|
uint16_t usbbus_get_vendor_id(struct libusb_device *dev) {
|
||||||
return libusb_claim_interface((libusb_device_handle *)dev, interface);
|
struct libusb_device_descriptor descriptor;
|
||||||
|
libusb_get_device_descriptor(dev, &descriptor);
|
||||||
|
return descriptor.idVendor;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbbus_release_interface(usbbus_device_handle *dev, int interface)
|
uint16_t usbbus_get_product_id(struct libusb_device *dev) {
|
||||||
{
|
struct libusb_device_descriptor descriptor;
|
||||||
return libusb_release_interface((libusb_device_handle *)dev, interface);
|
libusb_get_device_descriptor(dev, &descriptor);
|
||||||
|
return descriptor.idProduct;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usbbus_set_interface_alt_setting(usbbus_device_handle *dev, int interface, int alternate)
|
|
||||||
{
|
int usbbus_get_num_alternate_settings(struct libusb_device *dev, uint8_t config_idx) {
|
||||||
return libusb_set_interface_alt_setting((libusb_device_handle *)dev, interface, alternate);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
* Copyright (C) 2010-2012 Romain Tartière
|
* Copyright (C) 2010-2012 Romain Tartière
|
||||||
* Copyright (C) 2010-2013 Philippe Teuwen
|
* Copyright (C) 2010-2013 Philippe Teuwen
|
||||||
* Copyright (C) 2012-2013 Ludovic Rousseau
|
* Copyright (C) 2012-2013 Ludovic Rousseau
|
||||||
|
* Copyright (C) 2022 Kenspeckle
|
||||||
* See AUTHORS file for a more comprehensive list of contributors.
|
* See AUTHORS file for a more comprehensive list of contributors.
|
||||||
* Additional contributors of this file:
|
* Additional contributors of this file:
|
||||||
*
|
*
|
||||||
@ -25,150 +26,29 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
#ifndef __NFC_BUS_USBBUS_H__
|
||||||
* @file usbbus.h
|
#define __NFC_BUS_USBBUS_H__
|
||||||
* @brief libusb 0.1 driver header
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NFC_BUS_USB_H__
|
#include <libusb-1.0/libusb.h>
|
||||||
# define __NFC_BUS_USB_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#define EMPTY_STRING "\0";
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
struct usbbus_device {
|
struct usbbus_device {
|
||||||
struct usbbus_device *next, *prev;
|
uint16_t vendor_id;
|
||||||
|
uint16_t product_id;
|
||||||
char filename[USBBUS_PATH_MAX + 1];
|
const char *name;
|
||||||
|
uint16_t max_packet_size;
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -59,16 +60,18 @@ Thanks to d18c7db and Okko for example code
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
#include <libusb.h>
|
||||||
|
|
||||||
#include "nfc-internal.h"
|
#include "nfc-internal.h"
|
||||||
#include "buses/usbbus.h"
|
|
||||||
#include "chips/pn53x.h"
|
#include "chips/pn53x.h"
|
||||||
#include "chips/pn53x-internal.h"
|
#include "chips/pn53x-internal.h"
|
||||||
#include "drivers/acr122_usb.h"
|
#include "drivers/acr122_usb.h"
|
||||||
|
#include "buses/usbbus.h"
|
||||||
|
|
||||||
#define ACR122_USB_DRIVER_NAME "acr122_usb"
|
#define ACR122_USB_DRIVER_NAME "acr122_usb"
|
||||||
|
|
||||||
@ -161,7 +164,8 @@ struct acr122_usb_tama_frame {
|
|||||||
struct ccid_header ccid_header;
|
struct ccid_header ccid_header;
|
||||||
struct apdu_header apdu_header;
|
struct apdu_header apdu_header;
|
||||||
uint8_t tama_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).
|
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 acr122_usb_apdu_frame {
|
||||||
@ -173,10 +177,12 @@ struct acr122_usb_apdu_frame {
|
|||||||
|
|
||||||
// Internal data struct
|
// Internal data struct
|
||||||
struct acr122_usb_data {
|
struct acr122_usb_data {
|
||||||
usbbus_device_handle *pudh;
|
libusb_device * dev;
|
||||||
uint32_t uiEndPointIn;
|
libusb_device_handle *pudh;
|
||||||
uint32_t uiEndPointOut;
|
uint8_t configIdx;
|
||||||
uint32_t uiMaxPacketSize;
|
uint8_t uiEndPointIn;
|
||||||
|
uint8_t uiEndPointOut;
|
||||||
|
uint16_t uiMaxPacketSize;
|
||||||
volatile bool abort_flag;
|
volatile bool abort_flag;
|
||||||
// Keep some buffers to reduce memcpy() usage
|
// Keep some buffers to reduce memcpy() usage
|
||||||
struct acr122_usb_tama_frame tama_frame;
|
struct acr122_usb_tama_frame tama_frame;
|
||||||
@ -194,7 +200,6 @@ struct acr122_usb_data {
|
|||||||
#define SW1_Warning_with_NV_changed 0x63
|
#define SW1_Warning_with_NV_changed 0x63
|
||||||
#define PN53x_Specific_Application_Level_Error_Code 0x7f
|
#define PN53x_Specific_Application_Level_Error_Code 0x7f
|
||||||
|
|
||||||
|
|
||||||
// This frame template is copied at init time
|
// 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
|
// 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[] = {
|
const uint8_t acr122_usb_frame_template[] = {
|
||||||
@ -213,21 +218,30 @@ const struct pn53x_io acr122_usb_io;
|
|||||||
static int acr122_usb_init(nfc_device *pnd);
|
static int acr122_usb_init(nfc_device *pnd);
|
||||||
static int acr122_usb_ack(nfc_device *pnd);
|
static int acr122_usb_ack(nfc_device *pnd);
|
||||||
static int acr122_usb_send_apdu(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,
|
const uint8_t ins,
|
||||||
uint8_t *out, const size_t out_size);
|
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
|
static int
|
||||||
acr122_usb_bulk_read(struct acr122_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout)
|
acr122_usb_bulk_read(struct acr122_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout) {
|
||||||
{
|
|
||||||
int actual_length;
|
int actual_length;
|
||||||
int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, &actual_length, timeout);
|
int res = libusb_bulk_transfer(data->pudh, data->uiEndPointIn, (unsigned char *) abtRx, szRx, &actual_length, timeout);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, actual_length);
|
LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, actual_length);
|
||||||
res = actual_length;
|
res = actual_length;
|
||||||
} else {
|
} else {
|
||||||
if (res != USBBUS_ERROR_TIMEOUT) {
|
if (res != LIBUSB_ERROR_TIMEOUT) {
|
||||||
res = NFC_EIO;
|
res = NFC_EIO;
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", usbbus_strerror(res));
|
log_put(LOG_GROUP,
|
||||||
|
LOG_CATEGORY,
|
||||||
|
NFC_LOG_PRIORITY_ERROR,
|
||||||
|
"Unable to read from USB (%s)",
|
||||||
|
libusb_strerror(res));
|
||||||
} else {
|
} else {
|
||||||
res = NFC_ETIMEOUT;
|
res = NFC_ETIMEOUT;
|
||||||
}
|
}
|
||||||
@ -236,19 +250,18 @@ acr122_usb_bulk_read(struct acr122_usb_data *data, uint8_t abtRx[], const size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
acr122_usb_bulk_write(struct acr122_usb_data *data, uint8_t abtTx[], const size_t szTx, const int timeout)
|
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);
|
LOG_HEX(NFC_LOG_GROUP_COM, "TX", abtTx, szTx);
|
||||||
int actual_length;
|
int actual_length;
|
||||||
int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, (char *) abtTx, szTx, &actual_length, timeout);
|
int res = libusb_bulk_transfer(data->pudh, data->uiEndPointOut, (unsigned char *) abtTx, szTx, &actual_length, timeout);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
// HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
|
// 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)) {
|
if ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
|
||||||
usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, "\0", 0, &actual_length, timeout);
|
libusb_bulk_transfer(data->pudh, data->uiEndPointOut, EMPTY_STRING, 0, &actual_length, timeout);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", usbbus_strerror(res));
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", libusb_strerror(res));
|
||||||
if (res == USBBUS_ERROR_TIMEOUT) {
|
if (res == LIBUSB_ERROR_TIMEOUT) {
|
||||||
res = NFC_ETIMEOUT;
|
res = NFC_ETIMEOUT;
|
||||||
} else {
|
} else {
|
||||||
res = NFC_EIO;
|
res = NFC_EIO;
|
||||||
@ -261,120 +274,45 @@ struct acr122_usb_supported_device {
|
|||||||
uint16_t vendor_id;
|
uint16_t vendor_id;
|
||||||
uint16_t product_id;
|
uint16_t product_id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
uint16_t max_packet_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct acr122_usb_supported_device acr122_usb_supported_devices[] = {
|
const struct acr122_usb_supported_device acr122_usb_supported_devices[] = {
|
||||||
{ 0x072F, 0x2200, "ACS ACR122" },
|
//TODO find real max_packet_sizes
|
||||||
{ 0x072F, 0x90CC, "Touchatag" },
|
{0x072F, 0x2200, "ACS ACR122", 0x40},
|
||||||
{ 0x072F, 0x2214, "ACS ACR1222" },
|
{0x072F, 0x90CC, "Touchatag", 0x40},
|
||||||
|
{0x072F, 0x2214, "ACS ACR1222", 0x40},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Find transfer endpoints for bulk transfers
|
const size_t
|
||||||
static void
|
num_acr122_usb_supported_device = sizeof(acr122_usb_supported_devices) / sizeof(struct acr122_usb_supported_device);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
|
acr122_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) {
|
||||||
{
|
(void) context;
|
||||||
(void)context;
|
struct usbbus_device devices[num_acr122_usb_supported_device];
|
||||||
|
for (size_t i = 0; i < num_acr122_usb_supported_device; i++) {
|
||||||
usbbus_prepare();
|
devices[i].product_id = acr122_usb_supported_devices[i].product_id;
|
||||||
|
devices[i].vendor_id = acr122_usb_supported_devices[i].vendor_id;
|
||||||
size_t device_found = 0;
|
devices[i].name = acr122_usb_supported_devices[i].name;
|
||||||
uint32_t uiBusIndex = 0;
|
devices[i].max_packet_size = acr122_usb_supported_devices[i].max_packet_size;
|
||||||
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) {
|
return usbbus_usb_scan((char **) connstrings, connstrings_len, devices, num_acr122_usb_supported_device, ACR122_USB_DRIVER_NAME);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct acr122_usb_descriptor {
|
|
||||||
char *dirname;
|
|
||||||
char *filename;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
acr122_usb_get_usb_device_name(struct usbbus_device *dev, usbbus_device_handle *udev, char *buffer, size_t len)
|
acr122_usb_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
|
||||||
{
|
|
||||||
*buffer = '\0';
|
*buffer = '\0';
|
||||||
|
|
||||||
if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
|
usbbus_get_usb_device_name(dev, udev, buffer, len);
|
||||||
if (udev) {
|
uint16_t vendor_id = usbbus_get_vendor_id(dev);
|
||||||
usbbus_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len);
|
uint16_t product_id = usbbus_get_product_id(dev);
|
||||||
if (strlen(buffer) > 0)
|
|
||||||
strcpy(buffer + strlen(buffer), " / ");
|
|
||||||
usbbus_get_string_simple(udev, dev->descriptor.iProduct, buffer + strlen(buffer), len - strlen(buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*buffer) {
|
if (!*buffer) {
|
||||||
for (size_t n = 0; n < sizeof(acr122_usb_supported_devices) / sizeof(struct acr122_usb_supported_device); n++) {
|
for (size_t n = 0; n < num_acr122_usb_supported_device; n++) {
|
||||||
if ((acr122_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) &&
|
if ((acr122_usb_supported_devices[n].vendor_id == vendor_id) &&
|
||||||
(acr122_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) {
|
(acr122_usb_supported_devices[n].product_id == product_id)) {
|
||||||
strncpy(buffer, acr122_usb_supported_devices[n].name, len);
|
strncpy(buffer, acr122_usb_supported_devices[n].name, len);
|
||||||
buffer[len - 1] = '\0';
|
buffer[len - 1] = '\0';
|
||||||
return true;
|
return true;
|
||||||
@ -386,62 +324,66 @@ acr122_usb_get_usb_device_name(struct usbbus_device *dev, usbbus_device_handle *
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nfc_device *
|
static nfc_device *
|
||||||
acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
|
acr122_usb_open(const nfc_context *context, const nfc_connstring connstring) {
|
||||||
{
|
|
||||||
nfc_device *pnd = NULL;
|
nfc_device *pnd = NULL;
|
||||||
struct acr122_usb_descriptor desc = { NULL, NULL };
|
char *dev_address_str;
|
||||||
int connstring_decode_level = connstring_decode(connstring, ACR122_USB_DRIVER_NAME, "usb", &desc.dirname, &desc.filename);
|
char *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);
|
int connstring_decode_level =
|
||||||
if (connstring_decode_level < 1) {
|
connstring_decode(connstring, ACR122_USB_DRIVER_NAME, "usb", &dev_address_str, &config_idx_str);
|
||||||
goto free_mem;
|
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 = {
|
uint8_t dev_addres = atoi(dev_address_str);
|
||||||
.pudh = NULL,
|
uint8_t config_idx = atoi(config_idx_str);
|
||||||
.uiEndPointIn = 0,
|
|
||||||
.uiEndPointOut = 0,
|
|
||||||
};
|
|
||||||
struct usbbus_bus *bus;
|
|
||||||
struct usbbus_device *dev;
|
|
||||||
|
|
||||||
usbbus_prepare();
|
usbbus_prepare();
|
||||||
|
|
||||||
for (bus = usbbus_get_busses(); bus; bus = bus->next) {
|
struct acr122_usb_data data = {
|
||||||
if (connstring_decode_level > 1) {
|
.dev = NULL,
|
||||||
// A specific bus have been specified
|
.pudh = NULL,
|
||||||
if (0 != strcmp(bus->dirname, desc.dirname))
|
.configIdx = config_idx,
|
||||||
continue;
|
.uiEndPointIn = 0,
|
||||||
}
|
.uiEndPointOut = 0,
|
||||||
for (dev = bus->devices; dev; dev = dev->next) {
|
};
|
||||||
if (connstring_decode_level > 2) {
|
usbbus_get_device(dev_addres, data.dev, data.pudh);
|
||||||
// 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
|
// Reset device
|
||||||
usbbus_reset(data.pudh);
|
libusb_reset_device(data.pudh);
|
||||||
|
|
||||||
// Retrieve end points
|
// Retrieve end points
|
||||||
acr122_usb_get_end_points(dev, &data);
|
usbbus_get_usb_endpoints(data.dev, &(data.uiEndPointIn), &(data.uiEndPointOut), &(data.uiMaxPacketSize));
|
||||||
// Claim interface
|
// Claim interface
|
||||||
int res = usbbus_claim_interface(data.pudh, 0);
|
int res = libusb_claim_interface(data.pudh, 0);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", usbbus_strerror(res));
|
log_put(LOG_GROUP,
|
||||||
usbbus_close(data.pudh);
|
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
|
// we failed to use the specified device
|
||||||
goto free_mem;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there are more than 0 alternative interfaces and claim the first one
|
// Check if there are more than 0 alternative interfaces and claim the first one
|
||||||
if (dev->config->interface->altsetting->bAlternateSetting > 0) {
|
// TODO would it not be better to iterate the alterative interfaces (and alternative settings) and check each one?
|
||||||
res = usbbus_set_interface_alt_setting(data.pudh, 0, 0);
|
if (usbbus_get_num_alternate_settings(data.dev, data.configIdx) > 0) {
|
||||||
|
res = libusb_set_interface_alt_setting(data.pudh, 0, 0);
|
||||||
if (res < 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));
|
log_put(LOG_GROUP,
|
||||||
usbbus_close(data.pudh);
|
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
|
// we failed to use the specified device
|
||||||
goto free_mem;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,21 +391,23 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
|
|||||||
pnd = nfc_device_new(context, connstring);
|
pnd = nfc_device_new(context, connstring);
|
||||||
if (!pnd) {
|
if (!pnd) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
acr122_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name));
|
acr122_usb_get_usb_device_name(data.dev, data.pudh, pnd->name, sizeof(pnd->name));
|
||||||
|
|
||||||
pnd->driver_data = malloc(sizeof(struct acr122_usb_data));
|
pnd->driver_data = malloc(sizeof(struct acr122_usb_data));
|
||||||
if (!pnd->driver_data) {
|
if (!pnd->driver_data) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto error;
|
nfc_device_free(pnd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
*DRIVER_DATA(pnd) = data;
|
*DRIVER_DATA(pnd) = data;
|
||||||
|
|
||||||
// Alloc and init chip's data
|
// Alloc and init chip's data
|
||||||
if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) {
|
if (pn53x_data_new(pnd, &acr122_usb_io) == NULL) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto error;
|
nfc_device_free(pnd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&(DRIVER_DATA(pnd)->tama_frame), acr122_usb_frame_template, sizeof(acr122_usb_frame_template));
|
memcpy(&(DRIVER_DATA(pnd)->tama_frame), acr122_usb_frame_template, sizeof(acr122_usb_frame_template));
|
||||||
@ -472,38 +416,30 @@ acr122_usb_open(const nfc_context *context, const nfc_connstring connstring)
|
|||||||
pnd->driver = &acr122_usb_driver;
|
pnd->driver = &acr122_usb_driver;
|
||||||
|
|
||||||
if (acr122_usb_init(pnd) < 0) {
|
if (acr122_usb_init(pnd) < 0) {
|
||||||
usbbus_close(data.pudh);
|
libusb_close(data.pudh);
|
||||||
goto error;
|
nfc_device_free(pnd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
DRIVER_DATA(pnd)->abort_flag = false;
|
DRIVER_DATA(pnd)->abort_flag = false;
|
||||||
goto free_mem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We ran out of devices before the index required
|
|
||||||
goto free_mem;
|
|
||||||
|
|
||||||
error:
|
|
||||||
// Free allocated structure on error.
|
|
||||||
nfc_device_free(pnd);
|
|
||||||
pnd = NULL;
|
|
||||||
free_mem:
|
|
||||||
free(desc.dirname);
|
|
||||||
free(desc.filename);
|
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
acr122_usb_close(nfc_device *pnd)
|
acr122_usb_close(nfc_device *pnd) {
|
||||||
{
|
|
||||||
acr122_usb_ack(pnd);
|
acr122_usb_ack(pnd);
|
||||||
pn53x_idle(pnd);
|
pn53x_idle(pnd);
|
||||||
|
|
||||||
int res;
|
int res = libusb_release_interface(DRIVER_DATA(pnd)->pudh, 0);
|
||||||
if ((res = usbbus_release_interface(DRIVER_DATA(pnd)->pudh, 0)) < 0) {
|
if (res < 0) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to release USB interface (%s)", usbbus_strerror(res));
|
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);
|
libusb_close(DRIVER_DATA(pnd)->pudh);
|
||||||
pn53x_data_free(pnd);
|
pn53x_data_free(pnd);
|
||||||
nfc_device_free(pnd);
|
nfc_device_free(pnd);
|
||||||
}
|
}
|
||||||
@ -513,8 +449,7 @@ acr122_usb_close(nfc_device *pnd)
|
|||||||
uint32_t htole32(uint32_t u32);
|
uint32_t htole32(uint32_t u32);
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
htole32(uint32_t u32)
|
htole32(uint32_t u32) {
|
||||||
{
|
|
||||||
union {
|
union {
|
||||||
uint8_t arr[4];
|
uint8_t arr[4];
|
||||||
uint32_t u32;
|
uint32_t u32;
|
||||||
@ -529,8 +464,13 @@ htole32(uint32_t u32)
|
|||||||
#endif /* !defined(htole32) */
|
#endif /* !defined(htole32) */
|
||||||
|
|
||||||
static int
|
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)
|
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))
|
if (data_len > sizeof(DRIVER_DATA(pnd)->apdu_frame.apdu_payload))
|
||||||
return NFC_EINVARG;
|
return NFC_EINVARG;
|
||||||
if ((data == NULL) && (data_len != 0))
|
if ((data == NULL) && (data_len != 0))
|
||||||
@ -552,8 +492,7 @@ acr122_build_frame_from_apdu(nfc_device *pnd, const uint8_t ins, const uint8_t p
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
acr122_build_frame_from_tama(nfc_device *pnd, const uint8_t *tama, const size_t tama_len)
|
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))
|
if (tama_len > sizeof(DRIVER_DATA(pnd)->tama_frame.tama_payload))
|
||||||
return NFC_EINVARG;
|
return NFC_EINVARG;
|
||||||
|
|
||||||
@ -564,15 +503,15 @@ acr122_build_frame_from_tama(nfc_device *pnd, const uint8_t *tama, const size_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
acr122_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout)
|
acr122_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout) {
|
||||||
{
|
|
||||||
int res;
|
int res;
|
||||||
if ((res = acr122_build_frame_from_tama(pnd, pbtData, szData)) < 0) {
|
if ((res = acr122_build_frame_from_tama(pnd, pbtData, szData)) < 0) {
|
||||||
pnd->last_error = NFC_EINVARG;
|
pnd->last_error = NFC_EINVARG;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->tama_frame), res, timeout)) < 0) {
|
if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) &(DRIVER_DATA(pnd)->tama_frame), res, timeout))
|
||||||
|
< 0) {
|
||||||
pnd->last_error = res;
|
pnd->last_error = res;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
@ -580,9 +519,9 @@ acr122_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define USBBUS_TIMEOUT_PER_PASS 200
|
#define USBBUS_TIMEOUT_PER_PASS 200
|
||||||
|
|
||||||
static int
|
static int
|
||||||
acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout)
|
acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout) {
|
||||||
{
|
|
||||||
off_t offset = 0;
|
off_t offset = 0;
|
||||||
|
|
||||||
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
|
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
|
||||||
@ -594,7 +533,7 @@ acr122_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, co
|
|||||||
*/
|
*/
|
||||||
int usbbus_timeout;
|
int usbbus_timeout;
|
||||||
int remaining_time = timeout;
|
int remaining_time = timeout;
|
||||||
read:
|
read:
|
||||||
if (timeout == USBBUS_INFINITE_TIMEOUT) {
|
if (timeout == USBBUS_INFINITE_TIMEOUT) {
|
||||||
usbbus_timeout = USBBUS_TIMEOUT_PER_PASS;
|
usbbus_timeout = USBBUS_TIMEOUT_PER_PASS;
|
||||||
} else {
|
} else {
|
||||||
@ -645,17 +584,35 @@ read:
|
|||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
if (abtRxBuf[10] != SW1_More_Data_Available) {
|
if (abtRxBuf[10] != SW1_More_Data_Available) {
|
||||||
if ((abtRxBuf[10] == SW1_Warning_with_NV_changed) && (abtRxBuf[11] == PN53x_Specific_Application_Level_Error_Code)) {
|
if ((abtRxBuf[10] == SW1_Warning_with_NV_changed)
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 has detected an error at the application level");
|
&& (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)) {
|
} 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");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "PN532 didn't reply");
|
||||||
} else {
|
} else {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unexpected Status Word (SW1: %02x SW2: %02x)", abtRxBuf[10], abtRxBuf[11]);
|
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;
|
pnd->last_error = NFC_EIO;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
res = acr122_usb_send_apdu(pnd, APDU_GetAdditionnalData, 0x00, 0x00, NULL, 0, abtRxBuf[11], abtRxBuf, sizeof(abtRxBuf));
|
res = acr122_usb_send_apdu(pnd,
|
||||||
|
APDU_GetAdditionnalData,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
abtRxBuf[11],
|
||||||
|
abtRxBuf,
|
||||||
|
sizeof(abtRxBuf));
|
||||||
if (res == NFC_ETIMEOUT) {
|
if (res == NFC_ETIMEOUT) {
|
||||||
if (DRIVER_DATA(pnd)->abort_flag) {
|
if (DRIVER_DATA(pnd)->abort_flag) {
|
||||||
DRIVER_DATA(pnd)->abort_flag = false;
|
DRIVER_DATA(pnd)->abort_flag = false;
|
||||||
@ -684,7 +641,11 @@ read:
|
|||||||
// 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)
|
// 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++];
|
len = abtRxBuf[offset++];
|
||||||
if ((abtRxBuf[offset] != 0x00) && (abtRxBuf[offset + 1] != 0x00) && (abtRxBuf[offset + 2] != 0x00)) {
|
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.");
|
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;
|
pnd->last_error = NFC_EIO;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
@ -695,10 +656,16 @@ read:
|
|||||||
pnd->last_error = NFC_EIO;
|
pnd->last_error = NFC_EIO;
|
||||||
return pnd->last_error;
|
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).
|
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) {
|
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);
|
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;
|
pnd->last_error = NFC_EOVFLOW;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
@ -729,15 +696,16 @@ read:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
acr122_usb_ack(nfc_device *pnd)
|
acr122_usb_ack(nfc_device *pnd) {
|
||||||
{
|
|
||||||
(void) pnd;
|
(void) pnd;
|
||||||
int res = 0;
|
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
|
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");
|
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)
|
if ((res = acr122_build_frame_from_tama(pnd, acr122_ack_frame, sizeof(acr122_ack_frame))) < 0)
|
||||||
return res;
|
return res;
|
||||||
if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) & (DRIVER_DATA(pnd)->tama_frame), res, 1000)) < 0)
|
if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd), (unsigned char *) &(DRIVER_DATA(pnd)->tama_frame), res, 1000))
|
||||||
|
< 0)
|
||||||
return res;
|
return res;
|
||||||
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
|
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
|
||||||
res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000);
|
res = acr122_usb_bulk_read(DRIVER_DATA(pnd), abtRxBuf, sizeof(abtRxBuf), 1000);
|
||||||
@ -746,12 +714,20 @@ acr122_usb_ack(nfc_device *pnd)
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
acr122_usb_send_apdu(nfc_device *pnd,
|
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,
|
const uint8_t ins,
|
||||||
uint8_t *out, const size_t out_size)
|
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;
|
int res;
|
||||||
size_t frame_len = acr122_build_frame_from_apdu(pnd, ins, p1, p2, data, data_len, le);
|
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)
|
if ((res = acr122_usb_bulk_write(DRIVER_DATA(pnd),
|
||||||
|
(unsigned char *) &(DRIVER_DATA(pnd)->apdu_frame),
|
||||||
|
frame_len,
|
||||||
|
1000)) < 0)
|
||||||
return res;
|
return res;
|
||||||
if ((res = acr122_usb_bulk_read(DRIVER_DATA(pnd), out, out_size, 1000)) < 0)
|
if ((res = acr122_usb_bulk_read(DRIVER_DATA(pnd), out, out_size, 1000)) < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -759,8 +735,7 @@ acr122_usb_send_apdu(nfc_device *pnd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
acr122_usb_init(nfc_device *pnd)
|
acr122_usb_init(nfc_device *pnd) {
|
||||||
{
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int i;
|
int i;
|
||||||
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
|
uint8_t abtRxBuf[255 + sizeof(struct ccid_header)];
|
||||||
@ -819,8 +794,7 @@ acr122_usb_init(nfc_device *pnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
acr122_usb_abort_command(nfc_device *pnd)
|
acr122_usb_abort_command(nfc_device *pnd) {
|
||||||
{
|
|
||||||
DRIVER_DATA(pnd)->abort_flag = true;
|
DRIVER_DATA(pnd)->abort_flag = true;
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
|
|
||||||
#endif // HAVE_CONFIG_H
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -42,11 +43,12 @@ Thanks to d18c7db and Okko for example code
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
#include <libusb.h>
|
||||||
#include "nfc-internal.h"
|
#include "nfc-internal.h"
|
||||||
#include "buses/usbbus.h"
|
#include "buses/usbbus.h"
|
||||||
#include "chips/pn53x.h"
|
#include "chips/pn53x.h"
|
||||||
@ -76,11 +78,13 @@ typedef enum {
|
|||||||
|
|
||||||
// Internal data struct
|
// Internal data struct
|
||||||
struct pn53x_usb_data {
|
struct pn53x_usb_data {
|
||||||
usbbus_device_handle *pudh;
|
libusb_device * dev;
|
||||||
|
libusb_device_handle *pudh;
|
||||||
|
uint8_t configIdx;
|
||||||
pn53x_usb_model model;
|
pn53x_usb_model model;
|
||||||
uint32_t uiEndPointIn;
|
uint8_t uiEndPointIn;
|
||||||
uint32_t uiEndPointOut;
|
uint8_t uiEndPointOut;
|
||||||
uint32_t uiMaxPacketSize;
|
uint16_t uiMaxPacketSize;
|
||||||
volatile bool abort_flag;
|
volatile bool abort_flag;
|
||||||
bool possibly_corrupted_usbdesc;
|
bool possibly_corrupted_usbdesc;
|
||||||
};
|
};
|
||||||
@ -89,37 +93,43 @@ struct pn53x_usb_data {
|
|||||||
const struct pn53x_io pn53x_usb_io;
|
const struct pn53x_io pn53x_usb_io;
|
||||||
|
|
||||||
// Prototypes
|
// 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);
|
int pn53x_usb_init(nfc_device *pnd);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_bulk_read(struct pn53x_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout)
|
pn53x_usb_bulk_read(struct pn53x_usb_data *data, uint8_t abtRx[], const size_t szRx, const int timeout) {
|
||||||
{
|
|
||||||
int actual_length;
|
int actual_length;
|
||||||
int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointIn, (char *) abtRx, szRx, &actual_length, timeout);
|
int res = libusb_bulk_transfer(data->pudh, data->uiEndPointIn & 0xff, abtRx, szRx, &actual_length, timeout);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, actual_length);
|
LOG_HEX(NFC_LOG_GROUP_COM, "RX", abtRx, actual_length);
|
||||||
res = actual_length;
|
res = actual_length;
|
||||||
} else {
|
} else {
|
||||||
if (res != USBBUS_ERROR_TIMEOUT)
|
if (res != LIBUSB_ERROR_TIMEOUT)
|
||||||
log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to read from USB (%s)", usbbus_strerror(res));
|
log_put(NFC_LOG_GROUP_COM,
|
||||||
|
LOG_CATEGORY,
|
||||||
|
NFC_LOG_PRIORITY_ERROR,
|
||||||
|
"Unable to read from USB (%s)",
|
||||||
|
libusb_strerror(res));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_bulk_write(struct pn53x_usb_data *data, uint8_t abtTx[], const size_t szTx, const int timeout)
|
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);
|
LOG_HEX(NFC_LOG_GROUP_COM, "TX", abtTx, szTx);
|
||||||
int actual_length;
|
int actual_length;
|
||||||
int res = usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, (char *) abtTx, szTx, &actual_length, timeout);
|
int res = libusb_bulk_transfer(data->pudh, data->uiEndPointOut & 0xff, abtTx, szTx, &actual_length, timeout);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
// HACK This little hack is a well know problem of USB, see http://www.libusb.org/ticket/6 for more details
|
// 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)) {
|
if ((actual_length > 0) && ((actual_length % data->uiMaxPacketSize) == 0)) {
|
||||||
usbbus_bulk_transfer(data->pudh, data->uiEndPointOut, "\0", 0, &actual_length, timeout);
|
libusb_bulk_transfer(data->pudh, data->uiEndPointOut & 0xff, EMPTY_STRING, 0, &actual_length, timeout);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log_put(NFC_LOG_GROUP_COM, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to write to USB (%s)", usbbus_strerror(res));
|
log_put(NFC_LOG_GROUP_COM,
|
||||||
|
LOG_CATEGORY,
|
||||||
|
NFC_LOG_PRIORITY_ERROR,
|
||||||
|
"Unable to write to USB (%s)",
|
||||||
|
libusb_strerror(res));
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -136,15 +146,17 @@ struct pn53x_usb_supported_device {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = {
|
const struct pn53x_usb_supported_device pn53x_usb_supported_devices[] = {
|
||||||
{ 0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40 },
|
{0x04CC, 0x0531, NXP_PN531, "Philips / PN531", 0x84, 0x04, 0x40},
|
||||||
{ 0x04CC, 0x2533, NXP_PN533, "NXP / PN533", 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, 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
|
{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 },
|
{0x054c, 0x0193, SONY_PN531, "Sony / PN531", 0x84, 0x04, 0x40},
|
||||||
{ 0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40 },
|
{0x1FD3, 0x0608, ASK_LOGO, "ASK / LoGO", 0x84, 0x04, 0x40},
|
||||||
{ 0x054C, 0x02E1, SONY_RCS360, "Sony / FeliCa S360 [PaSoRi]", 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
|
// PN533 USB descriptors backup buffers
|
||||||
|
|
||||||
const uint8_t btXramUsbDesc_scl3711[] = {
|
const uint8_t btXramUsbDesc_scl3711[] = {
|
||||||
@ -172,21 +184,20 @@ const uint8_t btXramUsbDesc_asklogo[] = {
|
|||||||
0x00,
|
0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void pn533_fix_usbdesc(nfc_device *pnd)
|
static void pn533_fix_usbdesc(nfc_device *pnd) {
|
||||||
{
|
|
||||||
// PN533 USB descriptors may have been corrupted by large commands/responses
|
// PN533 USB descriptors may have been corrupted by large commands/responses
|
||||||
// so they need to be restored before closing usb connection.
|
// so they need to be restored before closing usb connection.
|
||||||
// cf PN5331B3HNC270 Release Note
|
// cf PN5331B3HNC270 Release Note
|
||||||
uint32_t szXramUsbDesc = 0;
|
uint32_t szXramUsbDesc = 0;
|
||||||
uint8_t *btXramUsbDesc = NULL;
|
uint8_t *btXramUsbDesc = NULL;
|
||||||
if (DRIVER_DATA(pnd)->model == NXP_PN533) {
|
if (DRIVER_DATA(pnd)->model == NXP_PN533) {
|
||||||
btXramUsbDesc = (uint8_t *)btXramUsbDesc_nxppn533;
|
btXramUsbDesc = (uint8_t *) btXramUsbDesc_nxppn533;
|
||||||
szXramUsbDesc = sizeof(btXramUsbDesc_nxppn533);
|
szXramUsbDesc = sizeof(btXramUsbDesc_nxppn533);
|
||||||
} else if (DRIVER_DATA(pnd)->model == SCM_SCL3711) {
|
} else if (DRIVER_DATA(pnd)->model == SCM_SCL3711) {
|
||||||
btXramUsbDesc = (uint8_t *)btXramUsbDesc_scl3711;
|
btXramUsbDesc = (uint8_t *) btXramUsbDesc_scl3711;
|
||||||
szXramUsbDesc = sizeof(btXramUsbDesc_scl3711);
|
szXramUsbDesc = sizeof(btXramUsbDesc_scl3711);
|
||||||
} else if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
|
} else if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
|
||||||
btXramUsbDesc = (uint8_t *)btXramUsbDesc_asklogo;
|
btXramUsbDesc = (uint8_t *) btXramUsbDesc_asklogo;
|
||||||
szXramUsbDesc = sizeof(btXramUsbDesc_asklogo);
|
szXramUsbDesc = sizeof(btXramUsbDesc_asklogo);
|
||||||
}
|
}
|
||||||
#define MAXSZXRAMUSBDESC 61
|
#define MAXSZXRAMUSBDESC 61
|
||||||
@ -216,8 +227,8 @@ static void pn533_fix_usbdesc(nfc_device *pnd)
|
|||||||
#endif
|
#endif
|
||||||
// Abuse the overflow bug to restore USB descriptors in one go
|
// 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");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_INFO, "%s", "Fixing USB descriptors corruption");
|
||||||
uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = { GetFirmwareVersion };
|
uint8_t abtCmdWR[19 + MAXSZXRAMUSBDESC] = {GetFirmwareVersion};
|
||||||
for (uint8_t i = 0; i < szXramUsbDesc; i++) {
|
for (size_t i = 0; i < szXramUsbDesc; i++) {
|
||||||
abtCmdWR[i + 19] = btXramUsbDesc[i];
|
abtCmdWR[i + 19] = btXramUsbDesc[i];
|
||||||
}
|
}
|
||||||
size_t szCmdWR = sizeof(abtCmdWR);
|
size_t szCmdWR = sizeof(abtCmdWR);
|
||||||
@ -229,8 +240,7 @@ static void pn533_fix_usbdesc(nfc_device *pnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static pn53x_usb_model
|
static pn53x_usb_model
|
||||||
pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id)
|
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++) {
|
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) &&
|
if ((vendor_id == pn53x_usb_supported_devices[n].vendor_id) &&
|
||||||
(product_id == pn53x_usb_supported_devices[n].product_id))
|
(product_id == pn53x_usb_supported_devices[n].product_id))
|
||||||
@ -241,11 +251,13 @@ pn53x_usb_get_device_model(uint16_t vendor_id, uint16_t product_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
pn53x_usb_get_end_points_default(struct usbbus_device *dev, struct pn53x_usb_data *data)
|
pn53x_usb_get_end_points_default(struct pn53x_usb_data *data) {
|
||||||
{
|
struct libusb_device_descriptor descriptor;
|
||||||
|
libusb_get_device_descriptor(data->dev, &descriptor);
|
||||||
|
|
||||||
for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) {
|
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) &&
|
if ((descriptor.idVendor == pn53x_usb_supported_devices[n].vendor_id) &&
|
||||||
(dev->descriptor.idProduct == pn53x_usb_supported_devices[n].product_id)) {
|
(descriptor.idProduct == pn53x_usb_supported_devices[n].product_id)) {
|
||||||
if (pn53x_usb_supported_devices[n].uiMaxPacketSize != 0) {
|
if (pn53x_usb_supported_devices[n].uiMaxPacketSize != 0) {
|
||||||
data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn;
|
data->uiEndPointIn = pn53x_usb_supported_devices[n].uiEndPointIn;
|
||||||
data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut;
|
data->uiEndPointOut = pn53x_usb_supported_devices[n].uiEndPointOut;
|
||||||
@ -261,126 +273,30 @@ pn53x_usb_get_end_points_default(struct usbbus_device *dev, struct pn53x_usb_dat
|
|||||||
|
|
||||||
int pn53x_usb_ack(nfc_device *pnd);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t
|
static size_t
|
||||||
pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len)
|
pn53x_usb_scan(const nfc_context *context, nfc_connstring connstrings[], const size_t connstrings_len) {
|
||||||
{
|
struct usbbus_device devices[num_pn53x_usb_supported_devices];
|
||||||
(void)context;
|
for (size_t i = 0; i < num_pn53x_usb_supported_devices; i++) {
|
||||||
|
devices[i].product_id = pn53x_usb_supported_devices[i].product_id;
|
||||||
usbbus_prepare();
|
devices[i].vendor_id = pn53x_usb_supported_devices[i].vendor_id;
|
||||||
|
devices[i].name = pn53x_usb_supported_devices[i].name;
|
||||||
size_t device_found = 0;
|
devices[i].max_packet_size = pn53x_usb_supported_devices[i].uiMaxPacketSize;
|
||||||
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) {
|
return usbbus_usb_scan((char **) connstrings, connstrings_len, devices, num_pn53x_usb_supported_devices, PN53X_USB_DRIVER_NAME);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pn53x_usb_descriptor {
|
|
||||||
char *dirname;
|
|
||||||
char *filename;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pn53x_usb_get_usb_device_name(struct usbbus_device *dev, usbbus_device_handle *udev, char *buffer, size_t len)
|
pn53x_usb_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
|
||||||
{
|
|
||||||
*buffer = '\0';
|
*buffer = '\0';
|
||||||
|
|
||||||
if (dev->descriptor.iManufacturer || dev->descriptor.iProduct) {
|
usbbus_get_usb_device_name(dev, udev, buffer, len);
|
||||||
if (udev) {
|
uint16_t vendor_id = usbbus_get_vendor_id(dev);
|
||||||
usbbus_get_string_simple(udev, dev->descriptor.iManufacturer, buffer, len);
|
uint16_t product_id = usbbus_get_product_id(dev);
|
||||||
if (strlen(buffer) > 0)
|
|
||||||
strcpy(buffer + strlen(buffer), " / ");
|
|
||||||
usbbus_get_string_simple(udev, dev->descriptor.iProduct, buffer + strlen(buffer), len - strlen(buffer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*buffer) {
|
if (!*buffer) {
|
||||||
for (size_t n = 0; n < sizeof(pn53x_usb_supported_devices) / sizeof(struct pn53x_usb_supported_device); n++) {
|
for (size_t n = 0; n < num_pn53x_usb_supported_devices; n++) {
|
||||||
if ((pn53x_usb_supported_devices[n].vendor_id == dev->descriptor.idVendor) &&
|
if ((pn53x_usb_supported_devices[n].vendor_id == vendor_id) &&
|
||||||
(pn53x_usb_supported_devices[n].product_id == dev->descriptor.idProduct)) {
|
(pn53x_usb_supported_devices[n].product_id == product_id)) {
|
||||||
strncpy(buffer, pn53x_usb_supported_devices[n].name, len);
|
strncpy(buffer, pn53x_usb_supported_devices[n].name, len);
|
||||||
buffer[len - 1] = '\0';
|
buffer[len - 1] = '\0';
|
||||||
return true;
|
return true;
|
||||||
@ -392,109 +308,120 @@ pn53x_usb_get_usb_device_name(struct usbbus_device *dev, usbbus_device_handle *u
|
|||||||
}
|
}
|
||||||
|
|
||||||
static nfc_device *
|
static nfc_device *
|
||||||
pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
|
pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring) {
|
||||||
{
|
|
||||||
nfc_device *pnd = NULL;
|
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);
|
char *dev_address_str;
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%d element(s) have been decoded from \"%s\"", connstring_decode_level, connstring);
|
char *config_idx_str;
|
||||||
if (connstring_decode_level < 1) {
|
int connstring_decode_level =
|
||||||
goto free_mem;
|
connstring_decode(connstring, PN53X_USB_DRIVER_NAME, "usb", &dev_address_str, &config_idx_str);
|
||||||
|
log_put(LOG_GROUP,
|
||||||
|
LOG_CATEGORY,
|
||||||
|
NFC_LOG_PRIORITY_DEBUG,
|
||||||
|
"%d element(s) have been decoded from \"%s\"",
|
||||||
|
connstring_decode_level,
|
||||||
|
connstring);
|
||||||
|
// At least the driver and the dev address need to be decoded
|
||||||
|
if (connstring_decode_level < 2) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t dev_addres = atoi(dev_address_str);
|
||||||
|
uint8_t config_idx = atoi(config_idx_str);
|
||||||
|
|
||||||
|
usbbus_prepare();
|
||||||
|
|
||||||
|
|
||||||
struct pn53x_usb_data data = {
|
struct pn53x_usb_data data = {
|
||||||
|
.dev = NULL,
|
||||||
.pudh = NULL,
|
.pudh = NULL,
|
||||||
|
.configIdx = config_idx,
|
||||||
.uiEndPointIn = 0,
|
.uiEndPointIn = 0,
|
||||||
.uiEndPointOut = 0,
|
.uiEndPointOut = 0,
|
||||||
.possibly_corrupted_usbdesc = false,
|
.possibly_corrupted_usbdesc = false,
|
||||||
};
|
};
|
||||||
struct usbbus_bus *bus;
|
|
||||||
struct usbbus_device *dev;
|
|
||||||
|
|
||||||
usbbus_prepare();
|
usbbus_get_device(dev_addres, data.dev, data.pudh);
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
//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
|
// Retrieve end points, using hardcoded defaults if available
|
||||||
// or using the descriptors otherwise.
|
// or using the descriptors otherwise.
|
||||||
if (pn53x_usb_get_end_points_default(dev, &data) == false) {
|
if (!pn53x_usb_get_end_points_default(&data)) {
|
||||||
pn53x_usb_get_end_points(dev, &data);
|
// Find transfer endpoints for bulk transfers
|
||||||
|
usbbus_get_usb_endpoints(data.dev, &(data.uiEndPointIn), &(data.uiEndPointOut), &(data.uiMaxPacketSize));
|
||||||
|
|
||||||
}
|
}
|
||||||
// Set configuration
|
// Set configuration
|
||||||
int res = usbbus_set_configuration(data.pudh, 1);
|
int res = libusb_set_configuration(data.pudh, data.configIdx);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set USB configuration (%s)", usbbus_strerror(res));
|
log_put(LOG_GROUP,
|
||||||
if (res == USBBUS_ERROR_ACCESS) {
|
LOG_CATEGORY,
|
||||||
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);
|
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);
|
||||||
}
|
}
|
||||||
usbbus_close(data.pudh);
|
libusb_close(data.pudh);
|
||||||
// we failed to use the specified device
|
// we failed to use the specified device
|
||||||
goto free_mem;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = usbbus_claim_interface(data.pudh, 0);
|
res = libusb_claim_interface(data.pudh, 0);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to claim USB interface (%s)", usbbus_strerror(res));
|
log_put(LOG_GROUP,
|
||||||
usbbus_close(data.pudh);
|
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
|
// we failed to use the specified device
|
||||||
goto free_mem;
|
return NULL;
|
||||||
}
|
}
|
||||||
data.model = pn53x_usb_get_device_model(dev->descriptor.idVendor, dev->descriptor.idProduct);
|
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
|
// Allocate memory for the device info and specification, fill it and return the info
|
||||||
pnd = nfc_device_new(context, connstring);
|
pnd = nfc_device_new(context, connstring);
|
||||||
if (!pnd) {
|
if (!pnd) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
pn53x_usb_get_usb_device_name(dev, data.pudh, pnd->name, sizeof(pnd->name));
|
pn53x_usb_get_usb_device_name(data.dev, data.pudh, pnd->name, sizeof(pnd->name));
|
||||||
|
|
||||||
pnd->driver_data = malloc(sizeof(struct pn53x_usb_data));
|
pnd->driver_data = malloc(sizeof(struct pn53x_usb_data));
|
||||||
if (!pnd->driver_data) {
|
if (!pnd->driver_data) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto error;
|
nfc_device_free(pnd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
*DRIVER_DATA(pnd) = data;
|
*DRIVER_DATA(pnd) = data;
|
||||||
|
|
||||||
// Alloc and init chip's data
|
// Alloc and init chip's data
|
||||||
if (pn53x_data_new(pnd, &pn53x_usb_io) == NULL) {
|
if (pn53x_data_new(pnd, &pn53x_usb_io) == NULL) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto error;
|
nfc_device_free(pnd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (DRIVER_DATA(pnd)->model) {
|
switch (DRIVER_DATA(pnd)->model) {
|
||||||
// empirical tuning
|
// empirical tuning
|
||||||
case ASK_LOGO:
|
case ASK_LOGO:CHIP_DATA(pnd)->timer_correction = 50;
|
||||||
CHIP_DATA(pnd)->timer_correction = 50;
|
|
||||||
CHIP_DATA(pnd)->progressive_field = true;
|
CHIP_DATA(pnd)->progressive_field = true;
|
||||||
break;
|
break;
|
||||||
case SCM_SCL3711:
|
case SCM_SCL3711:
|
||||||
case SCM_SCL3712:
|
case SCM_SCL3712:
|
||||||
case NXP_PN533:
|
case NXP_PN533:CHIP_DATA(pnd)->timer_correction = 46;
|
||||||
CHIP_DATA(pnd)->timer_correction = 46;
|
|
||||||
break;
|
break;
|
||||||
case NXP_PN531:
|
case NXP_PN531:CHIP_DATA(pnd)->timer_correction = 50;
|
||||||
CHIP_DATA(pnd)->timer_correction = 50;
|
|
||||||
break;
|
break;
|
||||||
case SONY_PN531:
|
case SONY_PN531:CHIP_DATA(pnd)->timer_correction = 54;
|
||||||
CHIP_DATA(pnd)->timer_correction = 54;
|
|
||||||
break;
|
break;
|
||||||
case SONY_RCS360:
|
case SONY_RCS360:
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
@ -509,29 +436,16 @@ pn53x_usb_open(const nfc_context *context, const nfc_connstring connstring)
|
|||||||
// HACK2: Then send a GetFirmware command to resync USB toggle bit between host & device
|
// 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
|
// 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) {
|
if (pn53x_usb_init(pnd) < 0) {
|
||||||
usbbus_close(data.pudh);
|
libusb_close(data.pudh);
|
||||||
goto error;
|
nfc_device_free(pnd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
DRIVER_DATA(pnd)->abort_flag = false;
|
DRIVER_DATA(pnd)->abort_flag = false;
|
||||||
goto free_mem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We ran out of devices before the index required
|
|
||||||
goto free_mem;
|
|
||||||
|
|
||||||
error:
|
|
||||||
// Free allocated structure on error.
|
|
||||||
nfc_device_free(pnd);
|
|
||||||
pnd = NULL;
|
|
||||||
free_mem:
|
|
||||||
free(desc.dirname);
|
|
||||||
free(desc.filename);
|
|
||||||
return pnd;
|
return pnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pn53x_usb_close(nfc_device *pnd)
|
pn53x_usb_close(nfc_device *pnd) {
|
||||||
{
|
|
||||||
pn53x_usb_ack(pnd);
|
pn53x_usb_ack(pnd);
|
||||||
|
|
||||||
if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
|
if (DRIVER_DATA(pnd)->model == ASK_LOGO) {
|
||||||
@ -540,17 +454,13 @@ pn53x_usb_close(nfc_device *pnd)
|
|||||||
pn53x_write_register(pnd, PN53X_SFR_P3, 0xFF, _BV(P30) | _BV(P31) | _BV(P32) | _BV(P33) | _BV(P35));
|
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)
|
if (DRIVER_DATA(pnd)->possibly_corrupted_usbdesc) {
|
||||||
pn533_fix_usbdesc(pnd);
|
pn533_fix_usbdesc(pnd);
|
||||||
|
}
|
||||||
|
|
||||||
pn53x_idle(pnd);
|
pn53x_idle(pnd);
|
||||||
|
|
||||||
int res;
|
libusb_close(DRIVER_DATA(pnd)->pudh);
|
||||||
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);
|
pn53x_data_free(pnd);
|
||||||
nfc_device_free(pnd);
|
nfc_device_free(pnd);
|
||||||
}
|
}
|
||||||
@ -558,9 +468,8 @@ pn53x_usb_close(nfc_device *pnd)
|
|||||||
#define PN53X_USB_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
|
#define PN53X_USB_BUFFER_LEN (PN53x_EXTENDED_FRAME__DATA_MAX_LEN + PN53x_EXTENDED_FRAME__OVERHEAD)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, const int timeout)
|
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"
|
||||||
uint8_t abtFrame[PN53X_USB_BUFFER_LEN] = { 0x00, 0x00, 0xff }; // Every packet must start with "00 00 ff"
|
|
||||||
size_t szFrame = 0;
|
size_t szFrame = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
@ -593,7 +502,10 @@ pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, con
|
|||||||
// pn53x_usb_receive()) will be able to retrieve the correct response
|
// pn53x_usb_receive()) will be able to retrieve the correct response
|
||||||
// packet.
|
// packet.
|
||||||
// FIXME Sony reader is also affected by this bug but NACK is not supported
|
// 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) {
|
if ((res = pn53x_usb_bulk_write(DRIVER_DATA(pnd),
|
||||||
|
(uint8_t *) pn53x_nack_frame,
|
||||||
|
sizeof(pn53x_nack_frame),
|
||||||
|
timeout)) < 0) {
|
||||||
pnd->last_error = res;
|
pnd->last_error = res;
|
||||||
// try to interrupt current device state
|
// try to interrupt current device state
|
||||||
pn53x_usb_ack(pnd);
|
pn53x_usb_ack(pnd);
|
||||||
@ -604,9 +516,9 @@ pn53x_usb_send(nfc_device *pnd, const uint8_t *pbtData, const size_t szData, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define USBBUS_TIMEOUT_PER_PASS 200
|
#define USBBUS_TIMEOUT_PER_PASS 200
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout)
|
pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, const int timeout) {
|
||||||
{
|
|
||||||
size_t len;
|
size_t len;
|
||||||
off_t offset = 0;
|
off_t offset = 0;
|
||||||
|
|
||||||
@ -619,7 +531,7 @@ pn53x_usb_receive(nfc_device *pnd, uint8_t *pbtData, const size_t szDataLen, con
|
|||||||
*/
|
*/
|
||||||
int usbbus_timeout;
|
int usbbus_timeout;
|
||||||
int remaining_time = timeout;
|
int remaining_time = timeout;
|
||||||
read:
|
read:
|
||||||
if (timeout == USBBUS_INFINITE_TIMEOUT) {
|
if (timeout == USBBUS_INFINITE_TIMEOUT) {
|
||||||
usbbus_timeout = USBBUS_TIMEOUT_PER_PASS;
|
usbbus_timeout = USBBUS_TIMEOUT_PER_PASS;
|
||||||
} else {
|
} else {
|
||||||
@ -635,7 +547,7 @@ read:
|
|||||||
|
|
||||||
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 (res == LIBUSB_ERROR_TIMEOUT) {
|
||||||
if (DRIVER_DATA(pnd)->abort_flag) {
|
if (DRIVER_DATA(pnd)->abort_flag) {
|
||||||
DRIVER_DATA(pnd)->abort_flag = false;
|
DRIVER_DATA(pnd)->abort_flag = false;
|
||||||
pn53x_usb_ack(pnd);
|
pn53x_usb_ack(pnd);
|
||||||
@ -653,7 +565,7 @@ read:
|
|||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t pn53x_preamble[3] = { 0x00, 0x00, 0xff };
|
const uint8_t pn53x_preamble[3] = {0x00, 0x00, 0xff};
|
||||||
if (0 != (memcmp(abtRxBuf, pn53x_preamble, 3))) {
|
if (0 != (memcmp(abtRxBuf, pn53x_preamble, 3))) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Frame preamble+start code mismatch");
|
||||||
pnd->last_error = NFC_EIO;
|
pnd->last_error = NFC_EIO;
|
||||||
@ -694,7 +606,12 @@ read:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len > szDataLen) {
|
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);
|
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;
|
pnd->last_error = NFC_EIO;
|
||||||
return pnd->last_error;
|
return pnd->last_error;
|
||||||
}
|
}
|
||||||
@ -742,24 +659,22 @@ read:
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pn53x_usb_ack(nfc_device *pnd)
|
pn53x_usb_ack(nfc_device *pnd) {
|
||||||
{
|
|
||||||
return pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *) pn53x_ack_frame, sizeof(pn53x_ack_frame), 1000);
|
return pn53x_usb_bulk_write(DRIVER_DATA(pnd), (uint8_t *) pn53x_ack_frame, sizeof(pn53x_ack_frame), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pn53x_usb_init(nfc_device *pnd)
|
pn53x_usb_init(nfc_device *pnd) {
|
||||||
{
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
// Sometimes PN53x USB doesn't reply ACK one the first frame, so we need to send a dummy one...
|
// 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:
|
//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 };
|
const uint8_t abtCmd[] = {GetFirmwareVersion};
|
||||||
pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1);
|
pn53x_transceive(pnd, abtCmd, sizeof(abtCmd), NULL, 0, -1);
|
||||||
// ...and we don't care about error
|
// ...and we don't care about error
|
||||||
pnd->last_error = 0;
|
pnd->last_error = 0;
|
||||||
if (SONY_RCS360 == DRIVER_DATA(pnd)->model) {
|
if (SONY_RCS360 == DRIVER_DATA(pnd)->model) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "SONY RC-S360 initialization.");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "SONY RC-S360 initialization.");
|
||||||
const uint8_t abtCmd2[] = { 0x18, 0x01 };
|
const uint8_t abtCmd2[] = {0x18, 0x01};
|
||||||
pn53x_transceive(pnd, abtCmd2, sizeof(abtCmd2), NULL, 0, -1);
|
pn53x_transceive(pnd, abtCmd2, sizeof(abtCmd2), NULL, 0, -1);
|
||||||
pn53x_usb_ack(pnd);
|
pn53x_usb_ack(pnd);
|
||||||
}
|
}
|
||||||
@ -771,7 +686,10 @@ pn53x_usb_init(nfc_device *pnd)
|
|||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ASK LoGO initialization.");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%s", "ASK LoGO initialization.");
|
||||||
/* Internal registers */
|
/* Internal registers */
|
||||||
/* Disable 100mA current limit, Power on Secure IC (SVDD) */
|
/* 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);
|
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 */
|
/* 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);
|
pn53x_write_register(pnd, PN53X_REG_CIU_TxSel, 0xFF, 0x14);
|
||||||
|
|
||||||
@ -808,8 +726,7 @@ pn53x_usb_init(nfc_device *pnd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
|
pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable) {
|
||||||
{
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
if ((res = pn53x_set_property_bool(pnd, property, bEnable)) < 0)
|
if ((res = pn53x_set_property_bool(pnd, property, bEnable)) < 0)
|
||||||
return res;
|
return res;
|
||||||
@ -818,18 +735,16 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const
|
|||||||
case ASK_LOGO:
|
case ASK_LOGO:
|
||||||
if (NP_ACTIVATE_FIELD == property) {
|
if (NP_ACTIVATE_FIELD == property) {
|
||||||
/* Switch on/off LED2 and Progressive Field GPIO according to ACTIVATE_FIELD option */
|
/* 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");
|
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)
|
if (pn53x_write_register(pnd, PN53X_SFR_P3, _BV(P31) | _BV(P34), bEnable ? _BV(P34) : _BV(P31)) < 0)
|
||||||
return NFC_ECHIP;
|
return NFC_ECHIP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCM_SCL3711:
|
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:
|
case SCM_SCL3712:
|
||||||
if (NP_ACTIVATE_FIELD == property) {
|
if (NP_ACTIVATE_FIELD == property) {
|
||||||
// Switch on/off LED according to ACTIVATE_FIELD option
|
// Switch on/off LED according to ACTIVATE_FIELD option
|
||||||
@ -849,15 +764,15 @@ pn53x_usb_set_property_bool(nfc_device *pnd, const nfc_property property, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_abort_command(nfc_device *pnd)
|
pn53x_usb_abort_command(nfc_device *pnd) {
|
||||||
{
|
|
||||||
DRIVER_DATA(pnd)->abort_flag = true;
|
DRIVER_DATA(pnd)->abort_flag = true;
|
||||||
return NFC_SUCCESS;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pn53x_usb_get_supported_modulation(nfc_device *pnd, const nfc_mode mode, const nfc_modulation_type **const supported_mt)
|
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))
|
if ((DRIVER_DATA(pnd)->model != ASK_LOGO) || (mode != N_TARGET))
|
||||||
return pn53x_get_supported_modulation(pnd, mode, supported_mt);
|
return pn53x_get_supported_modulation(pnd, mode, supported_mt);
|
||||||
else // ASK_LOGO has no N_TARGET support
|
else // ASK_LOGO has no N_TARGET support
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user