Implementation of configurable timeout (#101)

Previously, no timeout or an arbitrary timeout (500ms) was used. This
usually works but causes some issues when operations take longer: for
example, during `mifare_desfire_format_picc`.

This changes increases the previous default timeout to two seconds and
adds a new function that allows setting custom timeouts.
This commit is contained in:
broth-itk 2019-10-30 00:01:40 +01:00 committed by Robert Quattlebaum
parent d13eca5d3c
commit 7f695cfbec
6 changed files with 29 additions and 2 deletions

View file

@ -52,6 +52,7 @@ linkedman = \
freefare.3 freefare_get_tag_type.3 \
freefare.3 freefare_get_tag_uid.3 \
freefare.3 freefare_get_tags.3 \
freefare.3 freefare_set_tag_timeout.3 \
freefare.3 freefare_version.3 \
freefare_error.3 freefare_perror.3 \
freefare_error.3 freefare_strerror.3 \

View file

@ -27,6 +27,7 @@
.Nm freefare_get_tag_type ,
.Nm freefare_get_tag_friendly_name ,
.Nm freefare_get_tag_uid ,
.Nm freefare_set_tag_timeout ,
.Nm freefare_free_tag ,
.Nm freefare_free_tags ,
.Nm freefare_version
@ -67,6 +68,8 @@ enum freefare_tag_type {
.Ft "char *"
.Fn freefare_get_tag_uid "FreefareTag tag"
.Ft "void"
.Fn freefare_set_tag_timeout "FreefareTag tag" "int timeout"
.Ft "void"
.Fn freefare_free_tag "FreefareTag tags"
.Ft "void"
.Fn freefare_free_tags "FreefareTag *tags"
@ -122,6 +125,12 @@ and
functions.
.Pp
The
.Fn freefare_set_tag_timeout
function is used to set the maximum duration for a single NFC operation to
.Fa timeout
mili-seconds. Setting
.Fa timeout
to 0 disables the timeout feature. By default, a timeout of 2000 is configured.
.Fn freefare_version
function returns the version of the library.
.\" ____ _ _

View file

@ -39,6 +39,10 @@ freefare_tag_new(nfc_device *device, nfc_target target)
tag = mifare_ultralight_tag_new(device, target);
}
// Set default timeout
if (tag)
tag->timeout = MIFARE_DEFAULT_TIMEOUT;
return tag;
}
@ -202,6 +206,15 @@ bool freefare_selected_tag_is_present(nfc_device *device)
return (nfc_initiator_target_is_present(device, NULL) == NFC_SUCCESS);
}
/*
* Set NFC operation timeout
*/
void
freefare_set_tag_timeout(FreefareTag tag, int timeout)
{
tag->timeout = timeout;
}
/*
* Free the provided tag.
*/

View file

@ -49,6 +49,7 @@ char *freefare_get_tag_uid(FreefareTag tag);
void freefare_free_tag(FreefareTag tag);
void freefare_free_tags(FreefareTag *tags);
bool freefare_selected_tag_is_present(nfc_device *device);
void freefare_set_tag_timeout(FreefareTag tag, int timeout);
const char *freefare_version(void);

View file

@ -142,6 +142,8 @@ void *assert_crypto_buffer_size(FreefareTag tag, size_t nbytes);
#define MIFARE_ULTRALIGHT_C_PAGE_COUNT_READ 0x2C
// Max PAGE_COUNT of the Ultralight Family:
#define MIFARE_ULTRALIGHT_MAX_PAGE_COUNT 0x30
// Default timeout (ms) for tag operations
#define MIFARE_DEFAULT_TIMEOUT 2000
/*
* This structure is common to all supported MIFARE targets but shall not be
@ -156,6 +158,7 @@ struct freefare_tag {
nfc_target info;
int type;
int active;
int timeout;
void (*free_tag)(FreefareTag tag);
};

View file

@ -168,7 +168,7 @@ static ssize_t read_data(FreefareTag tag, uint8_t command, uint8_t file_no, off
MIFARE_DESFIRE (tag)->last_pcd_error = OPERATION_OK; \
DEBUG_XFER (__msg, __len, "===> "); \
int _res; \
if ((_res = nfc_initiator_transceive_bytes (tag->device, __msg, __len, __res, __##res##_size + 1, 500)) < 0) { \
if ((_res = nfc_initiator_transceive_bytes (tag->device, __msg, __len, __res, __##res##_size + 1, tag->timeout)) < 0) { \
return errno = (errno == ETIMEDOUT) ? errno : EIO, -1; \
} \
__##res##_n = _res; \
@ -306,7 +306,7 @@ mifare_desfire_connect(FreefareTag tag)
uint8_t AID[] = { 0xd2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x00};
BUFFER_APPEND(cmd, sizeof(AID));
BUFFER_APPEND_BYTES(cmd, AID, sizeof(AID));
if ((nfc_initiator_transceive_bytes(tag->device, cmd, BUFFER_SIZE(cmd), res, BUFFER_MAXSIZE(cmd), 500) < 0) || (res[0] != 0x90 || res[1] != 0x00)) {
if ((nfc_initiator_transceive_bytes(tag->device, cmd, BUFFER_SIZE(cmd), res, BUFFER_MAXSIZE(cmd), tag->timeout) < 0) || (res[0] != 0x90 || res[1] != 0x00)) {
errno = (errno == ETIMEDOUT) ? errno : EIO;
return -1;
}