aboutsummaryrefslogtreecommitdiffstats
path: root/binding/afm-nfc-binding.c
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-23 13:53:07 +0200
commit557e5f053411a3319c4f3efb5c56ad09f0de553b (patch)
treee7ee4412185b39bbf8c0546992ce2382139502f5 /binding/afm-nfc-binding.c
parentf3849cef1c0e3e00b0c10ded6b6f6395394c2faf (diff)
binding: nfc: Fix segmentation fault.guppy_6.99.1guppy/6.99.16.99.1
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>
Diffstat (limited to 'binding/afm-nfc-binding.c')
-rw-r--r--binding/afm-nfc-binding.c248
1 files changed, 141 insertions, 107 deletions
diff --git a/binding/afm-nfc-binding.c b/binding/afm-nfc-binding.c
index 94705de..6fc26d9 100644
--- a/binding/afm-nfc-binding.c
+++ b/binding/afm-nfc-binding.c
@@ -34,176 +34,210 @@
#include "afm-nfc-common.h"
-static afb_event_t presence_event;
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)
{
- nfc_binding_data *data = ptr;
- neardal_record *record;
- int ret = neardal_get_record_properties(tag_name, &record);
+ nfc_binding_data *data = ptr;
+ neardal_record *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();
+ 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();
- g_variant_iter_init(&iter, value);
- json_object_object_add(jresp, "status", json_object_new_string("detected"));
+ g_variant_iter_init(&iter, value);
+ json_object_object_add(jresp, "status",
+ json_object_new_string("detected"));
- while (g_variant_iter_loop(&iter, "{sv}", &s, &v)) {
- gchar *str;
+ while (g_variant_iter_loop(&iter, "{sv}", &s, &v)) {
+ gchar *str;
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);
- }
+ 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);
+ }
- json_object_object_add(jresp, "record", jdict);
+ json_object_object_add(jresp, "record", jdict);
neardal_free_record(record);
- pthread_mutex_lock(&mutex);
- data->jresp = jresp;
- json_object_get(jresp);
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_lock(&mutex);
+ data->jresp = jresp;
+ json_object_get(jresp);
+ pthread_mutex_unlock(&mutex);
- afb_event_push(presence_event, jresp);
- }
+ afb_event_push(presence_event, jresp);
+ }
}
static void neard_cb_tag_removed(const char *tag_name, void *ptr)
{
- nfc_binding_data *data = ptr;
- json_object *jresp = json_object_new_object();
-
- 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"));
-
- afb_event_push(presence_event, jresp);
-
- g_main_loop_quit(data->loop);
+ nfc_binding_data *data = ptr;
+ json_object *jresp = json_object_new_object();
+
+ 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"));
+
+ 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;
+ nfc_binding_data *data = ptr;
+ int ret;
- data->loop = g_main_loop_new(NULL, FALSE);
+ 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);
+ neardal_set_cb_tag_lost(neard_cb_tag_removed, ptr);
+ neardal_set_cb_record_found(neard_cb_record_found, ptr);
- while (1) {
- ret = neardal_start_poll(data->adapter);
+ 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;
+ }
- if (ret != NEARDAL_SUCCESS)
- break;
+ while (1) {
+ ret = neardal_start_poll(data->adapter);
- g_main_loop_run(data->loop);
- }
+ if ((ret != NEARDAL_SUCCESS) &&
+ (ret != NEARDAL_ERROR_POLLING_ALREADY_ACTIVE))
+ break;
+
+ g_main_loop_run(data->loop);
+ }
- g_free(data->adapter);
+ g_free(data->adapter);
- return NULL;
+ 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;
- neardal_free_array(&adapters);
+ data = malloc(sizeof(nfc_binding_data));
+ if (data == NULL)
+ return -ENOMEM;
- return 0;
+ 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;
+ }
+
+ /* 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" },
+ { .verb = NULL }
};
/*
* 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,
+ .preinit = NULL,
+ .init = init,
+ .onevent = NULL,
+ .noconcurrency = 0
};
+