diff --git a/include/nfc/nfc.h b/include/nfc/nfc.h
index 22f906d..5c63725 100644
--- a/include/nfc/nfc.h
+++ b/include/nfc/nfc.h
@@ -63,7 +63,7 @@ extern "C" {
# endif // __cplusplus
/* Library initialization/deinitialization */
- NFC_EXPORT void nfc_init(nfc_context *context);
+ NFC_EXPORT void nfc_init(nfc_context **context);
NFC_EXPORT void nfc_exit(nfc_context *context);
/* NFC Device/Hardware manipulation */
diff --git a/libnfc.conf.sample b/libnfc.conf.sample
new file mode 100644
index 0000000..1d81c9c
--- /dev/null
+++ b/libnfc.conf.sample
@@ -0,0 +1,8 @@
+# Allow device auto-detection (default: true)
+# Note: if this auto-detection is disable, user have to set manually a device
+# configuration using file or environnement variable
+#allow_autoscan = true
+
+# Allow intrusive auto-detection (default: false)
+# Warning: intrusive auto-detection can seriously disturb other devices
+#allow_intrusive_autoscan = false
diff --git a/libnfc/Makefile.am b/libnfc/Makefile.am
index 0f6f31c..6effdd9 100644
--- a/libnfc/Makefile.am
+++ b/libnfc/Makefile.am
@@ -4,6 +4,7 @@ SUBDIRS = chips buses drivers .
AM_CPPFLAGS = $(all_includes) $(LIBNFC_CFLAGS)
noinst_HEADERS = \
+ conf.h \
drivers.h \
iso7816.h \
log.h \
@@ -13,6 +14,7 @@ noinst_HEADERS = \
lib_LTLIBRARIES = libnfc.la
libnfc_la_SOURCES = \
+ conf.c \
iso14443-subr.c \
mirror-subr.c \
nfc.c \
diff --git a/libnfc/conf.c b/libnfc/conf.c
new file mode 100644
index 0000000..9e27fc8
--- /dev/null
+++ b/libnfc/conf.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (C) 2012 Romuald Conty
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include "nfc-internal.h"
+#include "log.h"
+
+#define LOG_CATEGORY "libnfc.config"
+
+#define LIBNFC_SYSCONFDIR "/etc/nfc"
+#define LIBNFC_CONFFILE LIBNFC_SYSCONFDIR"/libnfc.conf"
+#define LIBNFC_DEVICECONFDIR LIBNFC_SYSCONFDIR"/devices.d"
+
+
+bool conf_parse_file(const char* filename, void (*conf_keyvalue)(void* data, const char* key, const char* value), void* data)
+{
+ FILE *f = fopen (filename, "r");
+ if (!f) {
+ perror ("fopen");
+ return false;
+ }
+ char line[BUFSIZ];
+ const char *str_regex = "^[[:space:]]*([[:alnum:]_]+)[[:space:]]*=[[:space:]]*(\"(.+)\"|([^[:space:]]+))[[:space:]]*$";
+ regex_t preg;
+ if(regcomp (&preg, str_regex, REG_EXTENDED|REG_NOTEOL) != 0) {
+ printf ("regcomp error\n");
+ return false;
+ }
+ size_t nmatch = preg.re_nsub + 1;
+ regmatch_t *pmatch = malloc (sizeof (*pmatch) * nmatch);
+ if(!pmatch) {
+ perror ("malloc");
+ return false;
+ }
+
+ int lineno = 0;
+ while (fgets(line, BUFSIZ, f) != NULL) {
+ lineno++;
+ switch(line[0]) {
+ case '#':
+ case '\n':
+ break;
+ default: {
+ int match;
+ if ((match = regexec (&preg, line, nmatch, pmatch, 0)) == 0) {
+ const size_t key_size = pmatch[1].rm_eo - pmatch[1].rm_so;
+ const off_t value_pmatch = pmatch[3].rm_eo!=-1?3:4;
+ const size_t value_size = pmatch[value_pmatch].rm_eo - pmatch[value_pmatch].rm_so;
+ char key[key_size+1];
+ char value[value_size+1];
+ strncpy(key, line+(pmatch[1].rm_so), key_size); key[key_size]='\0';
+ strncpy(value, line+(pmatch[value_pmatch].rm_so), value_size); value[value_size]='\0';
+ conf_keyvalue(data, key, value);
+ } else {
+ log_put( LOG_CATEGORY, NFC_PRIORITY_TRACE, "parse error on line #%d: %s", lineno, line);
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+void
+conf_keyvalue_context(void *data, const char* key, const char* value)
+{
+ nfc_context *context = (nfc_context*)data;
+ printf ("key: [%s], value: [%s]\n", key, value);
+ if (strcmp(key, "allow_autoscan") == 0) {
+ string_as_boolean(value, &(context->allow_autoscan));
+ } else if (strcmp(key, "allow_intrusive_scan") == 0) {
+ string_as_boolean(value, &(context->allow_intrusive_scan));
+ } else {
+ log_put( LOG_CATEGORY, NFC_PRIORITY_INFO, "unknown key in config line: %s = %s", key, value);
+ }
+}
+
+void
+conf_load(nfc_context *context)
+{
+ conf_parse_file(LIBNFC_CONFFILE, conf_keyvalue_context, context);
+}
+
+/*
+int
+main(int argc, char *argv[])
+{
+ DIR *d = opendir(LIBNFC_DEVICECONFDIR);
+ if (!d) {
+ perror ("opendir");
+ } else {
+ struct dirent* de;
+ while (de = readdir(d)) {
+ if (de->d_name[0]!='.') {
+ printf ("\t%s\n", de->d_name);
+ char filename[BUFSIZ] = LIBNFC_DEVICECONFDIR"/";
+ strcat (filename, de->d_name);
+ struct stat s;
+ if (stat(filename, &s) == -1) {
+ perror("stat");
+ continue;
+ }
+ if(S_ISREG(s.st_mode)) {
+ nfc_open_from_file (filename);
+ }
+ }
+ }
+ }
+}
+*/
diff --git a/libnfc/conf.h b/libnfc/conf.h
new file mode 100644
index 0000000..4717768
--- /dev/null
+++ b/libnfc/conf.h
@@ -0,0 +1,19 @@
+/*-
+ * Copyright (C) 2012 Romuald Conty
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see
+ */
+
+void conf_load(nfc_context *context);
+
diff --git a/libnfc/nfc-internal.c b/libnfc/nfc-internal.c
index f3fd64d..7ebcdb3 100644
--- a/libnfc/nfc-internal.c
+++ b/libnfc/nfc-internal.c
@@ -24,20 +24,31 @@
#include
#include "nfc-internal.h"
+#include "conf.h"
#include
#include
-static bool
-string_as_boolean(const char* s)
+void
+string_as_boolean(const char* s, bool *value)
{
- if ((s) && (
- (strcmp(s, "yes") == 0) ||
- (strcmp(s, "true") == 0) ||
- (strcmp(s, "1") == 0))) {
- return true;
+ if (s) {
+ if (!(*value)) {
+ if ( (strcmp(s, "yes") == 0) ||
+ (strcmp(s, "true") == 0) ||
+ (strcmp(s, "1") == 0) ) {
+ *value = true;
+ return;
+ }
+ } else {
+ if ( (strcmp(s, "no") == 0) ||
+ (strcmp(s, "false") == 0) ||
+ (strcmp(s, "0") == 0) ) {
+ *value = false;
+ return;
+ }
+ }
}
- return false;
}
nfc_context *
@@ -49,10 +60,20 @@ nfc_context_new(void)
err(EXIT_FAILURE, "nfc_context_new: malloc");
}
+ // Set default context values
+ res->allow_autoscan = true;
+ res->allow_intrusive_scan = false;
+
+ // Load options from configuration file (ie. /etc/nfc/libnfc.conf)
+ conf_load(res);
+
+ // Environment variables
// Load "intrusive scan" option
- // XXX: Load this option from configuration file too ?
char *envvar = getenv("LIBNFC_INTRUSIVE_SCAN");
- res->allow_intrusive_scan = string_as_boolean(envvar);
+ string_as_boolean(envvar, &(res->allow_intrusive_scan));
+
+ // Debug context state
+ log_put ("libnfc", NFC_PRIORITY_DEBUG, "allow_autoscan is set to %s", (res->allow_autoscan)?"true":"false");
log_put ("libnfc", NFC_PRIORITY_DEBUG, "allow_intrusive_scan is set to %s", (res->allow_intrusive_scan)?"true":"false");
return res;
}
diff --git a/libnfc/nfc-internal.h b/libnfc/nfc-internal.h
index ba40e29..5edebf1 100644
--- a/libnfc/nfc-internal.h
+++ b/libnfc/nfc-internal.h
@@ -158,6 +158,7 @@ struct nfc_driver {
* Struct which contains internal options, references, pointers, etc. used by library
*/
struct nfc_context {
+ bool allow_autoscan;
bool allow_intrusive_scan;
};
@@ -195,6 +196,8 @@ struct nfc_device {
nfc_device *nfc_device_new(const nfc_connstring connstring);
void nfc_device_free(nfc_device *dev);
+void string_as_boolean(const char* s, bool *value);
+
void iso14443_cascade_uid(const uint8_t abtUID[], const size_t szUID, uint8_t *pbtCascadedUID, size_t *pszCascadedUID);
void prepare_initiator_data(const nfc_modulation nm, uint8_t **ppbtInitiatorData, size_t *pszInitiatorData);
diff --git a/libnfc/nfc.c b/libnfc/nfc.c
index 48fb2ea..9dc374d 100644
--- a/libnfc/nfc.c
+++ b/libnfc/nfc.c
@@ -108,12 +108,16 @@ const struct nfc_driver *nfc_drivers[] = {
/** @ingroup lib
* @brief Initialize libnfc.
* This function must be called before calling any other libnfc function
- * @param context Optional output location for context pointer
+ * @param context Output location for nfc_context
*/
void
-nfc_init(nfc_context *context)
+nfc_init(nfc_context **context)
{
- (void) context;
+ if (!context) {
+ printf("Error: NULL context is not supported anymore, please fix your code.\n");
+ exit(EXIT_FAILURE);
+ }
+ *context = nfc_context_new();
log_init();
}
@@ -265,23 +269,29 @@ nfc_list_devices(nfc_context *context, nfc_connstring connstrings[], const size_
const struct nfc_driver *ndr;
const struct nfc_driver **pndr = nfc_drivers;
- if (!context) context = nfc_context_new(); // Should we support NULL context ?
- // FIXME: Load device(s) from configuration file(s)
-
- while ((ndr = *pndr)) {
- size_t _device_found = 0;
- if((ndr->scan_type == NOT_INTRUSIVE) || ((context->allow_intrusive_scan) && (ndr->scan_type == INTRUSIVE))) {
- _device_found = ndr->scan(connstrings + (device_found), connstrings_len - (device_found));
- log_put(LOG_CATEGORY, NFC_PRIORITY_TRACE, "%ld device(s) found using %s driver", (unsigned long) _device_found, ndr->name);
- if (_device_found > 0) {
- device_found += _device_found;
- if (device_found == connstrings_len)
- break;
- }
- } // scan_type is INTRUSIVE but not allowed or NOT_AVAILABLE
- pndr++;
+ if (!context) {
+ printf ("NULL context is not supported anymore! Please fix your code.");
}
- log_fini();
+
+ // TODO Load manually configured devices (from config file and env variables)
+
+ // Device auto-detection
+ if (context->allow_autoscan) {
+ while ((ndr = *pndr)) {
+ size_t _device_found = 0;
+ if((ndr->scan_type == NOT_INTRUSIVE) || ((context->allow_intrusive_scan) && (ndr->scan_type == INTRUSIVE))) {
+ _device_found = ndr->scan(connstrings + (device_found), connstrings_len - (device_found));
+ log_put(LOG_CATEGORY, NFC_PRIORITY_TRACE, "%ld device(s) found using %s driver", (unsigned long) _device_found, ndr->name);
+ if (_device_found > 0) {
+ device_found += _device_found;
+ if (device_found == connstrings_len)
+ break;
+ }
+ } // scan_type is INTRUSIVE but not allowed or NOT_AVAILABLE
+ pndr++;
+ }
+ }
+
return device_found;
}
diff --git a/utils/nfc-list.c b/utils/nfc-list.c
index 035923d..e615741 100644
--- a/utils/nfc-list.c
+++ b/utils/nfc-list.c
@@ -75,7 +75,8 @@ main(int argc, const char *argv[])
bool verbose = false;
int res = 0;
- nfc_init(NULL);
+ nfc_context *context;
+ nfc_init(&context);
// Display libnfc version
acLibnfcVersion = nfc_version();
@@ -97,7 +98,7 @@ main(int argc, const char *argv[])
/* Lazy way to open an NFC device */
#if 0
- pnd = nfc_open(NULL, NULL);
+ pnd = nfc_open(context, NULL);
#endif
/* If specific device is wanted, i.e. an ARYGON device on /dev/ttyUSB0 */
@@ -106,7 +107,7 @@ main(int argc, const char *argv[])
ndd.pcDriver = "ARYGON";
ndd.pcPort = "/dev/ttyUSB0";
ndd.uiSpeed = 115200;
- pnd = nfc_open(NULL, &ndd);
+ pnd = nfc_open(context, &ndd);
#endif
/* If specific device is wanted, i.e. a SCL3711 on USB */
@@ -114,10 +115,10 @@ main(int argc, const char *argv[])
nfc_device_desc_t ndd;
ndd.pcDriver = "PN533_USB";
strcpy(ndd.acDevice, "SCM Micro / SCL3711-NFC&RW");
- pnd = nfc_open(NULL, &ndd);
+ pnd = nfc_open(context, &ndd);
#endif
nfc_connstring connstrings[MAX_DEVICE_COUNT];
- size_t szDeviceFound = nfc_list_devices(NULL, connstrings, MAX_DEVICE_COUNT);
+ size_t szDeviceFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);
if (szDeviceFound == 0) {
printf("No NFC device found.\n");
@@ -125,7 +126,7 @@ main(int argc, const char *argv[])
for (i = 0; i < szDeviceFound; i++) {
nfc_target ant[MAX_TARGET_COUNT];
- pnd = nfc_open(NULL, connstrings[i]);
+ pnd = nfc_open(context, connstrings[i]);
if (pnd == NULL) {
ERR("Unable to open NFC device: %s", connstrings[i]);