summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2012-12-14 15:33:59 +0100
committerSamuel Ortiz <sameo@linux.intel.com>2013-01-06 22:47:01 +0100
commit471d4fe3ed7569e5202308b490c640f4c57e59cf (patch)
tree93491ba2dfd3db683472b40a59c8224e42458c2f /tools
parent89f2c0585fa2c3a2fd197bc7ffb2b4997fa84412 (diff)
downloadneard-471d4fe3ed7569e5202308b490c640f4c57e59cf.tar.gz
neard-471d4fe3ed7569e5202308b490c640f4c57e59cf.tar.bz2
neard-471d4fe3ed7569e5202308b490c640f4c57e59cf.zip
neard: nfctool: Add an option to set LTO, RW, and MIUX parameters
nfctool --device nfcX --set-param lto=x,rw=y,miux=z This sets one or more of the LTO, RW, or MIUX parameters for device nfcX
Diffstat (limited to 'tools')
-rw-r--r--tools/nfctool/main.c130
-rw-r--r--tools/nfctool/netlink.c108
-rw-r--r--tools/nfctool/netlink.h5
-rw-r--r--tools/nfctool/nfctool.h7
4 files changed, 247 insertions, 3 deletions
diff --git a/tools/nfctool/main.c b/tools/nfctool/main.c
index 930d25e..2e1d493 100644
--- a/tools/nfctool/main.c
+++ b/tools/nfctool/main.c
@@ -30,6 +30,10 @@
#include "nfctool.h"
#include "netlink.h"
+#define LLCP_MAX_LTO 0xff
+#define LLCP_MAX_RW 0x0f
+#define LLCP_MAX_MIUX 0x7ff
+
GSList *adapters = NULL;
static GMainLoop *main_loop = NULL;
@@ -119,6 +123,10 @@ static void nfctool_print_adapter_info(struct nfc_adapter *adapter)
printf(" RF Mode: %s\n", rf_mode_str);
+ printf(" lto: %d\n", adapter->param_lto);
+ printf(" rw: %d\n", adapter->param_rw);
+ printf(" miux: %d\n", adapter->param_miux);
+
printf("\n");
}
@@ -190,6 +198,8 @@ static void nfctool_get_device(struct nfc_adapter *adapter)
{
if (adapter->rf_mode == NFC_RF_INITIATOR)
nl_get_targets(adapter);
+
+ nl_get_params(adapter);
}
static int nfctool_get_devices(void)
@@ -205,6 +215,29 @@ static int nfctool_get_devices(void)
return 0;
}
+static int nfctool_set_params(void)
+{
+ struct nfc_adapter *adapter;
+ int err;
+
+ adapter = nfctool_find_adapter(opts.adapter_idx);
+ if (!adapter)
+ return -ENODEV;
+
+ err = nl_set_params(adapter, opts.lto, opts.rw, opts.miux);
+ if (err) {
+ print_error("Error setting one of the parameters.");
+ goto exit;
+ }
+
+ nl_get_params(adapter);
+
+ nfctool_print_adapter_info(adapter);
+
+exit:
+ return err;
+}
+
static int nfctool_tm_activated(void)
{
printf("Target mode activated\n");
@@ -295,6 +328,10 @@ struct nfctool_options opts = {
.poll_mode = POLLING_MODE_INITIATOR,
.device_name = NULL,
.adapter_idx = INVALID_ADAPTER_IDX,
+ .set_param = FALSE,
+ .lto = -1,
+ .rw = -1,
+ .miux = -1,
};
static gboolean opt_parse_poll_arg(const gchar *option_name, const gchar *value,
@@ -314,6 +351,84 @@ static gboolean opt_parse_poll_arg(const gchar *option_name, const gchar *value,
return TRUE;
}
+static gboolean opt_parse_set_param_arg(const gchar *option_name,
+ const gchar *value,
+ gpointer data, GError **error)
+{
+ gchar **params = NULL, **keyval = NULL;
+ gchar *end;
+ gint i, intval;
+ gboolean result;
+
+ params = g_strsplit(value, ",", -1);
+
+ i = 0;
+ while (params[i] != NULL) {
+ keyval = g_strsplit(params[i], "=", 2);
+
+ if (keyval[0] == NULL || keyval[1] == NULL) {
+ result = FALSE;
+ goto exit;
+ }
+
+ intval = strtol(keyval[1], &end, 10);
+ if (keyval[1] == end) {
+ result = FALSE;
+ goto exit;
+ }
+
+ if (g_ascii_strcasecmp(keyval[0], "lto") == 0) {
+ if (intval < 0 || intval > LLCP_MAX_LTO) {
+ print_error("Bad value: max lto value is %d",
+ LLCP_MAX_LTO);
+ result = FALSE;
+ goto exit;
+ }
+
+ opts.lto = intval;
+ } else if (g_ascii_strcasecmp(keyval[0], "rw") == 0) {
+ if (intval < 0 || intval > LLCP_MAX_RW) {
+ print_error("Bad value: max rw value is %d",
+ LLCP_MAX_RW);
+ result = FALSE;
+ goto exit;
+ }
+
+ opts.rw = intval;
+ } else if (g_ascii_strcasecmp(keyval[0], "miux") == 0) {
+ if (intval < 0 || intval > LLCP_MAX_MIUX) {
+ print_error("Bad value: max miux value is %d",
+ LLCP_MAX_MIUX);
+ result = FALSE;
+ goto exit;
+ }
+
+ opts.miux = intval;
+ } else {
+ result = FALSE;
+ goto exit;
+ }
+
+ opts.set_param = TRUE;
+
+ g_strfreev(keyval);
+ keyval = NULL;
+
+ i++;
+ }
+
+ result = TRUE;
+
+exit:
+ if (params)
+ g_strfreev(params);
+
+ if (keyval)
+ g_strfreev(keyval);
+
+ return result;
+}
+
static GOptionEntry option_entries[] = {
{ "list", 'l', 0, G_OPTION_ARG_NONE, &opts.list,
"list attached NFC devices", NULL },
@@ -322,6 +437,8 @@ static GOptionEntry option_entries[] = {
{ "poll", 'p', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_CALLBACK,
opt_parse_poll_arg, "start polling as initiator, target, or both; "
"default mode is initiator", "[Initiator|Target|Both]" },
+ { "set-param", 's', 0, G_OPTION_ARG_CALLBACK, opt_parse_set_param_arg,
+ "set lto, rw, and/or miux parameters", "lto=150,rw=1,miux=100" },
{ NULL }
};
@@ -362,13 +479,14 @@ static int nfctool_options_parse(int argc, char **argv)
}
}
- if (!opts.poll && !opts.list) {
+ if (!opts.poll && !opts.list && !opts.set_param) {
printf("%s", g_option_context_get_help(context, TRUE, NULL));
goto exit;
}
- if (opts.poll && opts.adapter_idx == INVALID_ADAPTER_IDX) {
+ if ((opts.poll || opts.set_param) &&
+ opts.adapter_idx == INVALID_ADAPTER_IDX) {
print_error("Please specify a device with -d nfcX option");
goto exit;
@@ -424,9 +542,15 @@ int main(int argc, char **argv)
if (err)
goto exit_err;
- if (opts.list)
+ if (opts.list && !opts.set_param)
nfctool_list_adapters();
+ if (opts.set_param) {
+ err = nfctool_set_params();
+ if (err)
+ goto exit_err;
+ }
+
if (opts.poll) {
err = nfctool_start_poll();
if (err)
diff --git a/tools/nfctool/netlink.c b/tools/nfctool/netlink.c
index 67f1d10..7102bca 100644
--- a/tools/nfctool/netlink.c
+++ b/tools/nfctool/netlink.c
@@ -213,6 +213,114 @@ static int nl_no_seq_check_cb(struct nl_msg *n, void *arg)
return NL_OK;
}
+static int nl_get_params_handler(struct nl_msg *n, void *arg)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(n);
+ struct nlattr *attrs[NFC_ATTR_MAX + 1];
+ struct nfc_adapter *adapter = (struct nfc_adapter *)arg;
+ guint32 idx;
+
+ 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_PARAMS");
+ return NL_STOP;
+ }
+
+ idx = nla_get_u32(attrs[NFC_ATTR_DEVICE_INDEX]);
+ if (idx != adapter->idx) {
+ nl_perror(NLE_MISSING_ATTR, "NFC_CMD_GET_PARAMS");
+ return NL_STOP;
+ }
+
+ adapter->param_lto = nla_get_u8(attrs[NFC_ATTR_LLC_PARAM_LTO]);
+ adapter->param_rw = nla_get_u8(attrs[NFC_ATTR_LLC_PARAM_RW]);
+ adapter->param_miux = nla_get_u16(attrs[NFC_ATTR_LLC_PARAM_MIUX]);
+
+ return NL_STOP;
+}
+
+int nl_get_params(struct nfc_adapter *adapter)
+{
+ struct nl_msg *msg;
+ void *hdr;
+ int err = 0;
+
+ 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,
+ 0, NFC_CMD_LLC_GET_PARAMS, NFC_GENL_VERSION);
+ if (hdr == NULL) {
+ err = -EINVAL;
+ goto nla_put_failure;
+ }
+
+ NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, adapter->idx);
+
+ err = nl_send_msg(nfc_state->cmd_sock, msg, nl_get_params_handler,
+ adapter);
+
+ DBG("nl_send_msg returns %d", err);
+
+nla_put_failure:
+ nlmsg_free(msg);
+
+ return err;
+}
+
+int nl_set_params(struct nfc_adapter *adapter, gint32 lto, gint32 rw,
+ gint32 miux)
+{
+ struct nl_msg *msg;
+ void *hdr;
+ int err = 0;
+
+ DBG("");
+
+ if (lto < 0 && rw < 0 && miux < 0)
+ return -EINVAL;
+
+ 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,
+ 0, NFC_CMD_LLC_SET_PARAMS, NFC_GENL_VERSION);
+ if (hdr == NULL) {
+ err = -EINVAL;
+ goto nla_put_failure;
+ }
+
+ NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, adapter->idx);
+ if (lto >= 0)
+ NLA_PUT_U8(msg, NFC_ATTR_LLC_PARAM_LTO, (guint8)lto);
+ if (rw >= 0)
+ NLA_PUT_U8(msg, NFC_ATTR_LLC_PARAM_RW, (guint8)rw);
+ if (miux >= 0)
+ NLA_PUT_U16(msg, NFC_ATTR_LLC_PARAM_MIUX, (guint16)miux);
+
+ err = nl_send_msg(nfc_state->cmd_sock, msg, NULL, NULL);
+
+ DBG("nl_send_msg returns %d", err);
+
+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);
diff --git a/tools/nfctool/netlink.h b/tools/nfctool/netlink.h
index 6b5174e..88b2889 100644
--- a/tools/nfctool/netlink.h
+++ b/tools/nfctool/netlink.h
@@ -37,4 +37,9 @@ int nl_send_dep_link_up(guint32 idx, guint32 target_idx);
int nl_start_poll(struct nfc_adapter *adapter, guint8 mode);
+int nl_set_params(struct nfc_adapter *adapter, gint32 lto, gint32 rw,
+ gint32 miux);
+
+int nl_get_params(struct nfc_adapter *adapter);
+
#endif /* __NETLINK_H */
diff --git a/tools/nfctool/nfctool.h b/tools/nfctool/nfctool.h
index 7507eea..9562962 100644
--- a/tools/nfctool/nfctool.h
+++ b/tools/nfctool/nfctool.h
@@ -52,6 +52,9 @@ struct nfc_adapter {
guint8 rf_mode;
GSList *tags;
GSList *devices;
+ gint32 param_lto;
+ gint32 param_rw;
+ gint32 param_miux;
};
struct nfctool_options {
@@ -60,6 +63,10 @@ struct nfctool_options {
guint8 poll_mode;
gchar *device_name;
guint32 adapter_idx;
+ gboolean set_param;
+ gint32 lto;
+ gint32 rw;
+ gint32 miux;
};
extern struct nfctool_options opts;