summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2013-08-22 00:13:00 +0200
committerGeoffroy Van Cutsem <geoffroy.vancutsem@intel.com>2013-09-13 12:20:45 +0200
commit42f0ea2bf7fc32c52e26bf962fbd4218c72b5eef (patch)
tree5e0fc23cab48b7d0a09d6d4a3c141c5a34a898f1
parent62e2fa054ed5823a08ec3f3bbadb4a9c5814300c (diff)
downloadneard-42f0ea2bf7fc32c52e26bf962fbd4218c72b5eef.tar.gz
neard-42f0ea2bf7fc32c52e26bf962fbd4218c72b5eef.tar.bz2
neard-42f0ea2bf7fc32c52e26bf962fbd4218c72b5eef.zip
ndef: Add support for WiFi Handover through MIME/x-nfctl
The NFC task launcher Android application reads NFC tags formatted with a proprietary MIME/x-nfctl NDEF containing an SSID and a passphrase. By pushing the same kind of NDEF through SNEP, a WiFi association with the neard WiFi handover agent can be triggered. Change-Id: I11a64dfbf05b9db3e444e2ee4df09a843244f6c2 Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
-rw-r--r--Makefile.am2
-rw-r--r--src/ndef.c155
-rwxr-xr-xtest/push-device9
-rwxr-xr-xtest/wifi-handover58
4 files changed, 223 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 175cf07..fd2bb90 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -81,7 +81,7 @@ dist_man_MANS = doc/neard.8 doc/neard.conf.5 doc/nfctool.1
test_scripts = test/disable-adapter test/enable-adapter test/list-adapters \
test/dump-device test/dump-tag test/dump-record \
test/monitor-near test/start-poll test/stop-poll test/write-tag \
- test/push-device test/bt-handover test/handover-agent
+ test/push-device test/bt-handover test/handover-agent test/wifi-handover
if TEST
testdir = $(pkglibdir)/test
diff --git a/src/ndef.c b/src/ndef.c
index 4cf5199..b71558b 100644
--- a/src/ndef.c
+++ b/src/ndef.c
@@ -3273,6 +3273,119 @@ struct near_ndef_message *near_ndef_prepare_wsc_record(char *ssid,
return mime;
}
+static char *get_mime_payload_data(DBusMessageIter iter,
+ char **payload, int *payload_len)
+{
+ DBG("");
+
+ if (!payload || !payload_len) {
+ near_error("Payload %p payload_len %p", payload, payload_len);
+ return NULL;
+ }
+
+ while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
+ const char *key;
+ DBusMessageIter ent_iter;
+ DBusMessageIter var_iter;
+ DBusMessageIter arr_iter;
+
+ dbus_message_iter_recurse(&iter, &ent_iter);
+ dbus_message_iter_get_basic(&ent_iter, &key);
+ dbus_message_iter_next(&ent_iter);
+ dbus_message_iter_recurse(&ent_iter, &var_iter);
+
+ if (g_strcmp0(key, "Payload") == 0) {
+ if (dbus_message_iter_get_arg_type(&var_iter) ==
+ DBUS_TYPE_ARRAY &&
+ dbus_message_iter_get_element_type(&var_iter) ==
+ DBUS_TYPE_BYTE) {
+ dbus_message_iter_recurse(&var_iter,
+ &arr_iter);
+ dbus_message_iter_get_fixed_array(
+ &arr_iter, payload,
+ payload_len);
+ } else {
+ near_error("Unexpected payload type");
+ return NULL;
+ }
+ }
+ dbus_message_iter_next(&iter);
+ }
+
+ return *payload;
+}
+
+static struct near_ndef_message *near_ndef_prepare_mime_payload_record(
+ char *type, char *payload, int payload_len)
+{
+ struct near_ndef_message *mime;
+
+ DBG("Payload %*s", payload_len, payload);
+ mime = ndef_message_alloc_complete(type, payload_len, NULL, 0,
+ RECORD_TNF_MIME, TRUE, TRUE);
+ if (!mime) {
+ near_error("Failed to alloc NDEF message");
+ return NULL;
+ }
+
+ memcpy(mime->data + mime->offset, payload, payload_len);
+
+ return mime;
+}
+
+#define DE_AUTHENTICATION_TYPE 0x1003
+#define DE_NETWORK_KEY 0x1027
+#define DE_SSID 0x1045
+static void parse_wsc_oob(guint8 *oob_data, guint32 oob_length,
+ char **ssid, char **passphrase)
+{
+ guint32 offset = 0;
+ guint16 de_length, de_type;
+ guint16 auth_type;
+
+ while (offset < oob_length) {
+ de_type = near_get_be16(oob_data + offset);
+ de_length = near_get_be16(oob_data + offset + 2);
+
+ switch(de_type) {
+ case DE_AUTHENTICATION_TYPE:
+ auth_type = near_get_be16(oob_data + offset + 4);
+ DBG("WSC Authentication Type: 0x%02x",
+ auth_type);
+ break;
+
+ case DE_SSID:
+ *ssid = g_try_malloc0(de_length + 1);
+ if (!*ssid)
+ break;
+
+ g_snprintf(*ssid, de_length + 1,
+ "%s", oob_data + offset + 4);
+
+ DBG("SSID: %s", *ssid);
+ break;
+
+ case DE_NETWORK_KEY:
+ *passphrase = g_try_malloc0(de_length + 1);
+ if (!*passphrase)
+ break;
+
+ g_snprintf(*passphrase, de_length + 1,
+ "%s", oob_data + offset + 4);
+
+ DBG("Passphrase: %s", *passphrase);
+ break;
+
+ default:
+ DBG("Unknown Data Element");
+ break;
+
+ }
+
+ offset += 4 + de_length;
+ }
+}
+
static struct near_ndef_message *build_mime_record(DBusMessage *msg)
{
DBusMessageIter iter, arr_iter;
@@ -3329,6 +3442,48 @@ static struct near_ndef_message *build_mime_record(DBusMessage *msg)
g_free(carrier);
return mime;
+ } else if (g_strcmp0(mime_str, "x/nfctl") == 0) {
+ struct carrier_data *carrier;
+ char *ssid = NULL, *passphrase = NULL;
+ char payload[128];
+
+ carrier = __near_agent_handover_request_data(
+ HO_AGENT_WIFI, NULL);
+ if (!carrier)
+ return NULL;
+
+ parse_wsc_oob(carrier->data, carrier->size,
+ &ssid, &passphrase);
+ if (!ssid || !passphrase)
+ return NULL;
+
+ g_snprintf(payload, 128,
+ "enZ:wifi association;C:I4:%s:2:%s",
+ ssid, passphrase);
+ g_free(ssid);
+ g_free(passphrase);
+
+ DBG("payload %s", payload);
+
+ return near_ndef_prepare_mime_payload_record(
+ mime_str, payload, strlen(payload));
+ } else {
+ /*
+ * Expect data is set in the Payload field of
+ * message.
+ */
+ DBusMessageIter payload_iter;
+ char *payload;
+ int payload_len;
+
+ DBG("mime string %s", mime_str);
+ dbus_message_iter_recurse(&iter, &payload_iter);
+ if (!get_mime_payload_data(payload_iter,
+ &payload, &payload_len))
+ return NULL;
+
+ return near_ndef_prepare_mime_payload_record(
+ mime_str, payload, payload_len);
}
}
diff --git a/test/push-device b/test/push-device
index b0b0c55..d1a142d 100755
--- a/test/push-device
+++ b/test/push-device
@@ -17,6 +17,8 @@ def help_text():
print "e.g. < %s /org/neard/nfc0/device0 Handover bluetooth,wifi >" % (sys.argv[0])
print "e.g. < %s /org/neard/nfc0/device0 StaticHandover bluetooth,wifi >" % (sys.argv[0])
print "e.g. < %s /org/neard/nfc0/device0 MIME wifi_wsc>" % (sys.argv[0])
+ print "e.g. < %s /org/neard/nfc0/device0 MIME raw application/xml '<your><xml tags></your>' >" % (sys.argv[0])
+ print "e.g. < %s /org/neard/nfc0/device0 WiFiAssociation >" % (sys.argv[0])
sys.exit(1)
if len(sys.argv) < 2:
@@ -57,5 +59,12 @@ elif len(sys.argv) == 4:
help_text()
else:
help_text()
+
+elif len(sys.argv) == 3:
+ if sys.argv[2] in ["WiFiAssociation"]:
+ device.Push(({ "Type" : "MIME",
+ "MIME" : "x/nfctl" }))
+ else:
+ help_text()
else:
help_text()
diff --git a/test/wifi-handover b/test/wifi-handover
new file mode 100755
index 0000000..5bf966c
--- /dev/null
+++ b/test/wifi-handover
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
+import os
+import sys
+import gobject
+
+import dbus
+import dbus.mainloop.glib
+
+from dbus.lowlevel import MethodCallMessage, HANDLER_RESULT_NOT_YET_HANDLED
+
+mainloop = gobject.MainLoop()
+
+def property_changed_adapter(name, value, path):
+ if name in ["Devices"]:
+ if (len(value) == 0):
+ print "Lost device, exiting"
+ mainloop.quit()
+ else:
+ device_path = value[0]
+
+ print "%s is associating with us..." % (device_path)
+
+ device = dbus.Interface(bus.get_object("org.neard", device_path), "org.neard.Device")
+ device.Push(({ "Type" : "MIME", "MIME" : "x/nfctl"}))
+
+if __name__ == '__main__':
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+ bus = dbus.SystemBus()
+
+
+ manager = dbus.Interface(bus.get_object("org.neard", "/"),
+ "org.neard.Manager")
+
+ properties = manager.GetProperties()
+ device_path = properties["Adapters"][0]
+ adapter = dbus.Interface(bus.get_object("org.neard", device_path),
+ "org.neard.Adapter")
+
+ adapter_properties = adapter.GetProperties()
+
+ for key in adapter_properties.keys():
+ if key in ["Polling"]:
+ if adapter_properties[key] == dbus.Boolean(1):
+ print "Stoping poll on %s" % (device_path)
+ adapter.StopPollLoop()
+
+ print "Starting poll on %s" % (device_path)
+ adapter.StartPollLoop("Initiator")
+
+ bus.add_signal_receiver(property_changed_adapter,
+ bus_name="org.neard",
+ dbus_interface="org.neard.Adapter",
+ signal_name = "PropertyChanged",
+ path_keyword="path")
+
+ mainloop.run()