1252190Srpaulo#!/usr/bin/python
2252190Srpaulo#
3252190Srpaulo# Example nfcpy to wpa_supplicant wrapper for WPS NFC operations
4252190Srpaulo# Copyright (c) 2012, Jouni Malinen <j@w1.fi>
5252190Srpaulo#
6252190Srpaulo# This software may be distributed under the terms of the BSD license.
7252190Srpaulo# See README for more details.
8252190Srpaulo
9252190Srpauloimport os
10252190Srpauloimport sys
11252190Srpauloimport time
12252190Srpaulo
13252190Srpauloimport nfc
14252190Srpauloimport nfc.ndef
15252190Srpauloimport nfc.llcp
16252190Srpauloimport nfc.handover
17252190Srpaulo
18252190Srpauloimport wpactrl
19252190Srpaulo
20252190Srpaulowpas_ctrl = '/var/run/wpa_supplicant'
21252190Srpaulo
22252190Srpaulodef wpas_connect():
23252190Srpaulo    ifaces = []
24252190Srpaulo    if os.path.isdir(wpas_ctrl):
25252190Srpaulo        try:
26252190Srpaulo            ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
27252190Srpaulo        except OSError, error:
28252190Srpaulo            print "Could not find wpa_supplicant: ", error
29252190Srpaulo            return None
30252190Srpaulo
31252190Srpaulo    if len(ifaces) < 1:
32252190Srpaulo        print "No wpa_supplicant control interface found"
33252190Srpaulo        return None
34252190Srpaulo
35252190Srpaulo    for ctrl in ifaces:
36252190Srpaulo        try:
37252190Srpaulo            wpas = wpactrl.WPACtrl(ctrl)
38252190Srpaulo            return wpas
39252190Srpaulo        except wpactrl.error, error:
40252190Srpaulo            print "Error: ", error
41252190Srpaulo            pass
42252190Srpaulo    return None
43252190Srpaulo
44252190Srpaulo
45252190Srpaulodef wpas_tag_read(message):
46252190Srpaulo    wpas = wpas_connect()
47252190Srpaulo    if (wpas == None):
48252190Srpaulo        return
49252190Srpaulo    print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex"))
50252190Srpaulo
51252190Srpaulo
52252190Srpaulodef wpas_get_handover_req():
53252190Srpaulo    wpas = wpas_connect()
54252190Srpaulo    if (wpas == None):
55252190Srpaulo        return None
56252190Srpaulo    return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS").rstrip().decode("hex")
57252190Srpaulo
58252190Srpaulo
59252190Srpaulodef wpas_put_handover_sel(message):
60252190Srpaulo    wpas = wpas_connect()
61252190Srpaulo    if (wpas == None):
62252190Srpaulo        return
63252190Srpaulo    print wpas.request("NFC_RX_HANDOVER_SEL " + str(message).encode("hex"))
64252190Srpaulo
65252190Srpaulo
66252190Srpaulodef wps_handover_init(peer):
67252190Srpaulo    print "Trying to initiate WPS handover"
68252190Srpaulo
69252190Srpaulo    data = wpas_get_handover_req()
70252190Srpaulo    if (data == None):
71252190Srpaulo        print "Could not get handover request message from wpa_supplicant"
72252190Srpaulo        return
73252190Srpaulo    print "Handover request from wpa_supplicant: " + data.encode("hex")
74252190Srpaulo    message = nfc.ndef.Message(data)
75252190Srpaulo    print "Parsed handover request: " + message.pretty()
76252190Srpaulo
77252190Srpaulo    nfc.llcp.activate(peer);
78252190Srpaulo    time.sleep(0.5)
79252190Srpaulo
80252190Srpaulo    client = nfc.handover.HandoverClient()
81252190Srpaulo    try:
82252190Srpaulo        print "Trying handover";
83252190Srpaulo        client.connect()
84252190Srpaulo        print "Connected for handover"
85252190Srpaulo    except nfc.llcp.ConnectRefused:
86252190Srpaulo        print "Handover connection refused"
87252190Srpaulo        nfc.llcp.shutdown()
88252190Srpaulo        client.close()
89252190Srpaulo        return
90252190Srpaulo
91252190Srpaulo    print "Sending handover request"
92252190Srpaulo
93252190Srpaulo    if not client.send(message):
94252190Srpaulo        print "Failed to send handover request"
95252190Srpaulo
96252190Srpaulo    print "Receiving handover response"
97252190Srpaulo    message = client._recv()
98252190Srpaulo    print "Handover select received"
99252190Srpaulo    print message.pretty()
100252190Srpaulo    wpas_put_handover_sel(message)
101252190Srpaulo
102252190Srpaulo    print "Remove peer"
103252190Srpaulo    nfc.llcp.shutdown()
104252190Srpaulo    client.close()
105252190Srpaulo    print "Done with handover"
106252190Srpaulo
107252190Srpaulo
108252190Srpaulodef wps_tag_read(tag):
109252190Srpaulo    if len(tag.ndef.message):
110252190Srpaulo        message = nfc.ndef.Message(tag.ndef.message)
111252190Srpaulo        print "message type " + message.type
112252190Srpaulo
113252190Srpaulo        for record in message:
114252190Srpaulo            print "record type " + record.type
115252190Srpaulo            if record.type == "application/vnd.wfa.wsc":
116252190Srpaulo                print "WPS tag - send to wpa_supplicant"
117252190Srpaulo                wpas_tag_read(tag.ndef.message)
118252190Srpaulo                break
119252190Srpaulo    else:
120252190Srpaulo        print "Empty tag"
121252190Srpaulo
122252190Srpaulo    print "Remove tag"
123252190Srpaulo    while tag.is_present:
124252190Srpaulo        time.sleep(0.1)
125252190Srpaulo
126252190Srpaulo
127252190Srpaulodef main():
128252190Srpaulo    clf = nfc.ContactlessFrontend()
129252190Srpaulo
130252190Srpaulo    try:
131252190Srpaulo        while True:
132252190Srpaulo            print "Waiting for a tag or peer to be touched"
133252190Srpaulo
134252190Srpaulo            while True:
135252190Srpaulo                general_bytes = nfc.llcp.startup({})
136252190Srpaulo                tag = clf.poll(general_bytes)
137252190Srpaulo                if tag == None:
138252190Srpaulo                    continue
139252190Srpaulo
140252190Srpaulo                if isinstance(tag, nfc.DEP):
141252190Srpaulo                    wps_handover_init(tag)
142252190Srpaulo                    break
143252190Srpaulo
144252190Srpaulo                if tag.ndef:
145252190Srpaulo                    wps_tag_read(tag)
146252190Srpaulo                    break
147252190Srpaulo
148252190Srpaulo                if tag:
149252190Srpaulo                    print "Not an NDEF tag - remove tag"
150252190Srpaulo                    while tag.is_present:
151252190Srpaulo                        time.sleep(0.1)
152252190Srpaulo                    break
153252190Srpaulo
154252190Srpaulo    except KeyboardInterrupt:
155252190Srpaulo        raise SystemExit
156252190Srpaulo    finally:
157252190Srpaulo        clf.close()
158252190Srpaulo
159252190Srpaulo    raise SystemExit
160252190Srpaulo
161252190Srpauloif __name__ == '__main__':
162252190Srpaulo    main()
163