neard: Add nfctool native application
authorThierry Escande <thierry.escande@linux.intel.com>
Fri, 14 Dec 2012 14:33:57 +0000 (15:33 +0100)
committerSamuel Ortiz <sameo@linux.intel.com>
Sun, 6 Jan 2013 21:47:01 +0000 (22:47 +0100)
nfctool is a native application used as a tool box for various nfc related
operations. First goal is to be able to do such operations on embedded
platforms that don't have a python interpretor (since all neard test tools
are pyhton scripts)

This initial release can list nfc adapters, targets, etc.

.gitignore
Makefile.am
tools/nfctool/main.c [new file with mode: 0644]
tools/nfctool/netlink.c [new file with mode: 0644]
tools/nfctool/netlink.h [new file with mode: 0644]
tools/nfctool/nfctool.h [new file with mode: 0644]

index e678568..af74ca3 100644 (file)
@@ -32,3 +32,4 @@ include/version.h
 src/builtin.h
 src/neard
 tools/snep-send
+tools/nfctool/nfctool
index b563dfc..79110a5 100644 (file)
@@ -80,12 +80,15 @@ test_SCRIPTS = $(test_scripts)
 endif
 
 if TOOLS
-noinst_PROGRAMS = tools/snep-send
+noinst_PROGRAMS = tools/snep-send tools/nfctool/nfctool
 
 tools_snep_send_SOURCES = $(gdbus_sources) src/log.c src/dbus.c \
                        src/bluetooth.c src/ndef.c tools/snep-send.c src/agent.c
 tools_snep_send_LDADD = @GLIB_LIBS@ @DBUS_LIBS@
 
+tools_nfctool_nfctool_SOURCES = tools/nfctool/main.c tools/nfctool/netlink.c
+tools_nfctool_nfctool_LDADD = @GLIB_LIBS@ @NETLINK_LIBS@
+
 endif
 
 include Makefile.plugins
