From 6eb99ceb647cf35c39dc97292f00040fbb821170 Mon Sep 17 00:00:00 2001 From: Matt Ranostay Date: Thu, 24 May 2018 22:57:13 -0700 Subject: binding: nfc: new initial binding Slight rewrite to use libnfc initially for getting tag uid's for user settings. Bug-AGL: SPEC-1554 Change-Id: I7b8c30102b82e86a92c89909bcbfba9ab7164c1f Signed-off-by: Matt Ranostay --- src/libnfc_reader.c | 478 ---------------------------------------------------- 1 file changed, 478 deletions(-) delete mode 100644 src/libnfc_reader.c (limited to 'src/libnfc_reader.c') diff --git a/src/libnfc_reader.c b/src/libnfc_reader.c deleted file mode 100644 index 78269db..0000000 --- a/src/libnfc_reader.c +++ /dev/null @@ -1,478 +0,0 @@ -#include "nfc-binding.h" - -#include -#include -#include -#include - -// FIXME: It compile without these lines, but KDevelop complains about pthread_t being undeclared. -#ifndef _BITS_PTHREADTYPES -typedef unsigned long int pthread_t; -#endif - -#include -#include "libnfc_reader.h" -#include "stringutils.h" - -extern struct afb_event on_nfc_target_add_event; -extern struct afb_event on_nfc_target_remove_event; - -#define MAX_NFC_DEVICE_COUNT 8 -#define MAX_NFC_MODULATIONS 8 -#define MAX_NFC_BAUDRATES 8 -#define POLL_NUMBER 0x1 -#define POLL_PERIOD 0x7 - -typedef struct libnfc_device_tag -{ - pthread_t poller; - nfc_device* device; - nfc_connstring name; - - nfc_modulation* modulations; - size_t modulations_count; -} libnfc_device; - -typedef struct libnfc_context_tag -{ - nfc_context* context; - libnfc_device* devices; - size_t devices_count; - struct json_object* last_target; -} libnfc_context; - -static libnfc_context libnfc; - -void libnfc_polling_error(int code) -{ - switch(code) - { - case NFC_EIO: - AFB_ERROR("libnfc: polling failed with NFC_EIO (%d) code: Input / output error, device may not be usable anymore without re-open it!", code); - break; - case NFC_EINVARG: - AFB_ERROR("libnfc: polling failed with NFC_EINVARG (%d) code: Invalid argument(s)!", code); - break; - case NFC_EDEVNOTSUPP: - AFB_ERROR("libnfc: polling failed with NFC_EDEVNOTSUPP (%d) code: Operation not supported by device!", code); - break; - case NFC_ENOTSUCHDEV: - AFB_ERROR("libnfc: polling failed with NFC_ENOTSUCHDEV (%d) code: No such device!", code); - break; - case NFC_EOVFLOW: - AFB_ERROR("libnfc: polling failed with NFC_EOVFLOW (%d) code: Buffer overflow!", code); - break; - case NFC_ETIMEOUT: - AFB_ERROR("libnfc: polling failed with NFC_ETIMEOUT (%d) code: Operation timed out!", code); - break; - case NFC_EOPABORTED: - AFB_ERROR("libnfc: polling failed with NFC_EOPABORTED (%d) code: Operation aborted (by user)!", code); - break; - case NFC_ENOTIMPL: - AFB_ERROR("libnfc: polling failed with NFC_ENOTIMPL (%d) code: Not (yet) implemented!", code); - break; - case NFC_ETGRELEASED: - AFB_ERROR("libnfc: polling failed with NFC_ETGRELEASED (%d) code: Target released!", code); - break; - case NFC_ERFTRANS: - AFB_ERROR("libnfc: polling failed with NFC_ERFTRANS (%d) code: Error while RF transmission!", code); - break; - case NFC_EMFCAUTHFAIL: - AFB_ERROR("libnfc: polling failed with NFC_EMFCAUTHFAIL (%d) code: MIFARE Classic: authentication failed!", code); - break; - case NFC_ESOFT: - AFB_ERROR("libnfc: polling failed with NFC_ESOFT (%d) code: Software error (allocation, file/pipe creation, etc.)!", code); - break; - case NFC_ECHIP: - //AFB_ERROR("libnfc: polling failed with NFC_ECHIP (%d) code: Device's internal chip error!", code); - break; - default: - AFB_ERROR("libnfc: polling failed with unknown code: %d!", code); - break; - } -} - -void add_nfc_field(struct json_object* parent, const char* field, const void* src, size_t sz) -{ - char* data; - - if (parent && field && src && sz) - { - data = to_hex_string(src, sz); - if (data) - { - json_object_object_add(parent, field, json_object_new_string(data)); - free(data); - } - } -} - -struct json_object* read_target(const nfc_target* target) -{ - struct json_object* result; - const char* mt; - - if (!target) - { - AFB_WARNING("libnfc: No target to read!"); - return NULL; - } - - result = json_object_new_object(); - mt = str_nfc_modulation_type(target->nm.nmt); - json_object_object_add(result, "Type", json_object_new_string(mt)); - - switch(target->nm.nmt) - { - case NMT_ISO14443A: - add_nfc_field(result, "ATQA", target->nti.nai.abtAtqa, 2); - add_nfc_field(result, "SAK", &target->nti.nai.btSak, 1); - add_nfc_field(result, "UID", target->nti.nai.abtUid, target->nti.nai.szUidLen); - add_nfc_field(result, "ATS", target->nti.nai.abtAts, target->nti.nai.szAtsLen); - - break; - case NMT_ISO14443B: - add_nfc_field(result, "PUPI", target->nti.nbi.abtPupi, 4); - add_nfc_field(result, "Application Data", target->nti.nbi.abtApplicationData, 4); - add_nfc_field(result, "Protocol Info", target->nti.nbi.abtProtocolInfo, 3); - add_nfc_field(result, "Card Id", &target->nti.nbi.ui8CardIdentifier, 1); - - break; - default: - AFB_WARNING("libnfc: unsupported modulation type: %s.", mt); - json_object_object_add(result, "error", json_object_new_string("unsupported tag type")); - break; - } - return result; -} - -void* libnfc_reader_main(void* arg) -{ - libnfc_device* device; - nfc_target nt; - int polled_target_count; - nfc_modulation mods[MAX_NFC_MODULATIONS]; - struct json_object* result; - size_t i, j; - - device = (libnfc_device*)arg; - - memset(mods, 0, sizeof(nfc_modulation) * MAX_NFC_MODULATIONS); - for(i = 0, j = 0; i < device->modulations_count; ++i, ++j) - { - switch(device->modulations[i].nmt) - { -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_ISO14443A) - case NMT_ISO14443A: -#endif -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_ISOJEWEL) - case NMT_JEWEL: -#endif -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_ISO14443B) - case NMT_ISO14443B: -#endif -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_ISO14443BI) - case NMT_ISO14443BI: -#endif -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_ISO14443B2SR) - case NMT_ISO14443B2SR: -#endif -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_ISO14443B2CT) - case NMT_ISO14443B2CT: -#endif -#if defined(LIBNFC_POLL_ALL) || defined(LIBNFC_POLL_NMT_FELICA) - case NMT_FELICA: -#endif - mods[j] = device->modulations[i]; - AFB_NOTICE("libnfc: polling for %s at %s is ENABLED.", str_nfc_modulation_type(device->modulations[i].nmt), str_nfc_baud_rate(device->modulations[i].nbr)); - break; - default: - --j; - // NMT_DEP is always disabled because it can't be polled - AFB_NOTICE("libnfc: polling for %s at %s is DISABLED.", str_nfc_modulation_type(device->modulations[i].nmt), str_nfc_baud_rate(device->modulations[i].nbr)); - break; - } - } - - while(device->device) - { - polled_target_count = nfc_initiator_poll_target - ( - device->device, - mods, - j, - POLL_NUMBER, - POLL_PERIOD, - &nt - ); - - switch(polled_target_count) - { - case 0: - // No target detected - AFB_INFO("libnfc: polling done with no result."); - if (libnfc.last_target) - { - AFB_NOTICE("libnfc: tag removed = %s", json_object_to_json_string(libnfc.last_target)); - afb_event_push(on_nfc_target_remove_event, libnfc.last_target); - libnfc.last_target = NULL; - } - break; - - case 1: - AFB_INFO("libnfc: polling done with one result."); - // One target detected - result = read_target(&nt); - - if (libnfc.last_target) - { - if (strcmp(json_object_to_json_string(result), json_object_to_json_string(libnfc.last_target))) - { - AFB_NOTICE("libnfc: tag removed = %s", json_object_to_json_string(libnfc.last_target)); - afb_event_push(on_nfc_target_remove_event, libnfc.last_target); - libnfc.last_target = NULL; - } - } - - if (!libnfc.last_target) - { - json_object_get(result); - libnfc.last_target = result; - - AFB_NOTICE("libnfc: tag added = %s", json_object_to_json_string(result)); - afb_event_push(on_nfc_target_add_event, result); - } - break; - - default: - if (polled_target_count < 0) libnfc_polling_error(polled_target_count); - else AFB_WARNING("libnfc: polling done with unsupported result count: %d.", polled_target_count); - - // Consider target is removed - if (libnfc.last_target) - { - AFB_NOTICE("libnfc: tag removed = %s", json_object_to_json_string(libnfc.last_target)); - afb_event_push(on_nfc_target_remove_event, libnfc.last_target); - libnfc.last_target = NULL; - } - break; - } - } - return NULL; -} - -void exit_handler() -{ - size_t i; - nfc_device* dev; - for(i = 0; i < libnfc.devices_count; ++i) - { - if (libnfc.devices[i].device) - { - dev = libnfc.devices[i].device; - libnfc.devices[i].device = NULL; - nfc_close(dev); - } - } - nfc_exit(libnfc.context); - libnfc.context = NULL; -} - -void sigterm_handler(int sig) -{ - if (sig == SIGTERM && libnfc.context && libnfc.devices_count) - { - exit_handler(); - } -} - -/// @brief Start the libnfc context. -/// @return An exit code, @c EXIT_LIBNFC_SUCCESS (zero) on success. -int libnfc_init() -{ - nfc_device* dev; - const nfc_modulation_type* modulations; - const nfc_baud_rate* baudrates; - size_t modulation_idx; - nfc_connstring connstrings[MAX_NFC_DEVICE_COUNT]; - size_t ref_device_count; - size_t device_idx; - - atexit(exit_handler); - - memset(&libnfc, 0, sizeof(libnfc_context)); - - nfc_init(&libnfc.context); - if (libnfc.context == NULL) - { - AFB_ERROR("[libnfc] Initialization failed (malloc)!"); - return EXIT_LIBNFC_NOT_INITIALIZED; - } - - AFB_NOTICE("[libnfc] Using libnfc version: %s.", nfc_version()); - - // Find and register devices - ref_device_count = nfc_list_devices(libnfc.context, connstrings, MAX_NFC_DEVICE_COUNT); - if (!ref_device_count) - { - AFB_ERROR("libnfc: No NFC device found!"); - return EXIT_LIBNFC_NO_DEVICE_FOUND; - } - libnfc.devices_count = ref_device_count; - libnfc.devices = malloc(sizeof(libnfc_device) * libnfc.devices_count); - memset(libnfc.devices, 0, sizeof(libnfc_device) * libnfc.devices_count); - - signal(SIGTERM, sigterm_handler); - - for(device_idx = 0; device_idx < ref_device_count; ++device_idx) - { - AFB_NOTICE("libnfc: NFC Device found: \"%s\".", connstrings[device_idx]); - strcpy(libnfc.devices[device_idx].name, connstrings[device_idx]); - - // Find and register modulations - dev = nfc_open(libnfc.context, connstrings[device_idx]); - if (dev) - { - if (nfc_device_get_supported_modulation(dev, N_INITIATOR, &modulations)) - { - AFB_ERROR("libnfc: Failed to get supported modulations from '%s'!", connstrings[device_idx]); - } - else - { - // Find and register modulations - modulation_idx = 0; - while(modulations[modulation_idx]) ++modulation_idx; - libnfc.devices[device_idx].modulations_count = modulation_idx; - if (modulation_idx) - { - libnfc.devices[device_idx].modulations = malloc(sizeof(nfc_modulation) * modulation_idx); - memset(libnfc.devices[device_idx].modulations, 0, sizeof(nfc_modulation) * modulation_idx); - - modulation_idx = 0; - while(modulations[modulation_idx]) - { - libnfc.devices[device_idx].modulations[modulation_idx].nmt = modulations[modulation_idx]; - if (!nfc_device_get_supported_baud_rate(dev, modulations[modulation_idx], &baudrates)) - { - // Keep only the first speed which is supposed to be the fastest - libnfc.devices[device_idx].modulations[modulation_idx].nbr = baudrates[0]; - } - - AFB_NOTICE("libnfc: - Modulation '%s' supported at '%s'." - , str_nfc_modulation_type(libnfc.devices[device_idx].modulations[modulation_idx].nmt) - , str_nfc_baud_rate(libnfc.devices[device_idx].modulations[modulation_idx].nbr)); - ++modulation_idx; - } - } - } - nfc_close(dev); - } - } - - return EXIT_LIBNFC_SUCCESS; -} - -/// @brief List devices founds by libnfc. -/// @param[in] result A json object array into which found devices are added. -/// @return An exit code, @c EXIT_LIBNFC_SUCCESS (zero) on success. -int libnfc_list_devices(struct json_object* result) -{ - struct json_object* device; - size_t i; - - for(i = 0; i < libnfc.devices_count; ++i) - { - device = json_object_new_object(); - json_object_object_add(device, "source", json_object_new_string("libnfc")); - json_object_object_add(device, "name", json_object_new_string(libnfc.devices[i].name)); - json_object_array_add(result, device); - } - - return EXIT_LIBNFC_SUCCESS; -} - -int libnfc_list_devices_capabilities(struct json_object* result, struct json_object* devices) -{ - struct json_object* device; - struct json_object* mods; - struct json_object* mod; - size_t i, j; - - for(i = 0; i < libnfc.devices_count; ++i) - { - device = json_object_new_object(); - json_object_object_add(device, "source", json_object_new_string("libnfc")); - json_object_object_add(device, "name", json_object_new_string(libnfc.devices[i].name)); - mods = json_object_new_array(); - - for(j = 0; j < libnfc.devices[i].modulations_count; ++j) - { - mod = json_object_new_object(); - json_object_object_add(mod, "modulation", json_object_new_string(str_nfc_modulation_type(libnfc.devices[i].modulations[j].nmt))); - json_object_object_add(mod, "baudrate", json_object_new_string(str_nfc_baud_rate(libnfc.devices[i].modulations[j].nbr))); - json_object_array_add(mods, mod); - } - - json_object_object_add(device, "modulations", mods); - json_object_array_add(result, device); - } - - return EXIT_LIBNFC_SUCCESS; -} - -int libnfc_start_polling(struct json_object* result, struct json_object* devices) -{ - struct json_object* device; - size_t i; - int r; - - for(i = 0; i < libnfc.devices_count; ++i) - { - device = json_object_new_object(); - json_object_object_add(device, "source", json_object_new_string("libnfc")); - json_object_object_add(device, "name", json_object_new_string(libnfc.devices[i].name)); - if (libnfc.devices[i].device) - { - json_object_object_add(device, "status", json_object_new_string("already polling")); - AFB_NOTICE("libnfc: Device '%s' is already polling.", libnfc.devices[i].name); - } - else - { - libnfc.devices[i].device = nfc_open(libnfc.context, libnfc.devices[i].name); - if (libnfc.devices[i].device) - { - if (nfc_initiator_init(libnfc.devices[i].device) < 0) - { - nfc_close(libnfc.devices[i].device); - libnfc.devices[i].device = NULL; - json_object_object_add(device, "status", json_object_new_string("failed to set initiator mode")); - AFB_ERROR("libnfc: nfc_initiator_init failedfor device '%s'!", libnfc.devices[i].name); - } - else - { - r = pthread_create(&libnfc.devices[i].poller, NULL, libnfc_reader_main, (void*)&libnfc.devices[i]); - if (r) - { - nfc_close(libnfc.devices[i].device); - libnfc.devices[i].device = NULL; - json_object_object_add(device, "status", json_object_new_string("failed to create the polling thread")); - AFB_ERROR("libnfc: pthread_create failed!"); - } - else - { - json_object_object_add(device, "status", json_object_new_string("polling")); - AFB_NOTICE("libnfc: Polling the device '%s'.", libnfc.devices[i].name); - } - } - } - else - { - json_object_object_add(device, "status", json_object_new_string("failed to open device")); - AFB_ERROR("libnfc: Failed to open device '%s'!", libnfc.devices[i].name); - } - } - json_object_array_add(result, device); - } - - return EXIT_LIBNFC_SUCCESS; -} -- cgit 1.2.3-korg