summaryrefslogtreecommitdiffstats
path: root/binding-wifi/wifi-api.c
diff options
context:
space:
mode:
authorMatt Ranostay <matt.ranostay@konsulko.com>2017-06-29 19:01:55 -0700
committerMatt Ranostay <matt.ranostay@konsulko.com>2017-06-30 11:57:16 -0700
commitdfd034fb6016ad056131b17b30a0457789b791b9 (patch)
treec3b0e1ae6d892a44a011f080f978da37e3365473 /binding-wifi/wifi-api.c
parentca66ba0579e6c1e9a6d484f18633fdbd223a5bb5 (diff)
binding: wifi: make system wide service
Allow WiFi binding to be build separately and installed as a system wide service Bug-AGL: SPEC-661 SPEC-715 Change-Id: Id9eb9d9efae3f0bc3ab00641eb26cd1b5dae9d53 Signed-off-by: Matt Ranostay <matt.ranostay@konsulko.com>
Diffstat (limited to 'binding-wifi/wifi-api.c')
-rw-r--r--binding-wifi/wifi-api.c789
1 files changed, 789 insertions, 0 deletions
diff --git a/binding-wifi/wifi-api.c b/binding-wifi/wifi-api.c
new file mode 100644
index 0000000..30552e8
--- /dev/null
+++ b/binding-wifi/wifi-api.c
@@ -0,0 +1,789 @@
+/* Copyright 2016 ALPS ELECTRIC CO., LTD.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/**
+ * \file
+ *
+ * \brief Implementation of WiFi Binder for AGL's App Framework
+ *
+ * \author ALPS Electric
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <json-c/json.h>
+#include <afb/afb-binding.h>
+
+#include "wifi-api.h"
+#include "wifi-connman.h"
+
+
+
+static int need_passkey_flag = 0;
+static int passkey_not_correct_flag = 0;
+
+char *passkey;
+callback ptr_my_callback;
+callback wifiListChanged_clbck;
+
+GSList *wifi_list = NULL;
+
+
+/**
+ * \brief Input the passkey for connection to AP.
+ *
+ * \param[in] passkey pasword for the network
+ *
+ * The user should first subscribe for the event 'passkey' and then provide passkey
+ * when this event has been received.
+ *
+ * */
+static void insertpasskey(struct afb_req request) {
+
+
+ const char *passkey_from_user;
+
+ /* retrieves the argument, expects passkey string */
+ passkey_from_user = afb_req_value(request, "passkey");
+
+ NOTICE(afbitf, "Passkey inserted: %s\n", passkey_from_user);
+
+ sendPasskey(passkey_from_user);
+
+
+ if (passkey != NULL) {
+
+ registerPasskey(passkey);
+ } else {
+ NOTICE(afbitf, "Please enter the passkey first\n");
+
+ }
+}
+
+
+
+struct event
+{
+ struct event *next;
+ struct afb_event event;
+ char tag[1];
+};
+
+static struct event *events = 0;
+
+/**
+ * \internal
+ * \brief Helper function that searches for a specific event.
+ *
+ * \param[in] tag of the event
+ */
+static struct event *event_get(const char *tag)
+{
+ struct event *e = events;
+ while(e && strcmp(e->tag, tag))
+ e = e->next;
+ return e;
+}
+
+/**
+ * \internal
+ * \brief Helper function that actually pushes the event.
+ *
+ * \param[in] tag of the event
+ * \param[in] *args json object that contains data for the event
+ *
+ */
+static int do_event_push(struct json_object *args, const char *tag)
+{
+ struct event *e;
+ e = event_get(tag);
+ return e ? afb_event_push(e->event, json_object_get(args)) : -1;
+}
+
+/**
+ * \internal
+ * \brief Pushes the event of 'tag' with the 'data
+ *
+ * \param[in] tag
+ * \param[in] data
+ *
+ */
+static void eventpush (struct afb_req request)
+{
+ const char *tag = afb_req_value(request, "tag");
+ const char *data = afb_req_value(request, "data");
+ json_object *object = data ? json_tokener_parse(data) : NULL;
+
+ if (tag == NULL)
+ afb_req_fail(request, "failed", "bad arguments");
+ else if (0 > do_event_push(object, tag))
+ afb_req_fail(request, "failed", "push error");
+ else
+ afb_req_success(request, NULL, NULL);
+}
+
+/**
+ *
+ * \brief Notify user that passkey is necessary.
+ *
+ * \param[in] number additional integer data produced by Agent
+ * \param[in] asciidata additional ascii data produced by Agent
+ *
+ * This function is called from the registered agent on RequestInput() call.
+ *
+ */
+void ask_for_passkey(int number, const char* asciidata) {
+ NOTICE(afbitf, "Passkey for %s network needed.", asciidata);
+ NOTICE(afbitf, "Sending event.");
+
+ json_object *jresp = json_object_new_object();
+
+ json_object *int1 = json_object_new_int(number);
+ json_object *string = json_object_new_string(asciidata);
+
+ json_object_object_add(jresp, "data1", int1);
+ json_object_object_add(jresp, "data2", string);
+
+
+ do_event_push(jresp, "passkey");
+}
+
+/**
+ * \internal
+ * \brief Notify GUI that wifi list has changed.
+ *
+ * \param[in] number number of event that caused the callback
+ * \param[in] asciidata additional data, e.g "BSSRemoved"
+ *
+ * User should first subscribe for the event 'networkList' and then wait for this event.
+ * When notification comes, update the list if networks by scan_result call.
+ *
+ */
+void wifiListChanged(int number, const char* asciidata) {
+
+ //WARNING(afbitf, "wifiListChanged, reason:%d, %s",number, asciidata );
+
+
+ json_object *jresp = json_object_new_object();
+
+ json_object *int1 = json_object_new_int(number);
+ json_object *string = json_object_new_string(asciidata);
+
+ json_object_object_add(jresp, "data1", int1);
+ json_object_object_add(jresp, "data2", string);
+
+ do_event_push(jresp, "networkList");
+
+
+
+}
+
+
+/**
+ * \brief Initializes the binder and activates the WiFi HW, should be called first.
+ *
+ * \param[in] request no specific data needed
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ *
+ * This will fail if
+ * - agent for handling passkey requests cannot be registered
+ * - some error is returned from connman
+ */
+static void activate(struct afb_req request) /*AFB_SESSION_CHECK*/
+{
+ json_object *jresp;
+ GError *error = NULL;
+
+ if (ptr_my_callback == NULL) {
+
+ ptr_my_callback = ask_for_passkey;
+ register_callbackSecurity(ptr_my_callback);
+
+ }
+
+ if (wifiListChanged_clbck == NULL) {
+
+ wifiListChanged_clbck = wifiListChanged;
+ register_callbackWiFiList(wifiListChanged_clbck);
+
+ }
+
+ jresp = json_object_new_object();
+ json_object_object_add(jresp, "activation", json_object_new_string("on"));
+
+ error = do_wifiActivate();
+
+ if (error == NULL) {
+
+ afb_req_success(request, jresp, "Wi-Fi - Activated");
+
+ } else
+
+ afb_req_fail(request, "failed", error->message);
+
+}
+
+/**
+ * \brief Deinitializes the binder and deactivates the WiFi HW.
+ *
+ * \param[in] request no specific data needed
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ *
+ * This will fail if
+ * - agent for handling passkey requests cannot be unregistered
+ * - some error is returned from connman
+ *
+ */
+static void deactivate(struct afb_req request) /*AFB_SESSION_CHECK*/
+{
+
+ json_object *jresp;
+ GError *error = NULL;
+
+ ptr_my_callback = NULL;
+
+ jresp = json_object_new_object();
+ json_object_object_add(jresp, "deactivation", json_object_new_string("on"));
+
+ error = do_wifiDeactivate();
+
+ if (error == NULL) {
+
+ afb_req_success(request, jresp, "Wi-Fi - Activated");
+
+ } else
+
+ afb_req_fail(request, "failed", error->message);
+}
+
+/**
+ * \brief Starts scan for access points.
+ *
+ * \param[in] request no specific data needed
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ *
+ * User should first subscribe for the event 'networkList' and then wait for event to come.
+ * When notification comes, update the list of networks by scan_result call.
+ */
+static void scan(struct afb_req request) /*AFB_SESSION_NONE*/
+{
+ GError *error = NULL;
+
+ error = do_wifiScan();
+
+ if (error == NULL) {
+
+ afb_req_success(request, NULL, "Wi-Fi - Scan success");
+
+ } else
+
+ afb_req_fail(request, "failed", error->message);
+
+}
+
+/**
+ * \brief Return network list.
+ *
+ * \param[in] request no specific data needed
+ *
+ * \return result of the request, either "success" or "failed" with description of error \n
+ * result is array of following json objects: Number, Strength, ESSID, Security, IPAddress, State.
+ * E.g. {"Number":0,"Strength":82,"ESSID":"wifidata02","Security":"ieee8021x","IPAddress":"unsigned","State":"idle"}, or \n
+ * {"Number":1,"Strength":51,"ESSID":"ALCZM","Security":"WPA-PSK","IPAddress":"192.168.1.124","State":"ready"}
+ */
+static void scan_result(struct afb_req request) /*AFB_SESSION_CHECK*/
+{
+ struct wifi_profile_info *wifiProfile = NULL;
+ GSList *list = NULL;
+ GSList *holdMe = NULL;
+ wifi_list = NULL;
+ char *essid = NULL;
+ char *address = NULL;
+ char *security = NULL;
+ char *state = NULL;
+ unsigned int strength = 0;
+ int number = 0;
+ GError *error = NULL;
+
+ error = do_displayScan(&wifi_list); /*Get wifi scan list*/
+ if (error == NULL) {
+ json_object *my_array = json_object_new_array();
+
+ for (list = wifi_list; list; list = list->next) { /*extract wifi scan result*/
+ wifiProfile = (struct wifi_profile_info *) list->data;
+ security = wifiProfile->Security.sec_type;
+ strength = wifiProfile->Strength;
+ //if (essid == NULL || security == NULL)
+ // continue;
+
+ essid = wifiProfile->ESSID == NULL ?
+ "HiddenSSID" : wifiProfile->ESSID;
+ address =
+ wifiProfile->wifiNetwork.IPaddress == NULL ?
+ "unsigned" : wifiProfile->wifiNetwork.IPaddress;
+ state = wifiProfile->state;
+ //TODO: is there a case when security is NULL?
+
+ json_object *int1 = json_object_new_int(number);
+ json_object *int2 = json_object_new_int(strength);
+ json_object *jstring1 = json_object_new_string(essid);
+ json_object *jstring2 = json_object_new_string(security);
+ json_object *jstring3 = json_object_new_string(address);
+ json_object *jstring4 = json_object_new_string(state);
+
+ json_object *jresp = json_object_new_object();
+ json_object_object_add(jresp, "Number", int1);
+ json_object_object_add(jresp, "Strength", int2);
+ json_object_object_add(jresp, "ESSID", jstring1);
+ json_object_object_add(jresp, "Security", jstring2);
+ json_object_object_add(jresp, "IPAddress", jstring3);
+ json_object_object_add(jresp, "State", jstring4);
+
+ DEBUG(afbitf, "The object json: %s\n", json_object_to_json_string(jresp));
+
+ /*input each scan result into my_array*/
+ json_object_array_add(my_array, jresp);
+ number += 1;
+
+ //set the HMI icon according to strength, only if "ready" or "online"
+
+ int error = 0;
+ struct wifiStatus *status;
+
+ status = g_try_malloc0(sizeof(struct wifiStatus));
+ error = wifi_state(status); /*get current status of power and connection*/
+ if (!error) {
+
+ if (status->connected == 1) {
+
+ if ((strcmp(state, "ready") == 0)
+ || ((strcmp(state, "online") == 0))) {
+
+ if (strength < 30)
+ setHMIStatus(BAR_1);
+ else if (strength < 50)
+ setHMIStatus(BAR_2);
+ else if (strength < 70)
+ setHMIStatus(BAR_3);
+ else
+ setHMIStatus(BAR_FULL);
+ }
+ } else
+ setHMIStatus(BAR_NO);
+ }
+
+ }
+ while (list != NULL) {
+ holdMe = list->next;
+ g_free(list);
+ list = holdMe;
+ }
+ afb_req_success(request, my_array, "Wi-Fi - Scan Result is Displayed");
+ } else
+ afb_req_fail(request, "failed", error->message);
+}
+
+/**
+ * \brief Connects to a specific network.
+ *
+ * \param[in] request Number of network to connect to.
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ *
+ * Specify number of network to connect to obtained by scan_result().
+ * User should first subscribe for the event 'passkey', if passkey
+ * is needed for connection this event is pushed.
+ *
+ */
+static void connect(struct afb_req request) {
+
+ struct wifi_profile_info *wifiProfileToConnect = NULL;
+
+ const char *network;
+ int network_index = 0;
+ GError *error = NULL;
+ GSList *item = NULL;
+
+ /* retrieves the argument, expects the network number */
+ network = afb_req_value(request, "network");
+
+ if (network == NULL)
+ //TODO:better error message
+ afb_req_fail(request, "failed",
+ "specify a network number to connect to");
+
+ else {
+ network_index = atoi(network);
+ NOTICE(afbitf,"Joining network number %d\n", network_index);
+
+
+ }
+
+ //get information about desired network
+ item = g_slist_nth_data(wifi_list, network_index);
+
+ if (item == NULL) {
+ //Index starts from 1
+ ERROR(afbitf, "Network with number %d not found.\n", network_index + 1);
+ //TODO:better error message
+ afb_req_fail(request, "failed", "bad arguments");
+ }
+
+ else {
+ wifiProfileToConnect = (struct wifi_profile_info *) item;
+ INFO(afbitf, "Name: %s, strength: %d, %s\n", wifiProfileToConnect->ESSID,
+ wifiProfileToConnect->Strength,
+ wifiProfileToConnect->NetworkPath);
+ }
+ error = do_connectNetwork(wifiProfileToConnect->NetworkPath);
+
+ if (error == NULL)
+ afb_req_success(request, NULL, NULL);
+
+ else if (passkey_not_correct_flag) {
+ need_passkey_flag = 0;
+ passkey_not_correct_flag = 0;
+ afb_req_fail(request, "passkey-incorrect", NULL);
+ } else if (need_passkey_flag) {
+ need_passkey_flag = 0;
+ afb_req_fail(request, "need-passkey", NULL);
+
+ } else
+ afb_req_fail(request, "failed", error->message);
+}
+
+/**
+ * \brief Disconnects from a network.
+ *
+ * \param[in] request number of network to disconnect from
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ *
+ * Specify number of network to disconnect from obtained by scan_result().
+ */
+static void disconnect(struct afb_req request) {
+
+ struct wifi_profile_info *wifiProfileToConnect = NULL;
+
+ const char *network;
+ int network_index = 0;
+ GError *error = NULL;
+ GSList *item = NULL;
+
+ /* retrieves the argument, expects the network number */
+ network = afb_req_value(request, "network");
+
+ if (network == NULL)
+ //TODO:better error message
+ afb_req_fail(request, "failed",
+ "specify a network number to disconnect from");
+
+ else {
+ network_index = atoi(network);
+ NOTICE(afbitf, "Joining network number %d\n", network_index);
+
+ }
+
+ //get information about desired network
+ item = g_slist_nth_data(wifi_list, network_index);
+
+ if (item == NULL) {
+ //Index starts from 1
+ ERROR(afbitf,"Network with number %d not found.\n", network_index + 1);
+ //TODO:better error message
+ afb_req_fail(request, "failed", "bad arguments");
+ }
+
+ else {
+ wifiProfileToConnect = (struct wifi_profile_info *) item;
+ INFO(afbitf, "Name: %s, strength: %d, %s\n", wifiProfileToConnect->ESSID,
+ wifiProfileToConnect->Strength,
+ wifiProfileToConnect->NetworkPath);
+ }
+ error = do_disconnectNetwork(wifiProfileToConnect->NetworkPath);
+
+ if (error == NULL)
+ afb_req_success(request, NULL, NULL);
+ else
+ afb_req_fail(request, "failed", error->message);
+}
+
+/**
+ * \brief Return current status of a connection.
+ *
+ * \param[in] request no specific data needed
+ *
+ * \return result of the request, either "success" with status or "failed" with description of error
+ */
+static void status(struct afb_req request) {
+ int error = 0;
+ wifi_list = NULL;
+ struct wifiStatus *status;
+ json_object *jresp = json_object_new_object();
+
+ status = g_try_malloc0(sizeof(struct wifiStatus));
+ error = wifi_state(status); /*get current status of power and connection*/
+ if (!error) {
+ if (status->state == 0) {/*Wi-Fi is OFF*/
+ json_object_object_add(jresp, "Power",
+ json_object_new_string("OFF"));
+ //json_object_object_add(jresp, "Connection", json_object_new_string("Disconnected"));
+ DEBUG(afbitf, "Wi-Fi OFF\n");
+ } else {/*Wi-Fi is ON*/
+ json_object_object_add(jresp, "Power",
+ json_object_new_string("ON"));
+ if (status->connected == 0) {/*disconnected*/
+ json_object_object_add(jresp, "Connection",
+ json_object_new_string("Disconnected"));
+ DEBUG(afbitf, "Wi-Fi ON - Disconnected \n");
+ } else {/*Connected*/
+ json_object_object_add(jresp, "Connection",
+ json_object_new_string("Connected"));
+ DEBUG(afbitf, "Wi-Fi ON - Connected \n");
+ }
+ }
+ afb_req_success(request, jresp, "Wi-Fi - Connection Status Checked");
+ } else {
+ afb_req_fail(request, "failed", "Wi-Fi - Connection Status unknown");
+ }
+}
+
+static void reconnect() {
+ /*TBD*/
+}
+
+
+
+/**
+ * \internal
+ * \brief Helper functions that actually delete the tag.
+ *
+ * \param[in] tag tag to delete
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static int event_del(const char *tag)
+{
+ struct event *e, **p;
+
+ /* check exists */
+ e = event_get(tag);
+ if (!e) return -1;
+
+ /* unlink */
+ p = &events;
+ while(*p != e) p = &(*p)->next;
+ *p = e->next;
+
+ /* destroys */
+ afb_event_drop(e->event);
+ free(e);
+ return 0;
+}
+
+/**
+ * \internal
+ * \brief Helper functions that actually creates event of the tag.
+ *
+ * \param[in] tag tag to add
+ * \param[in] name name to add
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static int event_add(const char *tag, const char *name)
+{
+ struct event *e;
+
+ /* check valid tag */
+ e = event_get(tag);
+ if (e) return -1;
+
+ /* creation */
+ e = malloc(strlen(tag) + sizeof *e);
+ if (!e) return -1;
+ strcpy(e->tag, tag);
+
+ /* make the event */
+ e->event = afb_daemon_make_event(afbitf->daemon, name);
+ if (!e->event.closure) { free(e); return -1; }
+
+ /* link */
+ e->next = events;
+ events = e;
+ return 0;
+}
+
+/**
+ * \brief Creates event of the tag.
+ *
+ * \param[in] request tag and name of the event
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static void eventadd (struct afb_req request)
+{
+ const char *tag = afb_req_value(request, "tag");
+ const char *name = afb_req_value(request, "name");
+
+ json_object *query = afb_req_json(request);
+
+ if (tag == NULL || name == NULL)
+ afb_req_fail(request, "failed", "bad arguments");
+ else if (0 != event_add(tag, name))
+ afb_req_fail(request, "failed", "creation error");
+ else
+ afb_req_success(request, NULL, NULL);
+}
+
+/**
+ * \brief Deletes the event of tag.
+ *
+ * \param[in] request tag to delete
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static void eventdel (struct afb_req request)
+{
+ const char *tag = afb_req_value(request, "tag");
+
+ if (tag == NULL)
+ afb_req_fail(request, "failed", "bad arguments");
+ else if (0 != event_del(tag))
+ afb_req_fail(request, "failed", "deletion error");
+ else
+ afb_req_success(request, NULL, NULL);
+}
+
+
+/**
+ * \internal
+ * \brief Helper functions to subscribe for the event of tag.
+ *
+ * \param[in] request tag to subscribe for
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static int event_subscribe(struct afb_req request, const char *tag)
+{
+ struct event *e;
+ e = event_get(tag);
+ return e ? afb_req_subscribe(request, e->event) : -1;
+}
+
+/**
+ * \internal
+ * \brief Helper functions to unsubscribe for the event of tag.
+ *
+ * \param[in] request tag to unsubscribe for
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static int event_unsubscribe(struct afb_req request, const char *tag)
+{
+ struct event *e;
+ e = event_get(tag);
+ return e ? afb_req_unsubscribe(request, e->event) : -1;
+}
+
+
+/**
+ * \brief Subscribes for the event of tag.
+ *
+ * \param[in] request tag to subscribe for
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static void eventsub (struct afb_req request)
+{
+ const char *tag = afb_req_value(request, "tag");
+
+ if (tag == NULL)
+ afb_req_fail(request, "failed", "bad arguments");
+ else if (0 != event_subscribe(request, tag))
+ afb_req_fail(request, "failed", "subscription error");
+ else
+ afb_req_success(request, NULL, NULL);
+}
+
+
+/**
+ * \brief Unsubscribes for the event of tag.
+ *
+ * \param[in] request tag to unsubscribe for
+ *
+ * \return result of the request, either "success" or "failed" with description of error
+ */
+static void eventunsub (struct afb_req request)
+{
+ const char *tag = afb_req_value(request, "tag");
+
+ if (tag == NULL)
+ afb_req_fail(request, "failed", "bad arguments");
+ else if (0 != event_unsubscribe(request, tag))
+ afb_req_fail(request, "failed", "unsubscription error");
+ else
+ afb_req_success(request, NULL, NULL);
+}
+
+
+/*
+ * array of the verbs exported to afb-daemon
+ */
+static const struct afb_verb_desc_v1 binding_verbs[] = {
+/* VERB'S NAME SESSION MANAGEMENT FUNCTION TO CALL SHORT DESCRIPTION */
+{ .name = "activate", .session = AFB_SESSION_NONE, .callback = activate, .info = "Activate Wi-Fi" },
+{ .name = "deactivate", .session = AFB_SESSION_NONE, .callback = deactivate, .info ="Deactivate Wi-Fi" },
+{ .name = "scan", .session = AFB_SESSION_NONE, .callback = scan, .info ="Scanning Wi-Fi" },
+{ .name = "scan_result", .session = AFB_SESSION_NONE, .callback = scan_result, .info = "Get scan result Wi-Fi" },
+{ .name = "connect", .session = AFB_SESSION_NONE, .callback = connect, .info ="Connecting to Access Point" },
+{ .name = "status", .session = AFB_SESSION_NONE, .callback = status, .info ="Check connection status" },
+{ .name = "disconnect", .session = AFB_SESSION_NONE, .callback = disconnect, .info ="Disconnecting connection" },
+{ .name = "reconnect", .session = AFB_SESSION_NONE, .callback = reconnect, .info ="Reconnecting to Access Point" },
+{ .name = "insertpasskey",.session = AFB_SESSION_NONE, .callback = insertpasskey, .info ="inputs the passkey after it has been requsted"},
+{ .name = "eventadd", .session = AFB_SESSION_NONE, .callback = eventadd, .info ="adds the event of 'name' for the 'tag'"},
+{ .name = "eventsub", .session = AFB_SESSION_NONE, .callback = eventsub, .info ="unsubscribes to the event of 'tag'"},
+{ .name = "eventpush", .session = AFB_SESSION_NONE, .callback = eventpush, .info ="pushes the event of 'tag' with the 'data'"},
+{ .name = "eventunsub", .session = AFB_SESSION_NONE, .callback = eventunsub, .info ="unsubscribes to the event of 'tag'"},
+{ .name = "eventdel", .session = AFB_SESSION_NONE, .callback = eventdel, .info ="deletes the event of 'tag'"},
+
+{ .name = NULL } /* marker for end of the array */
+};
+
+/*
+ * description of the binding for afb-daemon
+ */
+static const struct afb_binding binding_description = {
+/* description conforms to VERSION 1 */
+.type = AFB_BINDING_VERSION_1, .v1 = { /* fills the v1 field of the union when AFB_BINDING_VERSION_1 */
+.prefix = "wifi-manager", /* the API name (or binding name or prefix) */
+.info = "wifi API", /* short description of of the binding */
+.verbs = binding_verbs /* the array describing the verbs of the API */
+} };
+
+/*
+ * activation function for registering the binding called by afb-daemon
+ */
+const struct afb_binding *afbBindingV1Register(
+ const struct afb_binding_interface *itf) {
+ afbitf = itf; // records the interface for accessing afb-daemon
+ return &binding_description; // returns the description of the binding
+}
+