From b7cae49a6d1b4c5dba12647e2b30e635b8993a92 Mon Sep 17 00:00:00 2001 From: Raquel Medina Date: Sun, 25 Nov 2018 02:17:48 +0200 Subject: binding: nfc: Process content data from tag (adapter in tag reader mode) Bug-AGL: SPEC-1975 - Register callback for tag found - Update callback for record found - Fix memory leak Change-Id: I870648f3c5771aa1b54b710ef6b75786a1c67f65 Signed-off-by: Raquel Medina --- binding/afm-nfc-binding.c | 292 ++++++++++++++++++++++++++++++---------------- 1 file changed, 189 insertions(+), 103 deletions(-) (limited to 'binding') diff --git a/binding/afm-nfc-binding.c b/binding/afm-nfc-binding.c index 6fc26d9..1037227 100644 --- a/binding/afm-nfc-binding.c +++ b/binding/afm-nfc-binding.c @@ -31,109 +31,190 @@ #include #define AFB_BINDING_VERSION 3 #include - #include "afm-nfc-common.h" +#define STR(X) STR1(X) +#define STR1(X) #X + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static afb_event_t presence_event; -static void neard_cb_record_found(const char *tag_name, void *ptr) +static void __attribute__((unused)) dbg_dump_tag_records(neardal_tag *tag) { - nfc_binding_data *data = ptr; - neardal_record *record; + char **recs = tag->records; + int i; - int ret = neardal_get_record_properties(tag_name, &record); - if (ret == NEARDAL_SUCCESS) { - GVariantIter iter; - char *s = NULL; - GVariant *v, *value = (neardal_record_to_g_variant(record)); - json_object *jresp = json_object_new_object(); - json_object *jdict = json_object_new_object(); + if (!recs) { + AFB_API_DEBUG(afbBindingV3root, "tag empty!"); + return; + } - g_variant_iter_init(&iter, value); - json_object_object_add(jresp, "status", - json_object_new_string("detected")); + for (i = 0; recs[i] != NULL; i++) + AFB_API_DEBUG(afbBindingV3root, "tag record[n]: %s", recs[i]); - while (g_variant_iter_loop(&iter, "{sv}", &s, &v)) { - gchar *str; + return; +} - if (g_strcmp0("Name", s) == 0) - continue; - str = g_variant_print(v, 0); - str[strlen(str) - 1] = '\0'; - json_object_object_add(jdict, s, - json_object_new_string(str + 1)); - g_free(str); - } +static void __attribute__((unused)) dbg_dump_record_content(neardal_record record) +{ +#define DBG_RECORD(__x) if (record.__x) \ + AFB_API_DEBUG(afbBindingV3root, "record %s=%s", STR(__x), (record.__x)) + + DBG_RECORD(authentication); + DBG_RECORD(representation); + DBG_RECORD(passphrase); + DBG_RECORD(encryption); + DBG_RECORD(encoding); + DBG_RECORD(language); + DBG_RECORD(action); + DBG_RECORD(mime); + DBG_RECORD(type); + DBG_RECORD(ssid); + DBG_RECORD(uri); +} - json_object_object_add(jresp, "record", jdict); +static void record_found(const char *tag_name, void *ptr) +{ + json_object *jresp, *jdict, *jtemp; + nfc_binding_data *data = ptr; + neardal_record *record; + GVariant *value, *v = NULL; + GVariantIter iter; + char *s = NULL; + int ret; + + ret = neardal_get_record_properties(tag_name, &record); + if (ret != NEARDAL_SUCCESS) { + AFB_API_ERROR(afbBindingV3root, + "read record properties for %s tag, err:0x%x (%s)", + tag_name, ret, neardal_error_get_text(ret)); + return; + } - neardal_free_record(record); + value = neardal_record_to_g_variant(record); + jresp = json_object_new_object(); + jdict = json_object_new_object(); - pthread_mutex_lock(&mutex); - data->jresp = jresp; - json_object_get(jresp); - pthread_mutex_unlock(&mutex); + g_variant_iter_init(&iter, value); + json_object_object_add(jresp, + "status", json_object_new_string("detected")); - afb_event_push(presence_event, jresp); - } + while (g_variant_iter_loop(&iter, "{sv}", &s, &v)) { + gchar *str = g_variant_print(v, 0); + + str[strlen(str) - 1] = '\0'; + AFB_API_DEBUG(afbBindingV3root, + "%s tag, record %s= %s", tag_name, s, str); + + json_object_object_add(jdict, s, + json_object_new_string(str + 1)); + g_free(str); + } + + neardal_free_record(record); + + /* + * get record dictionary and look for 'Representation' field which should + * contain the uid value the identity agent needs. + * + */ + if (json_object_object_get_ex(jdict, "Representation", &jtemp)) { + const char *uid = json_object_get_string(jtemp); + + pthread_mutex_lock(&mutex); + data->jresp = jresp; + json_object_object_add(jresp, "uid", json_object_new_string(uid)); + pthread_mutex_unlock(&mutex); + + afb_event_push(presence_event, jresp); + AFB_API_DEBUG(afbBindingV3root, + "sent presence event, record content %s, tag %s", + uid, tag_name); + } + + return; } -static void neard_cb_tag_removed(const char *tag_name, void *ptr) +static void tag_found(const char *tag_name, void *ptr) { - nfc_binding_data *data = ptr; - json_object *jresp = json_object_new_object(); + neardal_tag *tag; + int ret; - pthread_mutex_lock(&mutex); - if (data->jresp) { - json_object_put(data->jresp); - data->jresp = NULL; - } - pthread_mutex_unlock(&mutex); - - json_object_object_add(jresp, "status", - json_object_new_string("removed")); + ret = neardal_get_tag_properties(tag_name, &tag); + if (ret != NEARDAL_SUCCESS) { + AFB_API_ERROR(afbBindingV3root, + "read tag %s properties, err:0x%x (%s)", + tag_name, ret, neardal_error_get_text(ret)); + return; + } + + dbg_dump_tag_records(tag); + neardal_free_tag(tag); + + return; +} + +static void tag_removed(const char *tag_name, void *ptr) +{ + nfc_binding_data *data = ptr; + json_object *jresp; + + pthread_mutex_lock(&mutex); + if (data->jresp) { + json_object_put(data->jresp); + data->jresp = NULL; + } + pthread_mutex_unlock(&mutex); - afb_event_push(presence_event, jresp); + jresp = json_object_new_object(); + json_object_object_add(jresp, "status", + json_object_new_string("removed")); + afb_event_push(presence_event, jresp); - g_main_loop_quit(data->loop); + AFB_API_DEBUG(afbBindingV3root, "%s tag removed, quit loop", tag_name); + g_main_loop_quit(data->loop); } static void *poll_adapter(void *ptr) { - nfc_binding_data *data = ptr; - int ret; - - data->loop = g_main_loop_new(NULL, FALSE); - - neardal_set_cb_tag_lost(neard_cb_tag_removed, ptr); - neardal_set_cb_record_found(neard_cb_record_found, ptr); - - ret = neardal_set_adapter_property(data->adapter, - NEARD_ADP_PROP_POWERED, - GINT_TO_POINTER(1)); - if (ret != NEARDAL_SUCCESS) { - AFB_API_DEBUG(afbBindingV3root, - "failed to power %s adapter on: ret=0x%x (%s)", - data->adapter, ret, neardal_error_get_text(ret)); - g_free(data->adapter); - return NULL; - } + nfc_binding_data *data = ptr; + int ret; - while (1) { - ret = neardal_start_poll(data->adapter); + data->loop = g_main_loop_new(NULL, FALSE); - if ((ret != NEARDAL_SUCCESS) && - (ret != NEARDAL_ERROR_POLLING_ALREADY_ACTIVE)) - break; + neardal_set_cb_tag_found(tag_found, ptr); + neardal_set_cb_tag_lost(tag_removed, ptr); + neardal_set_cb_record_found(record_found, ptr); - g_main_loop_run(data->loop); - } + ret = neardal_set_adapter_property(data->adapter, + NEARD_ADP_PROP_POWERED, + GINT_TO_POINTER(1)); + if (ret != NEARDAL_SUCCESS) { + AFB_API_DEBUG(afbBindingV3root, + "failed to power %s adapter on: ret=0x%x (%s)", + data->adapter, ret, neardal_error_get_text(ret)); + + goto out; + } + + for (;;) { + ret = neardal_start_poll(data->adapter); + + if ((ret != NEARDAL_SUCCESS) && + (ret != NEARDAL_ERROR_POLLING_ALREADY_ACTIVE)) + break; + + g_main_loop_run(data->loop); + } - g_free(data->adapter); + AFB_API_DEBUG(afbBindingV3root, "exiting polling loop"); - return NULL; +out: + g_free(data->adapter); + free(data); + + return NULL; } static int get_adapter(nfc_binding_data *data, unsigned int id) @@ -146,52 +227,59 @@ static int get_adapter(nfc_binding_data *data, unsigned int id) AFB_API_DEBUG(afbBindingV3root, "failed to find adapters ret=0x%x (%s)", ret, neardal_error_get_text(ret)); - return -EIO; } if (id > num_adapters - 1) { - AFB_API_DEBUG(afbBindingV3root, - "adapter out of range (%d - %d)", + AFB_API_DEBUG(afbBindingV3root, + "adapter out of range (%d - %d)", id, num_adapters); - return -EINVAL; + ret = -EINVAL; + goto out; } data->adapter = g_strdup(adapters[id]); - neardal_free_array(&adapters); +out: + neardal_free_array(&adapters); return ret; } static int init(afb_api_t api) { - nfc_binding_data *data; - pthread_t thread_id; - int ret; - - data = malloc(sizeof(nfc_binding_data)); - if (data == NULL) - return -ENOMEM; - - presence_event = afb_api_make_event(api, "presence"); - if (!afb_event_is_valid(presence_event)) { - AFB_API_ERROR(api, "Failed to create event"); - return -EINVAL; - } + nfc_binding_data *data; + pthread_t thread_id; + int ret; + + data = malloc(sizeof(nfc_binding_data)); + if (!data) + return -ENOMEM; + + presence_event = afb_api_make_event(api, "presence"); + if (!afb_event_is_valid(presence_event)) { + AFB_API_ERROR(api, "Failed to create event"); + free(data); + return -EINVAL; + } /* get the first adapter */ - ret = get_adapter(data, 0); - if (ret != NEARDAL_SUCCESS) - return 0; + ret = get_adapter(data, 0); + if (ret != NEARDAL_SUCCESS) { + free(data); + return 0; /* ignore error if no adapter */ + } AFB_API_DEBUG(api, " %s adapter found", data->adapter); afb_api_set_userdata(api, data); ret = pthread_create(&thread_id, NULL, poll_adapter, data); - if (ret) + if (ret) { AFB_API_ERROR(api, "polling pthread creation failed"); + g_free(data->adapter); + free(data); + } - return 0; + return 0; } static void subscribe(afb_req_t request) @@ -202,15 +290,14 @@ static void subscribe(afb_req_t request) return; } - + afb_req_reply(request, NULL, NULL, NULL); } static void unsubscribe(afb_req_t request) { if (afb_req_unsubscribe(request, presence_event) < 0) { - AFB_REQ_ERROR(request, - "unsubscribe to presence_event failed"); + AFB_REQ_ERROR(request, "unsubscribe to presence_event failed"); afb_req_reply(request, NULL, "failed", "Invalid event"); return; @@ -219,10 +306,10 @@ static void unsubscribe(afb_req_t request) afb_req_reply(request, NULL, NULL, NULL); } -const afb_verb_t binding_verbs[] = { - { .verb = "subscribe", .callback = subscribe, +static const afb_verb_t binding_verbs[] = { + { .verb = "subscribe", .callback = subscribe, .info = "Subscribe to NFC events" }, - { .verb = "unsubscribe", .callback = unsubscribe, + { .verb = "unsubscribe", .callback = unsubscribe, .info = "Unsubscribe to NFC events" }, { .verb = NULL } }; @@ -240,4 +327,3 @@ const afb_binding_t afbBindingExport = { .onevent = NULL, .noconcurrency = 0 }; - -- cgit 1.2.3-korg