From 471d4fe3ed7569e5202308b490c640f4c57e59cf Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Fri, 14 Dec 2012 15:33:59 +0100 Subject: 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 --- tools/nfctool/main.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++-- tools/nfctool/netlink.c | 108 ++++++++++++++++++++++++++++++++++++++++ tools/nfctool/netlink.h | 5 ++ tools/nfctool/nfctool.h | 7 +++ 4 files changed, 247 insertions(+), 3 deletions(-) (limited to 'tools') 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; -- cgit v1.2.3