ndef: Add support for WiFi Handover through MIME/x-nfctl 76/30776/1
authorSamuel Ortiz <sameo@linux.intel.com>
Wed, 21 Aug 2013 22:13:00 +0000 (00:13 +0200)
committerArron Wang <arron.wang@intel.com>
Tue, 25 Nov 2014 07:40:23 +0000 (15:40 +0800)
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: I49f13dc3b32b347357c6d2a13f6b3a132ad74dab
Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
Makefile.am
src/ndef.c
test/test-device
test/wifi-handover [new file with mode: 0755]

index 32a3e91..001f82c 100644 (file)
@@ -81,7 +81,7 @@ dist_man_MANS = doc/neard.8 doc/neard.conf.5 doc/nfctool.1
 test_scripts = test/test-adapter test/test-device \
                test/test-tag test/monitor-near test/bt-handover \
                test/handover-agent test/phdc-simple-manager \
-               test/neardutils.py
+               test/neardutils.py test/wifi-handover
 
 if TEST
 testdir = $(pkglibdir)/test
index 4427f08..a729b84 100644 (file)
@@ -3536,6 +3536,59 @@ static struct near_ndef_message *near_ndef_prepare_mime_payload_record(
        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;
@@ -3592,6 +3645,31 @@ 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
index 226408f..d3b6873 100755 (executable)
@@ -33,6 +33,7 @@ def usage():
        print "e.g. < %s push /org/neard/nfc0/device0 StaticHandover bluetooth,wifi >" % (sys.argv[0])
        print "e.g. < %s push /org/neard/nfc0/device0 MIME wifi_wsc>" % (sys.argv[0])
        print "e.g. < %s push /org/neard/nfc0/device0 MIME raw application/xml '<your><xml tags></your>' >" % (sys.argv[0])
+       print "e.g. < %s push /org/neard/nfc0/device0 WiFiAssociation >" % (sys.argv[0])
 
        sys.exit(1)
 
@@ -116,6 +117,9 @@ if (sys.argv[1] == "push"):
                        if sys.argv[4] in ["wifi_wsc"]:
                                device.Push(({ "Type" : "MIME",
                                        "MIME" : "application/vnd.wfa.wsc"}))
+               elif sys.argv[3] in ["WiFiAssociation"]:
+                       device.Push(({ "Type" : "MIME",
+                                       "MIME" : "x/nfctl" }))
                else:
                        usage()
        else:
diff --git a/test/wifi-handover b/test/wifi-handover
new file mode 100755 (executable)
index 0000000..54c6347
--- /dev/null
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+
+import os
+import sys
+import gobject
+
+import dbus
+import dbus.mainloop.glib
+
+import neardutils
+
+from dbus.lowlevel import MethodCallMessage, HANDLER_RESULT_NOT_YET_HANDLED
+
+mainloop = gobject.MainLoop()
+
+def device_added(path, interfaces):
+       for iface, props in interfaces.iteritems():
+               if "org.neard.Device" in interfaces:
+                       print("Pairing with %s" % (path))
+                       device = dbus.Interface(bus.get_object("org.neard", path),
+                                                       "org.neard.Device")
+                       device.Push(({ "Type" : "MIME", "MIME" : "x/nfctl"}))
+                       break
+
+def device_removed(path, interfaces):
+       for iface in interfaces:
+               if "org.neard.Device" in interfaces:
+                       print("Lost device %s" % (path))
+                       mainloop.quit()
+                       break
+
+if __name__ == '__main__':
+       dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+       bus = dbus.SystemBus()
+
+       adapter_path = neardutils.find_adapter().object_path
+       print("Adapter path %s" % (adapter_path))
+       adapter = dbus.Interface(bus.get_object("org.neard", adapter_path),
+                                               "org.neard.Adapter")
+
+       adapter_props = dbus.Interface(bus.get_object("org.neard", adapter_path),
+                                               "org.freedesktop.DBus.Properties")
+       powered = adapter_props.Get("org.neard.Adapter", "Powered")
+       if (powered == dbus.Boolean(0)):
+               adapter_props.Set("org.neard.Adapter", "Powered", dbus.Boolean(1))
+
+       polling = adapter_props.Get("org.neard.Adapter", "Polling")
+       if (polling == dbus.Boolean(0)):
+               adapter.StopPollLoop()
+
+        print "Starting poll on %s" % (adapter_path)
+       adapter.StartPollLoop("Initiator")
+
+       bus.add_signal_receiver(device_added, bus_name="org.neard",
+                       dbus_interface="org.freedesktop.DBus.ObjectManager",
+                       signal_name="InterfacesAdded")
+
+       bus.add_signal_receiver(device_removed, bus_name="org.neard",
+                       dbus_interface="org.freedesktop.DBus.ObjectManager",
+                       signal_name="InterfacesRemoved")
+
+       mainloop.run()