WPS: Remove 0.5 sec extra wait from NFC handover with nfcpy
[mech_eap.git] / wpa_supplicant / examples / wps-nfc.py
1 #!/usr/bin/python
2 #
3 # Example nfcpy to wpa_supplicant wrapper for WPS NFC operations
4 # Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi>
5 #
6 # This software may be distributed under the terms of the BSD license.
7 # See README for more details.
8
9 import os
10 import sys
11 import time
12
13 import nfc
14 import nfc.ndef
15 import nfc.llcp
16 import nfc.handover
17
18 import logging
19 logging.basicConfig()
20
21 import wpactrl
22
23 wpas_ctrl = '/var/run/wpa_supplicant'
24
25 def wpas_connect():
26     ifaces = []
27     if os.path.isdir(wpas_ctrl):
28         try:
29             ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)]
30         except OSError, error:
31             print "Could not find wpa_supplicant: ", error
32             return None
33
34     if len(ifaces) < 1:
35         print "No wpa_supplicant control interface found"
36         return None
37
38     for ctrl in ifaces:
39         try:
40             wpas = wpactrl.WPACtrl(ctrl)
41             return wpas
42         except wpactrl.error, error:
43             print "Error: ", error
44             pass
45     return None
46
47
48 def wpas_tag_read(message):
49     wpas = wpas_connect()
50     if (wpas == None):
51         return
52     print wpas.request("WPS_NFC_TAG_READ " + message.encode("hex"))
53
54
55 def wpas_get_handover_req():
56     wpas = wpas_connect()
57     if (wpas == None):
58         return None
59     return wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS").rstrip().decode("hex")
60
61
62 def wpas_put_handover_sel(message):
63     wpas = wpas_connect()
64     if (wpas == None):
65         return
66     print wpas.request("NFC_RX_HANDOVER_SEL " + str(message).encode("hex"))
67
68
69 def wps_handover_init(peer):
70     print "Trying to initiate WPS handover"
71
72     data = wpas_get_handover_req()
73     if (data == None):
74         print "Could not get handover request message from wpa_supplicant"
75         return
76     print "Handover request from wpa_supplicant: " + data.encode("hex")
77     message = nfc.ndef.Message(data)
78     print "Parsed handover request: " + message.pretty()
79
80     nfc.llcp.activate(peer);
81
82     client = nfc.handover.HandoverClient()
83     try:
84         print "Trying handover";
85         client.connect()
86         print "Connected for handover"
87     except nfc.llcp.ConnectRefused:
88         print "Handover connection refused"
89         nfc.llcp.shutdown()
90         client.close()
91         return
92
93     print "Sending handover request"
94
95     if not client.send(message):
96         print "Failed to send handover request"
97
98     print "Receiving handover response"
99     message = client._recv()
100     print "Handover select received"
101     print message.pretty()
102     wpas_put_handover_sel(message)
103
104     print "Remove peer"
105     nfc.llcp.shutdown()
106     client.close()
107     print "Done with handover"
108
109
110 def wps_tag_read(tag):
111     if len(tag.ndef.message):
112         message = nfc.ndef.Message(tag.ndef.message)
113         print "message type " + message.type
114
115         for record in message:
116             print "record type " + record.type
117             if record.type == "application/vnd.wfa.wsc":
118                 print "WPS tag - send to wpa_supplicant"
119                 wpas_tag_read(tag.ndef.message)
120                 break
121     else:
122         print "Empty tag"
123
124     print "Remove tag"
125     while tag.is_present:
126         time.sleep(0.1)
127
128
129 def find_peer(clf):
130     while True:
131         if nfc.llcp.connected():
132             print "LLCP connected"
133         general_bytes = nfc.llcp.startup({})
134         peer = clf.listen(ord(os.urandom(1)) + 200, general_bytes)
135         if isinstance(peer, nfc.DEP):
136             print "listen -> DEP";
137             if peer.general_bytes.startswith("Ffm"):
138                 print "Found DEP"
139                 return peer
140             print "mismatch in general_bytes"
141             print peer.general_bytes
142
143         peer = clf.poll(general_bytes)
144         if isinstance(peer, nfc.DEP):
145             print "poll -> DEP";
146             if peer.general_bytes.startswith("Ffm"):
147                 print "Found DEP"
148                 return peer
149             print "mismatch in general_bytes"
150             print peer.general_bytes
151
152         if peer:
153             print "Found tag"
154             return peer
155
156
157 def main():
158     clf = nfc.ContactlessFrontend()
159
160     try:
161         while True:
162             print "Waiting for a tag or peer to be touched"
163
164             tag = find_peer(clf)
165             if isinstance(tag, nfc.DEP):
166                 wps_handover_init(tag)
167                 continue
168
169             if tag.ndef:
170                 wps_tag_read(tag)
171                 continue
172
173             print "Not an NDEF tag - remove tag"
174             while tag.is_present:
175                 time.sleep(0.1)
176
177     except KeyboardInterrupt:
178         raise SystemExit
179     finally:
180         clf.close()
181
182     raise SystemExit
183
184 if __name__ == '__main__':
185     main()