#include <sys/socket.h>
#include <glib.h>
+#include <netlink/genl/genl.h>
+
#include <near/nfc_copy.h>
#include "nfctool.h"
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;
"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,
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));
}
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");
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);
}
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)
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:
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;