nfctool: Add a handler mechanism for netlink events
authorThierry Escande <thierry.escande@linux.intel.com>
Mon, 4 Mar 2013 13:49:17 +0000 (14:49 +0100)
committerSamuel Ortiz <sameo@linux.intel.com>
Mon, 4 Mar 2013 15:26:48 +0000 (16:26 +0100)
Instead of one callback function in main.c for all netlink events, these
changes allow to register per event callback functions. this will be used
more intensively for service name lookup support.

tools/nfctool/main.c
tools/nfctool/netlink.c
tools/nfctool/netlink.h

index 1b9a266..d0fe128 100644 (file)
 
 static GMainLoop *main_loop = NULL;
 
+static int nfctool_poll_cb(guint8 cmd, guint32 idx, gpointer data);
+
+static void nfctool_quit(gboolean force);
+
 static gchar *nfctool_poll_mode_str(int mode)
 {
        if (mode == POLLING_MODE_TARGET)
@@ -64,6 +68,9 @@ static int nfctool_start_poll(void)
                return -ENODEV;
        }
 
+       nl_add_event_handler(NFC_EVENT_TARGETS_FOUND, nfctool_poll_cb);
+       nl_add_event_handler(NFC_EVENT_TM_ACTIVATED, nfctool_poll_cb);
+
        err = nl_start_poll(adapter, opts.poll_mode);
 
        if (err == 0) {
@@ -106,16 +113,6 @@ exit:
        return err;
 }
 
-static int nfctool_tm_activated(void)
-{
-       printf("Target mode activated\n");
-
-       if (!opts.sniff)
-               g_main_loop_quit(main_loop);
-
-       return 0;
-}
-
 static void nfctool_send_dep_link_up(guint32 target_idx, guint32 adapter_idx)
 {
        nl_send_dep_link_up(adapter_idx, target_idx);
@@ -154,27 +151,26 @@ static int nfctool_targets_found(guint32 adapter_idx)
        }
 
 exit:
-       if (!opts.sniff)
-               g_main_loop_quit(main_loop);
-
        return err;
 }
 
-static int nfc_event_cb(guint8 cmd, guint32 idx)
+static int nfctool_poll_cb(guint8 cmd, guint32 idx, gpointer data)
 {
        int err = 0;
 
+       DBG("cmd: %d, idx: %d", cmd, idx);
+
        switch (cmd) {
        case NFC_EVENT_TARGETS_FOUND:
-               DBG("Targets found");
                err = nfctool_targets_found(idx);
                break;
        case NFC_EVENT_TM_ACTIVATED:
-               DBG("Target mode activated");
-               err = nfctool_tm_activated();
+               printf("Target mode activated\n");
                break;
        }
 
+       nfctool_quit(FALSE);
+
        return err;
 }
 
@@ -189,7 +185,7 @@ static void sig_term(int sig)
 
        DBG("Terminating");
 
-       g_main_loop_quit(main_loop);
+       nfctool_quit(TRUE);
 }
 
 struct nfctool_options opts = {
@@ -433,6 +429,12 @@ static void nfctool_main_loop_clean(void)
                g_main_loop_unref(main_loop);
 }
 
+static void nfctool_quit(gboolean force)
+{
+       if (force || !opts.sniff)
+               g_main_loop_quit(main_loop);
+}
+
 int main(int argc, char **argv)
 {
        int err;
@@ -444,7 +446,7 @@ int main(int argc, char **argv)
        adapter_init();
 
        if (opts.need_netlink) {
-               err = nl_init(nfc_event_cb);
+               err = nl_init();
                if (err)
                        goto exit_err;
 
index edaefef..f27deeb 100644 (file)
@@ -77,7 +77,7 @@ static struct nlnfc_state *nfc_state = NULL;
 
 static GIOChannel *nl_gio_channel = NULL;
 
-static nfc_event_cb_t nfc_event_cb = NULL;
+static GHashTable *handlers = NULL;
 
 static int nl_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
                         void *arg)
@@ -561,9 +561,9 @@ static int nl_nfc_event_cb(struct nl_msg *n, void *arg)
        guint32 idx = INVALID_ADAPTER_IDX;
        struct nlattr *attr[NFC_ATTR_MAX + 1];
        struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(n));
+       nfc_event_cb_t cb = NULL;
 
-       if (nfc_event_cb == NULL)
-               return NL_SKIP;
+       DBG("Received cmd %d", gnlh->cmd);
 
        nla_parse(attr, NFC_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
                genlmsg_attrlen(gnlh, 0), NULL);
@@ -571,7 +571,11 @@ static int nl_nfc_event_cb(struct nl_msg *n, void *arg)
        if (attr[NFC_ATTR_DEVICE_INDEX] != NULL)
                idx = nla_get_u32(attr[NFC_ATTR_DEVICE_INDEX]);
 
-       nfc_event_cb(gnlh->cmd, idx);
+       if (handlers != NULL)
+               cb = g_hash_table_lookup(handlers, GINT_TO_POINTER(gnlh->cmd));
+
+       if (cb != NULL)
+               cb(gnlh->cmd, idx, NULL);
 
        return NL_SKIP;
 }
@@ -599,6 +603,12 @@ static gboolean nl_gio_handler(GIOChannel *channel,
        return TRUE;
 }
 
+void nl_add_event_handler(guint8 cmd, nfc_event_cb_t cb)
+{
+       if (handlers != NULL)
+               g_hash_table_replace(handlers, GINT_TO_POINTER(cmd), cb);
+}
+
 void nl_cleanup(void)
 {
        if (nl_gio_channel) {
@@ -617,9 +627,12 @@ void nl_cleanup(void)
                g_free(nfc_state);
                nfc_state = NULL;
        }
+
+       if (handlers != NULL)
+               g_hash_table_remove_all(handlers);
 }
 
-int nl_init(nfc_event_cb_t cb)
+int nl_init(void)
 {
        int err;
        int fd;
@@ -676,6 +689,8 @@ int nl_init(nfc_event_cb_t cb)
                goto exit_err;
        }
 
+       handlers = g_hash_table_new(g_direct_hash, g_direct_equal);
+
        fd = nl_socket_get_fd(nfc_state->event_sock);
        nl_gio_channel = g_io_channel_unix_new(fd);
        g_io_channel_set_close_on_unref(nl_gio_channel, TRUE);
@@ -687,8 +702,6 @@ int nl_init(nfc_event_cb_t cb)
                       G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
                       nl_gio_handler, nfc_state);
 
-       nfc_event_cb = cb;
-
        return 0;
 
 exit_err:
index 88b2889..c8dc66a 100644 (file)
 #ifndef __NETLINK_H
 #define __NETLINK_H
 
-typedef int (*nfc_event_cb_t)(guint8 cmd, guint32 adapter_idx);
+typedef int (*nfc_event_cb_t)(guint8 cmd, guint32 adapter_idx, gpointer data);
 
 struct nfc_adapter;
 
-int nl_init(nfc_event_cb_t cb);
+int nl_init(void);
 
 void nl_cleanup(void);
 
+void nl_add_event_handler(guint8 cmd, nfc_event_cb_t cb);
+
 int nl_get_devices(void);
 
 int nl_get_targets(struct nfc_adapter *adapter);