aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaquel Medina <raquel.medina@konsulko.com>2018-11-22 16:07:21 +0200
committerraquel medina <raquel.medina@konsulko.com>2018-11-28 13:56:33 +0000
commita78b46e4824e5eba4103df52b997bfb871ce096e (patch)
tree214ac14bcc2ef165160ec37d4862b35337c8b6c0
parent533dae6bd4359b72a365f0366fc41c08f3667fee (diff)
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 <raquel.medina@konsulko.com>
-rw-r--r--binding/afm-nfc-binding.c139
1 files 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
};
+