diff --git a/tools/nfctool/main.c b/tools/nfctool/main.c
new file mode 100644 (file)
index 0000000..fc8e0a3
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *
+ *  Near Field Communication nfctool
+ *
+ *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <linux/nfc.h>
+#include <glib.h>
+
+#include "nfctool.h"
+#include "netlink.h"
+
+GSList *adapters = NULL;
+
+static void nfctool_print_target(guint32 idx, gchar *type)
+{
+       printf("%s%d ", type, idx);
+}
+
+static void nfctool_print_targets(struct nfc_adapter *adapter, gchar *prefix)
+{
+       printf("%sTags: [ ", prefix);
+
+       g_slist_foreach(adapter->tags, (GFunc)nfctool_print_target, "tag");
+
+       printf("]\n");
+
+       printf("%sDevices: [ ", prefix);
+
+       g_slist_foreach(adapter->devices,
+                       (GFunc)nfctool_print_target, "device");
+
+       printf("]\n");
+}
+
+static void nfctool_print_adapter_info(struct nfc_adapter *adapter)
+{
+       printf("nfc%d:\n", adapter->idx);
+
+       nfctool_print_targets(adapter, "          ");
+
+       printf("          Protocols: [ ");
+
+       if (adapter->protocols & NFC_PROTO_FELICA_MASK)
+               printf("Felica ");
+
+       if (adapter->protocols & NFC_PROTO_MIFARE_MASK)
+               printf("MIFARE ");
+
+       if (adapter->protocols & NFC_PROTO_JEWEL_MASK)
+               printf("Jewel ");
+
+       if (adapter->protocols & NFC_PROTO_ISO14443_MASK)
+               printf("ISO-DEP ");
+
+       if (adapter->protocols & NFC_PROTO_NFC_DEP_MASK)
+               printf("NFC-DEP ");
+
+       printf("]\n");
+
+       printf("          Powered: %s\n",
+               adapter->powered ? "Yes" : "No");
+
+       printf("\n");
+}
+
+static void nfctool_list_adapter(struct nfc_adapter *adapter, guint32 idx)
+{
+       if (idx == INVALID_ADAPTER_IDX || idx == adapter->idx)
+               nfctool_print_adapter_info(adapter);
+}
+
+static void nfctool_list_adapters(void)
+{
+       g_slist_foreach(adapters, (GFunc)nfctool_list_adapter,
+                                       GINT_TO_POINTER(opts.adapter_idx));
+}
+
+static void nfctool_adapter_free(struct nfc_adapter *adapter)
+{
+       g_slist_free(adapter->tags);
+       g_slist_free(adapter->devices);
+
+       g_free(adapter);
+}
+
+static void nfctool_get_device(struct nfc_adapter *adapter)
+{
+       nl_get_targets(adapter);
+}
+
+static int nfctool_get_devices(void)
+{
+       int err;
+
+       err = nl_get_devices();
+       if (err)
+               return err;
+
+       g_slist_foreach(adapters, (GFunc)nfctool_get_device, NULL);
+
+       return 0;
+}
+
+struct nfctool_options opts = {
+       .list = FALSE,
+       .device_name = NULL,
+       .adapter_idx = INVALID_ADAPTER_IDX,
+};
+
+static GOptionEntry option_entries[] = {
+       { "list", 'l', 0, G_OPTION_ARG_NONE, &opts.list,
+         "list attached NFC devices", NULL },
+       { "device", 'd', 0, G_OPTION_ARG_STRING, &opts.device_name,
+         "specify a nfc device", "nfcX" },
+       { NULL }
+};
+
+static int nfctool_options_parse(int argc, char **argv)
+{
+       GOptionContext *context;
+       GError *error = NULL;
+       gchar *start, *end;
+       int err = -EINVAL;
+
+       context = g_option_context_new("- A small NFC tool box");
+
+       g_option_context_add_main_entries(context, option_entries, NULL);
+
+       if (!g_option_context_parse(context, &argc, &argv, &error)) {
+               print_error("%s: %s", argv[0], error->message);
+
+               g_error_free(error);
+
+               goto exit;
+       }
+
+       if (opts.device_name != NULL) {
+               if (strncmp("nfc", opts.device_name, 3) != 0) {
+                       print_error("Invalid device name: %s",
+                                                       opts.device_name);
+
+                       goto exit;
+               }
+
+               start = opts.device_name + 3;
+
+               opts.adapter_idx = strtol(start, &end, 10);
+               if (start == end) {
+                       print_error("Invalid NFC adapter %s", opts.device_name);
+
+                       goto exit;
+               }
+       }
+
+       if (!opts.list) {
+               printf("%s", g_option_context_get_help(context, TRUE, NULL));
+
+               goto exit;
+       }
+
+       err = 0;
+
+exit:
+       g_option_context_free(context);
+
+       return err;
+}
+
+static void nfctool_options_cleanup(void)
+{
+       if (opts.device_name != NULL)
+               g_free(opts.device_name);
+}
+
+int main(int argc, char **argv)
+{
+       int err;
+
+       err = nfctool_options_parse(argc, argv);
+       if (err)
+               goto exit_err;
+
+       err = nl_init();
+       if (err)
+               goto exit_err;
+
+       err = nfctool_get_devices();
+       if (err)
+               goto exit_err;
+
+       if (opts.list)
+               nfctool_list_adapters();
+
+       err = 0;
+
+exit_err:
+       g_slist_free_full(adapters, (GDestroyNotify)nfctool_adapter_free);
+
+       nl_cleanup();
+
+       nfctool_options_cleanup();
+
+       return err;
+}
diff --git a/tools/nfctool/netlink.c b/tools/nfctool/netlink.c
new file mode 100644 (file)
index 0000000..c7bf07a
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ *
+ *  Near Field Communication nfctool
+ *
+ *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <linux/nfc.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <glib.h>
+
+#include "nfctool.h"
+#include "netlink.h"
+
+struct handler_args {
+       const char *group;
+       int id;
+};
+
+struct nlnfc_state {
+       struct nl_sock *cmd_sock;
+       struct nl_sock *event_sock;
+       int nfc_id;
+       int mcid;
+};
+
+static struct nlnfc_state *nfc_state = NULL;
+
+static void adapter_add_target(struct nfc_adapter *adapter,
+                               guint8 type, guint32 idx)
+{
+       DBG("adapter_idx: %d, target_type: %d, target_idx: %d", adapter->idx,
+                                                               type, idx);
+
+       if (type == TARGET_TYPE_TAG)
+               adapter->tags = g_slist_append(adapter->tags,
+                                              GINT_TO_POINTER(idx));
+       else
+               adapter->devices = g_slist_append(adapter->devices,
+                                                 GINT_TO_POINTER(idx));
+}
+
+static int nl_error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+                        void *arg)
+{
+       int *ret = arg;
+
+       DBG("");
+
+       *ret = err->error;
+
+       return NL_STOP;
+}
+
+static int nl_finish_handler(struct nl_msg *msg, void *arg)
+{
+       int *ret = arg;
+
+       DBG("");
+
+       *ret = 1;
+
+       return NL_SKIP;
+}
+
+static int nl_ack_handler(struct nl_msg *msg, void *arg)
+{
+       int *ret = arg;
+
+       DBG("");
+
+       *ret = 1;
+
+       return NL_STOP;
+}
+
+static int nl_send_msg(struct nl_sock *sock, struct nl_msg *msg,
+                      int (*rx_handler)(struct nl_msg *, void *),
+                      void *data)
+{
+       struct nl_cb *cb;
+       int err, done;
+
+       DBG("");
+
+       cb = nl_cb_alloc(NL_CB_DEFAULT);
+       if (cb == NULL)
+               return -ENOMEM;
+
+       err = nl_send_auto_complete(sock, msg);
+       if (err < 0) {
+               nl_cb_put(cb);
+               print_error("%s", strerror(err));
+
+               return err;
+       }
+
+       err = done = 0;
+
+       nl_cb_err(cb, NL_CB_CUSTOM, nl_error_handler, &err);
+       nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_finish_handler, &done);
+       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, &done);
+
+       if (rx_handler != NULL)
+               nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data);
+
+       while (err == 0 && done == 0)
+               nl_recvmsgs(sock, cb);
+
+       nl_cb_put(cb);
+
+       return err;
+}
+
+static int nl_family_handler(struct nl_msg *msg, void *arg)
+{
+       struct handler_args *grp = arg;
+       struct nlattr *tb[CTRL_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+       struct nlattr *mcgrp;
+       int rem_mcgrp;
+
+       DBG("");
+
+       nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+
+       if (!tb[CTRL_ATTR_MCAST_GROUPS])
+               return NL_SKIP;
+
+       nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
+               struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
+
+               nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
+                         nla_data(mcgrp), nla_len(mcgrp), NULL);
+
+               if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] ||
+                   !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
+                       continue;
+               if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
+                           grp->group,
+                           nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])))
+                       continue;
+               grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
+               break;
+       }
+
+       return NL_SKIP;
+}
+
+static int nl_get_multicast_id(struct nl_sock *sock, const char *family,
+                               const char *group)
+{
+       struct nl_msg *msg;
+       int err = 0, ctrlid;
+       struct handler_args grp = {
+               .group = group,
+               .id = -ENOENT,
+       };
+
+       DBG("");
+
+       msg = nlmsg_alloc();
+       if (msg == NULL)
+               return -ENOMEM;
+
+       ctrlid = genl_ctrl_resolve(sock, "nlctrl");
+
+       genlmsg_put(msg, 0, 0, ctrlid, 0,
+                   0, CTRL_CMD_GETFAMILY, 0);
+
+       NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
+
+       err = nl_send_msg(sock, msg, nl_family_handler, &grp);
+       if (err)
+               goto nla_put_failure;
+
+       DBG("multicast id %d", grp.id);
+
+       err = grp.id;
+
+nla_put_failure:
+       nlmsg_free(msg);
+
+       return err;
+}
+
+static int nl_get_targets_handler(struct nl_msg *n, void *arg)
+{
+       struct nlmsghdr *nlh = nlmsg_hdr(n);
+       struct nlattr *attrs[NFC_ATTR_MAX + 1];
+       guint32 target_idx, target_type, protocols;
+       struct nfc_adapter *adapter;
+
+       DBG("");
+
+       adapter = (struct nfc_adapter *)arg;
+
+       genlmsg_parse(nlh, 0, attrs, NFC_ATTR_MAX, NULL);
+
+       target_idx = nla_get_u32(attrs[NFC_ATTR_TARGET_INDEX]);
+       protocols = nla_get_u32(attrs[NFC_ATTR_PROTOCOLS]);
+
+       if (protocols & NFC_PROTO_NFC_DEP_MASK)
+               target_type = TARGET_TYPE_DEVICE;
+       else
+               target_type = TARGET_TYPE_TAG;
+
+       adapter_add_target(adapter, target_type, target_idx);
+
+       return 0;
+}
+
+int nl_get_targets(struct nfc_adapter *adapter)
+{
+       struct nl_msg *msg;
+       void *hdr;
+       int err;
+
+       DBG("");
+
+       if (nfc_state == NULL || nfc_state->nfc_id < 0)
+               return -ENODEV;
+
+       msg = nlmsg_alloc();
+       if (msg == NULL)
+               return -ENOMEM;
+
+       hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nfc_state->nfc_id, 0,
+                         NLM_F_DUMP, NFC_CMD_GET_TARGET, NFC_GENL_VERSION);
+       if (hdr == NULL) {
+               err = -EINVAL;
+               goto nla_put_failure;
+       }
+
+       err = -EMSGSIZE;
+
+       g_slist_free(adapter->tags);
+       adapter->tags = NULL;
+
+       g_slist_free(adapter->devices);
+       adapter->devices = NULL;
+
+       NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, adapter->idx);
+
+       err = nl_send_msg(nfc_state->cmd_sock, msg,
+                         nl_get_targets_handler, adapter);
+
+       DBG("nl_send_msg returns %d", err);
+
+nla_put_failure:
+       nlmsg_free(msg);
+
+       return err;
+}
+
+static int nl_get_devices_handler(struct nl_msg *n, void *arg)
+{
+       struct nlmsghdr *nlh = nlmsg_hdr(n);
+       struct nlattr *attrs[NFC_ATTR_MAX + 1];
+       guint32 idx, protocols = 0;
+       guint8 powered = 0;
+       guint8 rf_mode = NFC_RF_NONE;
+       struct nfc_adapter *adapter;
+
+       DBG("");
+
+       genlmsg_parse(nlh, 0, attrs, NFC_ATTR_MAX, NULL);
+
+       if (attrs[NFC_ATTR_DEVICE_INDEX] == NULL) {
+               nl_perror(NLE_MISSING_ATTR, "NFC_CMD_GET_DEVICE");
+               return NL_STOP;
+       }
+
+       idx = nla_get_u32(attrs[NFC_ATTR_DEVICE_INDEX]);
+
+       if (attrs[NFC_ATTR_PROTOCOLS] != NULL)
+               protocols = nla_get_u32(attrs[NFC_ATTR_PROTOCOLS]);
+
+       if (attrs[NFC_ATTR_RF_MODE] != NULL)
+               rf_mode = nla_get_u8(attrs[NFC_ATTR_RF_MODE]);
+
+       if (attrs[NFC_ATTR_DEVICE_POWERED] != NULL)
+               powered = nla_get_u8(attrs[NFC_ATTR_DEVICE_POWERED]);
+
+       adapter = g_malloc0(sizeof(struct nfc_adapter));
+
+       adapter->idx = idx;
+       adapter->protocols = protocols;
+       adapter->powered = powered;
+
+       if (rf_mode == NFC_RF_TARGET)
+               adapter_add_target(adapter, TARGET_TYPE_DEVICE, 0);
+
+       adapters = g_slist_append(adapters, adapter);
+
+       return NL_SKIP;
+}
+
+int nl_get_devices(void)
+{
+       struct nl_msg *msg;
+       void *hdr;
+       int err;
+
+       DBG("");
+
+       if (nfc_state == NULL || nfc_state->nfc_id < 0)
+               return -ENODEV;
+
+       msg = nlmsg_alloc();
+       if (msg == NULL)
+               return -ENOMEM;
+
+       hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nfc_state->nfc_id, 0,
+                         NLM_F_DUMP, NFC_CMD_GET_DEVICE, NFC_GENL_VERSION);
+       if (hdr == NULL) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       err = nl_send_msg(nfc_state->cmd_sock, msg, nl_get_devices_handler,
+                         NULL);
+
+       DBG("nl_send_msg returns %d", err);
+
+out:
+       nlmsg_free(msg);
+
+       return err;
+}
+
+void nl_cleanup(void)
+{
+       if (nfc_state) {
+               if (nfc_state->cmd_sock)
+                       nl_socket_free(nfc_state->cmd_sock);
+
+               if (nfc_state->event_sock)
+                       nl_socket_free(nfc_state->event_sock);
+
+               g_free(nfc_state);
+               nfc_state = NULL;
+       }
+}
+
+int nl_init(void)
+{
+       int err;
+
+       DBG("");
+
+       nfc_state = g_malloc0(sizeof(struct nlnfc_state));
+
+       nfc_state->cmd_sock = nl_socket_alloc();
+       if (nfc_state->cmd_sock == NULL) {
+               print_error("Failed to allocate NFC netlink socket");
+               err = -ENOMEM;
+               goto exit_err;
+       }
+
+       nfc_state->event_sock = nl_socket_alloc();
+       if (nfc_state->event_sock == NULL) {
+               print_error("Failed to allocate NFC netlink socket");
+               err = -ENOMEM;
+               goto exit_err;
+       }
+
+       if (genl_connect(nfc_state->cmd_sock)) {
+               print_error("Failed to connect to generic netlink");
+               err = -ENOLINK;
+               goto exit_err;
+       }
+
+       if (genl_connect(nfc_state->event_sock)) {
+               print_error("Failed to connect to generic netlink");
+               err = -ENOLINK;
+               goto exit_err;
+       }
+
+       nfc_state->nfc_id = genl_ctrl_resolve(nfc_state->cmd_sock, "nfc");
+       if (nfc_state->nfc_id < 0) {
+               print_error("Unable to find NFC netlink family");
+               err = -ENOENT;
+               goto exit_err;
+       }
+
+       nfc_state->mcid = nl_get_multicast_id(nfc_state->cmd_sock,
+                                             NFC_GENL_NAME,
+                                             NFC_GENL_MCAST_EVENT_NAME);
+       if (nfc_state->mcid <= 0) {
+               print_error("Wrong mcast id %d", nfc_state->mcid);
+               err = nfc_state->mcid;
+               goto exit_err;
+       }
+
+       err = nl_socket_add_membership(nfc_state->event_sock, nfc_state->mcid);
+       if (err) {
+               print_error("Error adding nl socket to membership");
+               goto exit_err;
+       }
+
+       return 0;
+
+exit_err:
+       nl_cleanup();
+
+       print_error("netlink init failed");
+
+       return err;
+}
diff --git a/tools/nfctool/netlink.h b/tools/nfctool/netlink.h
new file mode 100644 (file)
index 0000000..99e4e91
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *
+ *  Near Field Communication nfctool
+ *
+ *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+#ifndef __NETLINK_H
+#define __NETLINK_H
+
+struct nfc_adapter;
+
+int nl_init(void);
+
+void nl_cleanup(void);
+
+int nl_get_devices(void);
+
+int nl_get_targets(struct nfc_adapter *adapter);
+
+#endif /* __NETLINK_H */
diff --git a/tools/nfctool/nfctool.h b/tools/nfctool/nfctool.h
new file mode 100644 (file)
index 0000000..35d985b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *
+ *  Near Field Communication nfctool
+ *
+ *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __NFCTOOL_H
+#define __NFCTOOL_H
+
+#ifdef DEBUG
+#define DBG(fmt, ...) fprintf(stdout, "%s: " fmt "\n", __func__, ## __VA_ARGS__)
+#else
+#define DBG(fmt, ...)
+#endif
+
+#define print_error(fmt, ...) fprintf(stderr, fmt"\n", ## __VA_ARGS__)
+
+#define INVALID_ADAPTER_IDX 0xFFFFFFFF
+
+#define TARGET_TYPE_TAG                0
+#define TARGET_TYPE_DEVICE     1
+
+struct nfc_target {
+       guint32 idx;
+       guint8 type;
+};
+
+struct nfc_adapter {
+       guint32 idx;
+       guint32 protocols;
+       guint8 powered;
+       GSList *tags;
+       GSList *devices;
+};
+
+struct nfctool_options {
+       gboolean list;
+       gchar *device_name;
+       guint32 adapter_idx;
+};
+
+extern struct nfctool_options opts;
+
+extern GSList *adapters;
+
+#endif /* __NFCTOOL_H */