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-2013 Philippe Teuwen
|
||||
* Copyright (C) 2012-2013 Ludovic Rousseau
|
||||
* Copyright (C) 2022 Kenspeckle
|
||||
* See AUTHORS file for a more comprehensive list of contributors.
|
||||
* Additional contributors of this file:
|
||||
*
|
||||
@ -24,634 +25,300 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file usbbus.c
|
||||
* @brief libusb 0.1 driver wrapper
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <libusb.h>
|
||||
#include <stdint.h>
|
||||
#include "usbbus.h"
|
||||
#include "log.h"
|
||||
#define LOG_CATEGORY "libnfc.buses.usbbus"
|
||||
|
||||
|
||||
#define LOG_CATEGORY "libnfc.bus.usbbus"
|
||||
#define LOG_GROUP NFC_LOG_GROUP_DRIVER
|
||||
|
||||
/*
|
||||
* This file embeds partially libusb-compat-0.1 by:
|
||||
* Copyright (C) 2008 Daniel Drake <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;
|
||||
|
||||
struct usbbus_bus *usb_busses = NULL;
|
||||
uint8_t get_usb_num_configs(struct libusb_device *dev);
|
||||
|
||||
static void _usb_finalize(void)
|
||||
{
|
||||
if (ctx) {
|
||||
libusb_exit(ctx);
|
||||
ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_init(void)
|
||||
{
|
||||
if (!ctx) {
|
||||
int r;
|
||||
r = libusb_init(&ctx);
|
||||
if (r < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
atexit(_usb_finalize);
|
||||
}
|
||||
}
|
||||
|
||||
static int find_busses(struct usbbus_bus **ret)
|
||||
{
|
||||
libusb_device **dev_list = NULL;
|
||||
struct usbbus_bus *busses = NULL;
|
||||
struct usbbus_bus *bus;
|
||||
int dev_list_len = 0;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
r = libusb_get_device_list(ctx, &dev_list);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
libusb_free_device_list(dev_list, 1);
|
||||
/* no buses */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* iterate over the device list, identifying the individual busses.
|
||||
* we use the location field of the usbbus_bus structure to store the
|
||||
* bus number. */
|
||||
|
||||
dev_list_len = r;
|
||||
for (i = 0; i < dev_list_len; i++) {
|
||||
libusb_device *dev = dev_list[i];
|
||||
uint8_t bus_num = libusb_get_bus_number(dev);
|
||||
|
||||
/* if we already know about it, continue */
|
||||
if (busses) {
|
||||
bus = busses;
|
||||
int found = 0;
|
||||
do {
|
||||
if (bus_num == bus->location) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
} while ((bus = bus->next) != NULL);
|
||||
if (found)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* add it to the list of busses */
|
||||
bus = malloc(sizeof(*bus));
|
||||
if (!bus)
|
||||
goto err;
|
||||
|
||||
memset(bus, 0, sizeof(*bus));
|
||||
bus->location = bus_num;
|
||||
snprintf(bus->dirname, USBBUS_PATH_MAX, "%03d", bus_num);
|
||||
LIST_ADD(busses, bus);
|
||||
}
|
||||
|
||||
libusb_free_device_list(dev_list, 1);
|
||||
*ret = busses;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
bus = busses;
|
||||
while (bus) {
|
||||
struct usbbus_bus *tbus = bus->next;
|
||||
free(bus);
|
||||
bus = tbus;
|
||||
}
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
static int usb_find_busses(void)
|
||||
{
|
||||
struct usbbus_bus *new_busses = NULL;
|
||||
struct usbbus_bus *bus;
|
||||
int changes = 0;
|
||||
int r;
|
||||
|
||||
/* libusb-1.0 initialization might have failed, but we can't indicate
|
||||
* this with libusb-0.1, so trap that situation here */
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
r = find_busses(&new_busses);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* walk through all busses we already know about, removing duplicates
|
||||
* from the new list. if we do not find it in the new list, the bus
|
||||
* has been removed. */
|
||||
|
||||
bus = usb_busses;
|
||||
while (bus) {
|
||||
struct usbbus_bus *tbus = bus->next;
|
||||
struct usbbus_bus *nbus = new_busses;
|
||||
int found = 0;
|
||||
|
||||
while (nbus) {
|
||||
struct usbbus_bus *tnbus = nbus->next;
|
||||
|
||||
if (bus->location == nbus->location) {
|
||||
LIST_DEL(new_busses, nbus);
|
||||
free(nbus);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
nbus = tnbus;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
/* bus removed */
|
||||
changes++;
|
||||
LIST_DEL(usb_busses, bus);
|
||||
free(bus);
|
||||
}
|
||||
|
||||
bus = tbus;
|
||||
}
|
||||
|
||||
/* anything remaining in new_busses is a new bus */
|
||||
bus = new_busses;
|
||||
while (bus) {
|
||||
struct usbbus_bus *tbus = bus->next;
|
||||
LIST_DEL(new_busses, bus);
|
||||
LIST_ADD(usb_busses, bus);
|
||||
changes++;
|
||||
bus = tbus;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
static int find_devices(libusb_device **dev_list, int dev_list_len,
|
||||
struct usbbus_bus *bus, struct usbbus_device **ret)
|
||||
{
|
||||
struct usbbus_device *devices = NULL;
|
||||
struct usbbus_device *dev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_list_len; i++) {
|
||||
libusb_device *newlib_dev = dev_list[i];
|
||||
uint8_t bus_num = libusb_get_bus_number(newlib_dev);
|
||||
|
||||
if (bus_num != bus->location)
|
||||
continue;
|
||||
|
||||
dev = malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
goto err;
|
||||
|
||||
/* No need to reference the device now, just take the pointer. We
|
||||
* increase the reference count later if we keep the device. */
|
||||
dev->dev = newlib_dev;
|
||||
|
||||
dev->bus = bus;
|
||||
dev->devnum = libusb_get_device_address(newlib_dev);
|
||||
snprintf(dev->filename, USBBUS_PATH_MAX, "%03d", dev->devnum);
|
||||
LIST_ADD(devices, dev);
|
||||
}
|
||||
|
||||
*ret = devices;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev = devices;
|
||||
while (dev) {
|
||||
struct usbbus_device *tdev = dev->next;
|
||||
free(dev);
|
||||
dev = tdev;
|
||||
}
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
static void clear_endpoint_descriptor(struct usbbus_endpoint_descriptor *ep)
|
||||
{
|
||||
if (ep->extra)
|
||||
free(ep->extra);
|
||||
}
|
||||
|
||||
static void clear_interface_descriptor(struct usbbus_interface_descriptor *iface)
|
||||
{
|
||||
if (iface->extra)
|
||||
free(iface->extra);
|
||||
if (iface->endpoint) {
|
||||
int i;
|
||||
for (i = 0; i < iface->bNumEndpoints; i++)
|
||||
clear_endpoint_descriptor(iface->endpoint + i);
|
||||
free(iface->endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_interface(struct usbbus_interface *iface)
|
||||
{
|
||||
if (iface->altsetting) {
|
||||
int i;
|
||||
for (i = 0; i < iface->num_altsetting; i++)
|
||||
clear_interface_descriptor(iface->altsetting + i);
|
||||
free(iface->altsetting);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_config_descriptor(struct usbbus_config_descriptor *config)
|
||||
{
|
||||
if (config->extra)
|
||||
free(config->extra);
|
||||
if (config->interface) {
|
||||
int i;
|
||||
for (i = 0; i < config->bNumInterfaces; i++)
|
||||
clear_interface(config->interface + i);
|
||||
free(config->interface);
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_device(struct usbbus_device *dev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
|
||||
clear_config_descriptor(dev->config + i);
|
||||
}
|
||||
|
||||
static int copy_endpoint_descriptor(struct usbbus_endpoint_descriptor *dest,
|
||||
const struct libusb_endpoint_descriptor *src)
|
||||
{
|
||||
memcpy(dest, src, USBBUS_DT_ENDPOINT_AUDIO_SIZE);
|
||||
|
||||
dest->extralen = src->extra_length;
|
||||
if (src->extra_length) {
|
||||
dest->extra = malloc(src->extra_length);
|
||||
if (!dest->extra)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
memcpy(dest->extra, src->extra, src->extra_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_interface_descriptor(struct usbbus_interface_descriptor *dest,
|
||||
const struct libusb_interface_descriptor *src)
|
||||
{
|
||||
int i;
|
||||
int num_endpoints = src->bNumEndpoints;
|
||||
size_t alloc_size = sizeof(struct usbbus_endpoint_descriptor) * num_endpoints;
|
||||
|
||||
memcpy(dest, src, USBBUS_DT_INTERFACE_SIZE);
|
||||
dest->endpoint = malloc(alloc_size);
|
||||
if (!dest->endpoint)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
memset(dest->endpoint, 0, alloc_size);
|
||||
|
||||
for (i = 0; i < num_endpoints; i++) {
|
||||
int r = copy_endpoint_descriptor(dest->endpoint + i, &src->endpoint[i]);
|
||||
if (r < 0) {
|
||||
clear_interface_descriptor(dest);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
dest->extralen = src->extra_length;
|
||||
if (src->extra_length) {
|
||||
dest->extra = malloc(src->extra_length);
|
||||
if (!dest->extra) {
|
||||
clear_interface_descriptor(dest);
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
memcpy(dest->extra, src->extra, src->extra_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_interface(struct usbbus_interface *dest,
|
||||
const struct libusb_interface *src)
|
||||
{
|
||||
int i;
|
||||
int num_altsetting = src->num_altsetting;
|
||||
size_t alloc_size = sizeof(struct usbbus_interface_descriptor)
|
||||
* num_altsetting;
|
||||
|
||||
dest->num_altsetting = num_altsetting;
|
||||
dest->altsetting = malloc(alloc_size);
|
||||
if (!dest->altsetting)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
memset(dest->altsetting, 0, alloc_size);
|
||||
|
||||
for (i = 0; i < num_altsetting; i++) {
|
||||
int r = copy_interface_descriptor(dest->altsetting + i,
|
||||
&src->altsetting[i]);
|
||||
if (r < 0) {
|
||||
clear_interface(dest);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_config_descriptor(struct usbbus_config_descriptor *dest,
|
||||
const struct libusb_config_descriptor *src)
|
||||
{
|
||||
int i;
|
||||
int num_interfaces = src->bNumInterfaces;
|
||||
size_t alloc_size = sizeof(struct usbbus_interface) * num_interfaces;
|
||||
|
||||
memcpy(dest, src, USBBUS_DT_CONFIG_SIZE);
|
||||
dest->interface = malloc(alloc_size);
|
||||
if (!dest->interface)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
memset(dest->interface, 0, alloc_size);
|
||||
|
||||
for (i = 0; i < num_interfaces; i++) {
|
||||
int r = copy_interface(dest->interface + i, &src->interface[i]);
|
||||
if (r < 0) {
|
||||
clear_config_descriptor(dest);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
dest->extralen = src->extra_length;
|
||||
if (src->extra_length) {
|
||||
dest->extra = malloc(src->extra_length);
|
||||
if (!dest->extra) {
|
||||
clear_config_descriptor(dest);
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
}
|
||||
memcpy(dest->extra, src->extra, src->extra_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int initialize_device(struct usbbus_device *dev)
|
||||
{
|
||||
libusb_device *newlib_dev = dev->dev;
|
||||
int num_configurations;
|
||||
size_t alloc_size;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
/* device descriptor is identical in both libs */
|
||||
r = libusb_get_device_descriptor(newlib_dev,
|
||||
(struct libusb_device_descriptor *) &dev->descriptor);
|
||||
if (r < 0) {
|
||||
return r;
|
||||
}
|
||||
|
||||
num_configurations = dev->descriptor.bNumConfigurations;
|
||||
alloc_size = sizeof(struct usbbus_config_descriptor) * num_configurations;
|
||||
dev->config = malloc(alloc_size);
|
||||
if (!dev->config)
|
||||
return LIBUSB_ERROR_NO_MEM;
|
||||
memset(dev->config, 0, alloc_size);
|
||||
|
||||
for (i = 0; i < num_configurations; i++) {
|
||||
struct libusb_config_descriptor *newlib_config;
|
||||
r = libusb_get_config_descriptor(newlib_dev, i, &newlib_config);
|
||||
if (r < 0) {
|
||||
clear_device(dev);
|
||||
free(dev->config);
|
||||
return r;
|
||||
}
|
||||
r = copy_config_descriptor(dev->config + i, newlib_config);
|
||||
libusb_free_config_descriptor(newlib_config);
|
||||
if (r < 0) {
|
||||
clear_device(dev);
|
||||
free(dev->config);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
dev->num_children = 0;
|
||||
dev->children = NULL;
|
||||
|
||||
libusb_ref_device(newlib_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_device(struct usbbus_device *dev)
|
||||
{
|
||||
clear_device(dev);
|
||||
libusb_unref_device(dev->dev);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static int usb_find_devices(void)
|
||||
{
|
||||
struct usbbus_bus *bus;
|
||||
libusb_device **dev_list;
|
||||
int dev_list_len;
|
||||
int changes = 0;
|
||||
|
||||
/* libusb-1.0 initialization might have failed, but we can't indicate
|
||||
* this with libusb-0.1, so trap that situation here */
|
||||
if (!ctx)
|
||||
return 0;
|
||||
|
||||
dev_list_len = libusb_get_device_list(ctx, &dev_list);
|
||||
if (dev_list_len < 0)
|
||||
return dev_list_len;
|
||||
|
||||
for (bus = usb_busses; bus; bus = bus->next) {
|
||||
int r;
|
||||
struct usbbus_device *new_devices = NULL;
|
||||
struct usbbus_device *dev;
|
||||
|
||||
r = find_devices(dev_list, dev_list_len, bus, &new_devices);
|
||||
if (r < 0) {
|
||||
libusb_free_device_list(dev_list, 1);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* walk through the devices we already know about, removing duplicates
|
||||
* from the new list. if we do not find it in the new list, the device
|
||||
* has been removed. */
|
||||
dev = bus->devices;
|
||||
while (dev) {
|
||||
int found = 0;
|
||||
struct usbbus_device *tdev = dev->next;
|
||||
struct usbbus_device *ndev = new_devices;
|
||||
|
||||
while (ndev) {
|
||||
if (ndev->devnum == dev->devnum) {
|
||||
LIST_DEL(new_devices, ndev);
|
||||
free(ndev);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
ndev = ndev->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
LIST_DEL(bus->devices, dev);
|
||||
free_device(dev);
|
||||
changes++;
|
||||
}
|
||||
|
||||
dev = tdev;
|
||||
}
|
||||
|
||||
/* anything left in new_devices is a new device */
|
||||
dev = new_devices;
|
||||
while (dev) {
|
||||
struct usbbus_device *tdev = dev->next;
|
||||
r = initialize_device(dev);
|
||||
if (r < 0) {
|
||||
dev = tdev;
|
||||
continue;
|
||||
}
|
||||
LIST_DEL(new_devices, dev);
|
||||
LIST_ADD(bus->devices, dev);
|
||||
changes++;
|
||||
dev = tdev;
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_device_list(dev_list, 1);
|
||||
return changes;
|
||||
}
|
||||
|
||||
int usbbus_prepare(void)
|
||||
{
|
||||
static bool usb_initialized = false;
|
||||
if (!usb_initialized) {
|
||||
int usbbus_prepare() {
|
||||
static bool usb_initialized = false;
|
||||
int res;
|
||||
if (!usb_initialized) {
|
||||
|
||||
#ifdef ENVVARS
|
||||
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
|
||||
// Set libusb debug only if asked explicitely:
|
||||
// LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB)
|
||||
if (env_log_level && (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
|
||||
setenv("USB_DEBUG", "255", 1);
|
||||
}
|
||||
char *env_log_level = getenv("LIBNFC_LOG_LEVEL");
|
||||
// Set libusb debug only if asked explicitely:
|
||||
// LIBUSB_LOG_LEVEL=12288 (= NFC_LOG_PRIORITY_DEBUG * 2 ^ NFC_LOG_GROUP_LIBUSB)
|
||||
if (env_log_level
|
||||
&& (((atoi(env_log_level) >> (NFC_LOG_GROUP_LIBUSB * 2)) & 0x00000003) >= NFC_LOG_PRIORITY_DEBUG)) {
|
||||
setenv("USB_DEBUG", "255", 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_init();
|
||||
usb_initialized = true;
|
||||
}
|
||||
res = libusb_init(&ctx);
|
||||
if (res != 0) {
|
||||
log_put(LOG_GROUP,
|
||||
LOG_CATEGORY,
|
||||
NFC_LOG_PRIORITY_ERROR,
|
||||
"Unable to init libusb (%s)",
|
||||
libusb_strerror(res));
|
||||
return res;
|
||||
}
|
||||
usb_initialized = true;
|
||||
}
|
||||
|
||||
int res;
|
||||
// usb_find_busses will find all of the busses on the system. Returns the
|
||||
// number of changes since previous call to this function (total of new
|
||||
// busses and busses removed).
|
||||
if ((res = usb_find_busses()) < 0) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB busses (%s)", usbbus_strerror(res));
|
||||
return -1;
|
||||
}
|
||||
// usb_find_devices will find all of the devices on each bus. This should be
|
||||
// called after usb_find_busses. Returns the number of changes since the
|
||||
// previous call to this function (total of new device and devices removed).
|
||||
if ((res = usb_find_devices()) < 0) {
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to find USB devices (%s)", usbbus_strerror(res));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
// usb_find_devices will find all of the devices on each bus. This should be
|
||||
// called after usb_find_busses. Returns the number of changes since the
|
||||
// previous call to this function (total of new device and devices removed).
|
||||
libusb_device **tmp_devices;
|
||||
ssize_t num_devices = libusb_get_device_list(ctx, &tmp_devices);
|
||||
libusb_free_device_list(tmp_devices, (int) num_devices);
|
||||
if (num_devices <= 0) {
|
||||
log_put(LOG_GROUP,
|
||||
LOG_CATEGORY,
|
||||
NFC_LOG_PRIORITY_ERROR,
|
||||
"Unable to find USB devices (%s)",
|
||||
libusb_strerror((int) num_devices));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
usbbus_device_handle *usbbus_open(struct usbbus_device *dev)
|
||||
{
|
||||
int r;
|
||||
usbbus_device_handle *udev;
|
||||
r = libusb_open((libusb_device *) dev->dev, (libusb_device_handle **)&udev);
|
||||
if (r < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return (usbbus_device_handle *)udev;
|
||||
|
||||
TODO kenspeckle
|
||||
beim ende vom programm libusb dinge wieder freigeben
|
||||
|
||||
size_t usbbus_usb_scan(char **connstrings,
|
||||
const size_t connstrings_len,
|
||||
struct usbbus_device *nfc_usb_devices,
|
||||
const size_t num_nfc_usb_devices,
|
||||
char *usb_driver_name) {
|
||||
usbbus_prepare();
|
||||
|
||||
size_t device_found = 0;
|
||||
struct libusb_device **devices;
|
||||
ssize_t num_devices = libusb_get_device_list(ctx, &devices);
|
||||
for (size_t i = 0; i < num_devices; i++) {
|
||||
struct libusb_device *dev = devices[i];
|
||||
|
||||
for (size_t nfc_dev_idx = 0; nfc_dev_idx < num_nfc_usb_devices; nfc_dev_idx++) {
|
||||
if (nfc_usb_devices[nfc_dev_idx].vendor_id == usbbus_get_vendor_id(dev)
|
||||
&& nfc_usb_devices[nfc_dev_idx].product_id == usbbus_get_product_id(dev)) {
|
||||
|
||||
size_t valid_config_idx = 1;
|
||||
|
||||
// Make sure there are 2 endpoints available
|
||||
// with libusb-win32 we got some null pointers so be robust before looking at endpoints
|
||||
if (nfc_usb_devices[nfc_dev_idx].max_packet_size == 0) {
|
||||
|
||||
bool found_valid_config = false;
|
||||
|
||||
for (size_t config_idx = 0; config_idx < get_usb_num_configs(dev); i++) {
|
||||
struct libusb_config_descriptor *usb_config;
|
||||
int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
|
||||
|
||||
if (r != 0
|
||||
|| usb_config->interface == NULL
|
||||
|| usb_config->interface->altsetting == NULL
|
||||
|| usb_config->interface->altsetting->bNumEndpoints < 2) {
|
||||
// Nope, we maybe want the next one, let's try to find another
|
||||
libusb_free_config_descriptor(usb_config);
|
||||
continue;
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(usb_config);
|
||||
|
||||
found_valid_config = true;
|
||||
valid_config_idx = config_idx;
|
||||
break;
|
||||
}
|
||||
if (!found_valid_config) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
libusb_device_handle *udev;
|
||||
int res = libusb_open(dev, &udev);
|
||||
if (res < 0 && udev == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set configuration
|
||||
res = libusb_set_configuration(udev, (int) valid_config_idx);
|
||||
if (res < 0) {
|
||||
log_put(LOG_GROUP,
|
||||
LOG_CATEGORY,
|
||||
NFC_LOG_PRIORITY_ERROR,
|
||||
"Unable to set USB configuration (%s)",
|
||||
libusb_strerror(res));
|
||||
libusb_close(udev);
|
||||
// we failed to use the device
|
||||
continue;
|
||||
}
|
||||
|
||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "device found: Vendor-Id: %d Product-Id %d",
|
||||
usbbus_get_vendor_id(dev), usbbus_get_product_id(dev));
|
||||
libusb_close(udev);
|
||||
|
||||
uint8_t dev_address = libusb_get_device_address(dev);
|
||||
size_t size_new_str = snprintf(
|
||||
connstrings[device_found],
|
||||
sizeof(nfc_connstring),
|
||||
"%s:%03d:%03d",
|
||||
usb_driver_name,
|
||||
dev_address, (int) valid_config_idx);
|
||||
if (size_new_str >= (int) sizeof(nfc_connstring)) {
|
||||
// truncation occurred, skipping that one
|
||||
continue;
|
||||
}
|
||||
device_found++;
|
||||
// Test if we reach the maximum "wanted" devices
|
||||
if (device_found == connstrings_len) {
|
||||
return device_found;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return device_found;
|
||||
}
|
||||
|
||||
void usbbus_close(usbbus_device_handle *dev)
|
||||
{
|
||||
libusb_close((libusb_device_handle *)dev);
|
||||
void usbbus_get_usb_endpoints(struct libusb_device *dev,
|
||||
uint8_t *endpoint_in,
|
||||
uint8_t *endpoint_out,
|
||||
uint16_t *max_packet_size) {
|
||||
|
||||
bool endpoint_in_set = false;
|
||||
bool endpoint_out_set = false;
|
||||
size_t num_configs = get_usb_num_configs(dev);
|
||||
for (size_t config_idx = 0; config_idx < num_configs; config_idx++) {
|
||||
struct libusb_config_descriptor *usb_config;
|
||||
|
||||
int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
|
||||
if (r != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!usb_config->interface) {
|
||||
continue;
|
||||
}
|
||||
for (size_t interface_idx = 0; interface_idx < usb_config->bNumInterfaces; interface_idx++) {
|
||||
struct libusb_interface interface = usb_config->interface[interface_idx];
|
||||
if (!interface.altsetting) {
|
||||
continue;
|
||||
}
|
||||
for (size_t settings_idx = 0; settings_idx < interface.num_altsetting; settings_idx++) {
|
||||
struct libusb_interface_descriptor settings = interface.altsetting[settings_idx];
|
||||
if (!settings.endpoint) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3 Endpoints maximum: Interrupt In, Bulk In, Bulk Out
|
||||
for (size_t endpoint_idx = 0; endpoint_idx < settings.bNumEndpoints; endpoint_idx++) {
|
||||
struct libusb_endpoint_descriptor endpoint = settings.endpoint[endpoint_idx];
|
||||
|
||||
// Only accept bulk transfer endpoints (ignore interrupt endpoints)
|
||||
if (endpoint.bmAttributes != LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copy the endpoint to a local var, makes it more readable code
|
||||
uint8_t endpoint_address = endpoint.bEndpointAddress;
|
||||
|
||||
// Test if we dealing with a bulk IN endpoint
|
||||
if ((endpoint_address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN && !endpoint_in_set) {
|
||||
*endpoint_in = endpoint_address;
|
||||
*max_packet_size = endpoint.wMaxPacketSize;
|
||||
endpoint_in_set = true;
|
||||
}
|
||||
// Test if we dealing with a bulk OUT endpoint
|
||||
if ((endpoint_address & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT && !endpoint_out_set) {
|
||||
*endpoint_out = endpoint_address;
|
||||
*max_packet_size = endpoint.wMaxPacketSize;
|
||||
endpoint_out_set = true;
|
||||
}
|
||||
|
||||
if (endpoint_in_set && endpoint_out_set) {
|
||||
libusb_free_config_descriptor(usb_config);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libusb_free_config_descriptor(usb_config);
|
||||
}
|
||||
}
|
||||
|
||||
int usbbus_set_configuration(usbbus_device_handle *dev, int configuration)
|
||||
{
|
||||
return libusb_set_configuration((libusb_device_handle *)dev, configuration);
|
||||
uint8_t get_usb_num_configs(struct libusb_device *dev) {
|
||||
struct libusb_device_descriptor descriptor;
|
||||
libusb_get_device_descriptor(dev, &descriptor);
|
||||
return descriptor.bNumConfigurations;
|
||||
}
|
||||
|
||||
int usbbus_get_string_simple(usbbus_device_handle *dev, int index, char *buf, size_t buflen)
|
||||
{
|
||||
return libusb_get_string_descriptor_ascii((libusb_device_handle *)dev, index & 0xff,
|
||||
(unsigned char *) buf, (int) buflen);
|
||||
void usbbus_get_usb_device_name(struct libusb_device *dev, libusb_device_handle *udev, char *buffer, size_t len) {
|
||||
struct libusb_device_descriptor descriptor;
|
||||
libusb_get_device_descriptor(dev, &descriptor);
|
||||
if (descriptor.iManufacturer || descriptor.iProduct) {
|
||||
if (udev) {
|
||||
libusb_get_string_descriptor_ascii(udev, descriptor.iManufacturer & 0xff, (unsigned char *) buffer, len);
|
||||
if (strlen(buffer) > 0) {
|
||||
strncpy(buffer + strlen(buffer), " / ", 4);
|
||||
}
|
||||
libusb_get_string_descriptor_ascii(udev,
|
||||
descriptor.iProduct & 0xff,
|
||||
(unsigned char *) buffer + strlen(buffer),
|
||||
len - strlen(buffer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int usbbus_bulk_transfer(usbbus_device_handle *dev, int ep, char *bytes, int size, int *actual_length, int timeout)
|
||||
{
|
||||
return libusb_bulk_transfer((libusb_device_handle *)dev, ep & 0xff, (unsigned char *)bytes, size, actual_length, timeout);
|
||||
|
||||
void usbbus_get_device(uint8_t dev_address, struct libusb_device * dev, struct libusb_device_handle * dev_handle) {
|
||||
struct libusb_device ** device_list;
|
||||
ssize_t num_devices = libusb_get_device_list(ctx, &device_list);
|
||||
for (size_t i = 0; i < num_devices; i++) {
|
||||
if (libusb_get_device_address(device_list[i]) != dev_address) {
|
||||
continue;
|
||||
} else {
|
||||
dev = device_list[i];
|
||||
int res = libusb_open(dev, &dev_handle);
|
||||
if (res != 0 || dev_handle == NULL) {
|
||||
log_put(LOG_GROUP,LOG_CATEGORY,NFC_LOG_PRIORITY_ERROR,
|
||||
"Unable to open libusb device (%s)",libusb_strerror(res));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// libusb works with a reference counter which is set to 1 for each device when calling libusb_get_device_list and increased
|
||||
// by libusb_open. Thus we decrease the counter by 1 for all devices and only the "real" device will survive
|
||||
libusb_free_device_list(device_list, num_devices);
|
||||
|
||||
}
|
||||
|
||||
int usbbus_claim_interface(usbbus_device_handle *dev, int interface)
|
||||
{
|
||||
return libusb_claim_interface((libusb_device_handle *)dev, interface);
|
||||
|
||||
uint16_t usbbus_get_vendor_id(struct libusb_device *dev) {
|
||||
struct libusb_device_descriptor descriptor;
|
||||
libusb_get_device_descriptor(dev, &descriptor);
|
||||
return descriptor.idVendor;
|
||||
}
|
||||
|
||||
int usbbus_release_interface(usbbus_device_handle *dev, int interface)
|
||||
{
|
||||
return libusb_release_interface((libusb_device_handle *)dev, interface);
|
||||
uint16_t usbbus_get_product_id(struct libusb_device *dev) {
|
||||
struct libusb_device_descriptor descriptor;
|
||||
libusb_get_device_descriptor(dev, &descriptor);
|
||||
return descriptor.idProduct;
|
||||
}
|
||||
|
||||
int usbbus_set_interface_alt_setting(usbbus_device_handle *dev, int interface, int alternate)
|
||||
{
|
||||
return libusb_set_interface_alt_setting((libusb_device_handle *)dev, interface, alternate);
|
||||
|
||||
int usbbus_get_num_alternate_settings(struct libusb_device *dev, uint8_t config_idx) {
|
||||
struct libusb_config_descriptor *usb_config;
|
||||
int r = libusb_get_config_descriptor(dev, config_idx, &usb_config);
|
||||
if (r != 0 || usb_config == NULL) {
|
||||
return -1;
|
||||
}
|
||||
libusb_free_config_descriptor(usb_config);
|
||||
return usb_config->interface->num_altsetting;
|
||||
}
|
||||
|
||||
int usbbus_reset(usbbus_device_handle *dev)
|
||||
{
|
||||
return libusb_reset_device((libusb_device_handle *)dev);
|
||||
}
|
||||
|
||||
const char *usbbus_strerror(int errcode)
|
||||
{
|
||||
return libusb_strerror((enum libusb_error)errcode);
|
||||
}
|
||||
|
||||
struct usbbus_bus *usbbus_get_busses(void)
|
||||
{
|
||||
return usb_busses;
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
* Copyright (C) 2010-2012 Romain Tartière
|
||||
* Copyright (C) 2010-2013 Philippe Teuwen
|
||||
* Copyright (C) 2012-2013 Ludovic Rousseau
|
||||
* Copyright (C) 2022 Kenspeckle
|
||||
* See AUTHORS file for a more comprehensive list of contributors.
|
||||
* Additional contributors of this file:
|
||||
*
|
||||
@ -25,150 +26,29 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file usbbus.h
|
||||
* @brief libusb 0.1 driver header
|
||||
*/
|
||||
#ifndef __NFC_BUS_USBBUS_H__
|
||||
#define __NFC_BUS_USBBUS_H__
|
||||
|
||||
#ifndef __NFC_BUS_USB_H__
|
||||
# define __NFC_BUS_USB_H__
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#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;
|
||||
#define EMPTY_STRING "\0";
|
||||
|
||||
struct usbbus_device {
|
||||
struct usbbus_device *next, *prev;
|
||||
|
||||
char filename[USBBUS_PATH_MAX + 1];
|
||||
|
||||
struct usbbus_bus *bus;
|
||||
|
||||
struct usbbus_device_descriptor descriptor;
|
||||
struct usbbus_config_descriptor *config;
|
||||
|
||||
void *dev;
|
||||
|
||||
uint8_t devnum;
|
||||
|
||||
unsigned char num_children;
|
||||
struct usbbus_device **children;
|
||||
};
|
||||
|
||||
struct usbbus_bus {
|
||||
struct usbbus_bus *next, *prev;
|
||||
|
||||
char dirname[USBBUS_PATH_MAX + 1];
|
||||
|
||||
struct usbbus_device *devices;
|
||||
uint32_t location;
|
||||
|
||||
struct usbbus_device *root_dev;
|
||||
uint16_t vendor_id;
|
||||
uint16_t product_id;
|
||||
const char *name;
|
||||
uint16_t max_packet_size;
|
||||
};
|
||||
|
||||
|
||||
usbbus_device_handle *usbbus_open(struct usbbus_device *dev);
|
||||
void usbbus_close(usbbus_device_handle *dev);
|
||||
int usbbus_set_configuration(usbbus_device_handle *dev, int configuration);
|
||||
int usbbus_get_string_simple(usbbus_device_handle *dev, int index, char *buf, size_t buflen);
|
||||
int usbbus_bulk_transfer(usbbus_device_handle *dev, int ep, char *bytes, int size, int *actual_length, int timeout);
|
||||
int usbbus_claim_interface(usbbus_device_handle *dev, int interface);
|
||||
int usbbus_release_interface(usbbus_device_handle *dev, int interface);
|
||||
int usbbus_set_interface_alt_setting(usbbus_device_handle *dev, int interface, int alternate);
|
||||
int usbbus_reset(usbbus_device_handle *dev);
|
||||
const char *usbbus_strerror(int errcode);
|
||||
struct usbbus_bus *usbbus_get_busses(void);
|
||||
|
||||
#endif // __NFC_BUS_USB_H__
|
||||
int usbbus_prepare();
|
||||
|
||||
size_t usbbus_usb_scan(char ** connstrings, size_t connstrings_len, struct usbbus_device * nfc_usb_devices, size_t num_nfc_usb_devices, char * usb_driver_name);
|
||||
void usbbus_get_usb_endpoints(struct libusb_device *dev, uint8_t * endpoint_in, uint8_t * endpoint_out, uint16_t * max_packet_size);
|
||||
void usbbus_get_usb_device_name(struct libusb_device * dev, libusb_device_handle *udev, char *buffer, size_t len);
|
||||
void usbbus_get_device(uint8_t dev_address, struct libusb_device * dev, struct libusb_device_handle * dev_handle);
|
||||
uint16_t usbbus_get_vendor_id(struct libusb_device * dev);
|
||||
uint16_t usbbus_get_product_id(struct libusb_device * dev);
|
||||
int usbbus_get_num_alternate_settings(struct libusb_device *dev, uint8_t config_idx);
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user