From 754da55d4a19cc9035d9e7e0c724fad853a59b2c Mon Sep 17 00:00:00 2001 From: Thierry Escande Date: Mon, 9 Sep 2013 18:27:08 +0200 Subject: [PATCH] nfctool: Add firmware download command This adds a command line option (--fw-download or -w) to start firmware download process on the specified device with the passed firmware filename. e.g. nfctool -d nfc0 --fw-download fw_filename --- tools/nfctool/main.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--- tools/nfctool/netlink.c | 34 +++++++++++++++++++++++++ tools/nfctool/netlink.h | 2 ++ tools/nfctool/nfctool.h | 1 + 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/tools/nfctool/main.c b/tools/nfctool/main.c index 8527dd7..a139237 100644 --- a/tools/nfctool/main.c +++ b/tools/nfctool/main.c @@ -30,6 +30,8 @@ #include #include +#include + #include #include "nfctool.h" @@ -152,6 +154,49 @@ static int nfctool_set_powered(bool powered) return err; } +static int nfctool_fw_download_cb(guint8 cmd, guint32 adapter_idx, + gpointer data) +{ + int err; + gchar *fw_filename; + struct nlattr **nl_attr = data; + + if (nl_attr[NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS] != NULL) + err = nla_get_u32(nl_attr[NFC_ATTR_FIRMWARE_DOWNLOAD_STATUS]); + else + err = -ENOTSUP; + + if (nl_attr[NFC_ATTR_FIRMWARE_NAME] != NULL) + fw_filename = nla_get_string(nl_attr[NFC_ATTR_FIRMWARE_NAME]); + else + fw_filename = "UNKNOWN"; + + printf("Firmware download operation for %s terminated with status %s\n", + fw_filename, err ? strerror(-err) : "OK"); + + nfctool_quit(false); + + return 0; +} + +static int nfctool_fw_download(gchar *fw_filename) +{ + struct nfc_adapter *adapter; + int err; + + adapter = adapter_get(opts.adapter_idx); + if (!adapter) + return -ENODEV; + + nl_add_event_handler(NFC_CMD_FW_DOWNLOAD, nfctool_fw_download_cb); + + err = nl_fw_download(adapter, fw_filename); + if (err) + print_error("Firmware download failed: %s", strerror(-err)); + + return err; +} + static int nfctool_dep_link_up_cb(guint8 cmd, guint32 idx, gpointer data) { struct nfc_adapter *adapter; @@ -508,6 +553,8 @@ static GOptionEntry option_entries[] = { "enable device", NULL }, { "disable", '0', 0, G_OPTION_ARG_NONE, &opts.disable_dev, "disable device", NULL }, + { "fw-download", 'w', 0, G_OPTION_ARG_STRING, &opts.fw_filename, + "Put the device in firmware download mode", "fw_filename" }, { "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" }, { "snl", 'k', 0, G_OPTION_ARG_CALLBACK, &opt_parse_snl_arg, @@ -580,8 +627,8 @@ static int nfctool_options_parse(int argc, char **argv) if (opts.poll) opts.enable_dev = true; - opts.need_netlink = opts.list || opts.poll || - opts.set_param || opts.snl; + opts.need_netlink = opts.list || opts.poll || opts.set_param || + opts.snl || opts.fw_filename; if (!opts.need_netlink && !opts.sniff) { printf("%s", g_option_context_get_help(context, TRUE, NULL)); @@ -590,7 +637,7 @@ static int nfctool_options_parse(int argc, char **argv) } if ((opts.poll || opts.set_param || opts.sniff || opts.snl || - opts.enable_dev || opts.disable_dev) && + opts.enable_dev || opts.disable_dev || opts.fw_filename) && opts.adapter_idx == INVALID_ADAPTER_IDX) { print_error("Please specify a device with -d nfcX option"); @@ -628,6 +675,9 @@ static void nfctool_options_cleanup(void) if (opts.pcap_filename) g_free(opts.pcap_filename); + if (opts.fw_filename != NULL) + g_free(opts.fw_filename); + g_slist_free_full(opts.snl_list, g_free); } @@ -666,6 +716,14 @@ int main(int argc, char **argv) goto exit_err; } + if (opts.fw_filename) { + err = nfctool_fw_download(opts.fw_filename); + if (err) + goto exit_err; + + goto start_loop; + } + if (opts.sniff) { err = sniffer_init(); if (err) @@ -703,7 +761,8 @@ int main(int argc, char **argv) if (opts.snl) nfctool_snl(); - if (opts.poll || opts.sniff || opts.snl) +start_loop: + if (opts.poll || opts.sniff || opts.snl || opts.fw_filename) nfctool_main_loop_start(); done: diff --git a/tools/nfctool/netlink.c b/tools/nfctool/netlink.c index c4b620c..112b3cb 100644 --- a/tools/nfctool/netlink.c +++ b/tools/nfctool/netlink.c @@ -703,6 +703,40 @@ static int nl_nfc_send_sdres_event(guint32 idx, struct nlattr *sdres_attr, return err; } +int nl_fw_download(struct nfc_adapter *adapter, gchar *fw_filename) +{ + 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; + + err = -EINVAL; + + hdr = genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, nfc_state->nfc_id, 0, + NLM_F_REQUEST, NFC_CMD_FW_DOWNLOAD, NFC_GENL_VERSION); + if (hdr == NULL) + goto nla_put_failure; + + NLA_PUT_U32(msg, NFC_ATTR_DEVICE_INDEX, adapter->idx); + + NLA_PUT_STRING(msg, NFC_ATTR_FIRMWARE_NAME, fw_filename); + + err = nl_send_msg(nfc_state->event_sock, msg, NULL, NULL); + +nla_put_failure: + nlmsg_free(msg); + + return err; +} + static int nl_nfc_event_cb(struct nl_msg *n, void *arg) { guint32 idx = INVALID_ADAPTER_IDX; diff --git a/tools/nfctool/netlink.h b/tools/nfctool/netlink.h index ce51910..21a9f5b 100644 --- a/tools/nfctool/netlink.h +++ b/tools/nfctool/netlink.h @@ -48,4 +48,6 @@ int nl_send_sdreq(struct nfc_adapter *adapter, GSList *uris); int nl_set_powered(struct nfc_adapter *adapter, bool powered); +int nl_fw_download(struct nfc_adapter *adapter, gchar *fw_filename); + #endif /* __NETLINK_H */ diff --git a/tools/nfctool/nfctool.h b/tools/nfctool/nfctool.h index 7c93210..da3c965 100644 --- a/tools/nfctool/nfctool.h +++ b/tools/nfctool/nfctool.h @@ -67,6 +67,7 @@ struct nfctool_options { guint32 adapter_idx; bool enable_dev; bool disable_dev; + gchar *fw_filename; bool set_param; gint32 lto; gint32 rw; -- 2.7.4