From a78b46e4824e5eba4103df52b997bfb871ce096e Mon Sep 17 00:00:00 2001 From: Raquel Medina Date: Thu, 22 Nov 2018 16:07:21 +0200 Subject: binding: nfc: Fix segmentation fault. Bug-AGL: SPEC-1959 Duplicate reply (xreq_reply_cb) causes the segmentation fault when the adapter is plugged in at boot time. Several changes have been applied to fix this issue: - remove reply on subscribe for presence_event(only reply from loop); - power the adapter up only after configuration is complete; - update req & api artifacts to implement v3 bindings. Change-Id: I945de9dc1fee0a95859f28b9d77b627cb998fa1b Signed-off-by: Raquel Medina --- binding/afm-nfc-binding.c | 139 ++++++++++++++++++++++++++++------------------ 1 file changed, 84 insertions(+), 55 deletions(-) diff --git a/binding/afm-nfc-binding.c b/binding/afm-nfc-binding.c index 94705de..40caa5a 100644 --- a/binding/afm-nfc-binding.c +++ b/binding/afm-nfc-binding.c @@ -41,8 +41,8 @@ static void neard_cb_record_found(const char *tag_name, void *ptr) { nfc_binding_data *data = ptr; neardal_record *record; - int ret = neardal_get_record_properties(tag_name, &record); + int ret = neardal_get_record_properties(tag_name, &record); if (ret == NEARDAL_SUCCESS) { GVariantIter iter; char *s = NULL; @@ -51,7 +51,8 @@ static void neard_cb_record_found(const char *tag_name, void *ptr) json_object *jdict = json_object_new_object(); g_variant_iter_init(&iter, value); - json_object_object_add(jresp, "status", json_object_new_string("detected")); + json_object_object_add(jresp, "status", + json_object_new_string("detected")); while (g_variant_iter_loop(&iter, "{sv}", &s, &v)) { gchar *str; @@ -59,11 +60,10 @@ static void neard_cb_record_found(const char *tag_name, void *ptr) if (g_strcmp0("Name", s) == 0) continue; - str = g_variant_print(v, 0); + str = g_variant_print(v, 0); str[strlen(str) - 1] = '\0'; - - json_object_object_add(jdict, s, json_object_new_string(str + 1)); - + json_object_object_add(jdict, s, + json_object_new_string(str + 1)); g_free(str); } @@ -77,7 +77,7 @@ static void neard_cb_record_found(const char *tag_name, void *ptr) pthread_mutex_unlock(&mutex); afb_event_push(presence_event, jresp); - } + } } static void neard_cb_tag_removed(const char *tag_name, void *ptr) @@ -92,14 +92,15 @@ static void neard_cb_tag_removed(const char *tag_name, void *ptr) } pthread_mutex_unlock(&mutex); - json_object_object_add(jresp, "status", json_object_new_string("removed")); + json_object_object_add(jresp, "status", + json_object_new_string("removed")); afb_event_push(presence_event, jresp); g_main_loop_quit(data->loop); } -static void *neard_loop_thread(void *ptr) +static void *poll_adapter(void *ptr) { nfc_binding_data *data = ptr; int ret; @@ -109,10 +110,22 @@ static void *neard_loop_thread(void *ptr) 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; + } + while (1) { ret = neardal_start_poll(data->adapter); - if (ret != NEARDAL_SUCCESS) + if ((ret != NEARDAL_SUCCESS) && + (ret != NEARDAL_ERROR_POLLING_ALREADY_ACTIVE)) break; g_main_loop_run(data->loop); @@ -123,87 +136,103 @@ static void *neard_loop_thread(void *ptr) return NULL; } -static int init(afb_api_t api) +static int get_adapter(nfc_binding_data *data, unsigned int id) { - pthread_t thread_id; - nfc_binding_data *data = NULL; char **adapters = NULL; int num_adapters, ret; - presence_event = afb_daemon_make_event("presence"); - ret = neardal_get_adapters(&adapters, &num_adapters); + if (ret != NEARDAL_SUCCESS) { + AFB_API_DEBUG(afbBindingV3root, + "failed to find adapters ret=0x%x (%s)", + ret, neardal_error_get_text(ret)); - if (ret == NEARDAL_SUCCESS) { - ret = neardal_set_adapter_property(adapters[0], NEARD_ADP_PROP_POWERED, GINT_TO_POINTER(1)); + return -EIO; + } - if (ret == NEARDAL_SUCCESS) { - data = malloc(sizeof(nfc_binding_data)); + if (id > num_adapters - 1) { + AFB_API_DEBUG(afbBindingV3root, + "adapter out of range (%d - %d)", + id, num_adapters); + return -EINVAL; + } - if (data == NULL) - return -ENOMEM; + data->adapter = g_strdup(adapters[id]); + neardal_free_array(&adapters); - afb_api_set_userdata(api, data); + return ret; +} - data->adapter = g_strdup(adapters[0]); - ret = pthread_create(&thread_id, NULL, neard_loop_thread, data); - } +static int init(afb_api_t api) +{ + nfc_binding_data *data; + pthread_t thread_id; + int ret; + + data = g_malloc0(sizeof(nfc_binding_data)); + + 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; } - neardal_free_array(&adapters); + /* get the first adapter */ + ret = get_adapter(data, 0); + if (ret != NEARDAL_SUCCESS) + return 0; + + 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) + AFB_API_ERROR(api, "polling pthread creation failed"); return 0; } static void subscribe(afb_req_t request) { - const char *value = afb_req_value(request, "value"); - afb_api_t api = afb_req_get_api(request); - nfc_binding_data *data = afb_api_get_userdata(api); - - if (value && !strcasecmp(value, "presence")) { - afb_req_subscribe(request, presence_event); - afb_req_success(request, NULL, NULL); - - // send initial tag if exists - pthread_mutex_lock(&mutex); - if (data && data->jresp) { - json_object_get(data->jresp); - afb_event_push(presence_event, data->jresp); - } - pthread_mutex_unlock(&mutex); + if (afb_req_subscribe(request, presence_event) < 0) { + AFB_REQ_ERROR(request, "subscribe to presence_event failed"); + afb_req_reply(request, NULL, "failed", "Invalid event"); return; } - afb_req_fail(request, "failed", "Invalid event"); + afb_req_reply(request, NULL, NULL, NULL); } static void unsubscribe(afb_req_t request) { - const char *value = afb_req_value(request, "value"); + if (afb_req_unsubscribe(request, presence_event) < 0) { + AFB_REQ_ERROR(request, + "unsubscribe to presence_event failed"); + afb_req_reply(request, NULL, "failed", "Invalid event"); - if (value && !strcasecmp(value, "presence")) { - afb_req_unsubscribe(request, presence_event); - afb_req_success(request, NULL, NULL); return; } - afb_req_fail(request, "failed", "Invalid event"); + afb_req_reply(request, NULL, NULL, NULL); } -static const struct afb_verb_v3 binding_verbs[] = { - { .verb = "subscribe", .callback = subscribe, .info = "Subscribe to NFC events" }, - { .verb = "unsubscribe", .callback = unsubscribe, .info = "Unsubscribe to NFC events" }, +const afb_verb_t binding_verbs[] = { + { .verb = "subscribe", .callback = subscribe, + .info = "Subscribe to NFC events" }, + { .verb = "unsubscribe", .callback = unsubscribe, + .info = "Unsubscribe to NFC events" }, { } }; /* * binder API description */ -const struct afb_binding_v3 afbBindingV3 = { - .api = "nfc", - .specification = "NFC service API", - .verbs = binding_verbs, - .init = init, +const afb_binding_t afbBindingExport = { + .api = "nfc", + .specification = "NFC service API", + .info = "AGL nfc service", + .verbs = binding_verbs, + .init = init }; + -- cgit 1.2.3-korg