15b9c547cSRui Paulo#!/usr/bin/python 25b9c547cSRui Paulo# 35b9c547cSRui Paulo# Example nfcpy to wpa_supplicant wrapper for P2P NFC operations 45b9c547cSRui Paulo# Copyright (c) 2012-2013, Jouni Malinen <j@w1.fi> 55b9c547cSRui Paulo# 65b9c547cSRui Paulo# This software may be distributed under the terms of the BSD license. 75b9c547cSRui Paulo# See README for more details. 85b9c547cSRui Paulo 95b9c547cSRui Pauloimport os 105b9c547cSRui Pauloimport sys 115b9c547cSRui Pauloimport time 125b9c547cSRui Pauloimport random 135b9c547cSRui Pauloimport threading 145b9c547cSRui Pauloimport argparse 155b9c547cSRui Paulo 165b9c547cSRui Pauloimport nfc 175b9c547cSRui Pauloimport nfc.ndef 185b9c547cSRui Pauloimport nfc.llcp 195b9c547cSRui Pauloimport nfc.handover 205b9c547cSRui Paulo 215b9c547cSRui Pauloimport logging 225b9c547cSRui Paulo 235b9c547cSRui Pauloimport wpaspy 245b9c547cSRui Paulo 255b9c547cSRui Paulowpas_ctrl = '/var/run/wpa_supplicant' 265b9c547cSRui Pauloifname = None 275b9c547cSRui Pauloinit_on_touch = False 285b9c547cSRui Pauloin_raw_mode = False 295b9c547cSRui Pauloprev_tcgetattr = 0 305b9c547cSRui Pauloinclude_wps_req = True 315b9c547cSRui Pauloinclude_p2p_req = True 325b9c547cSRui Paulono_input = False 335b9c547cSRui Paulosrv = None 345b9c547cSRui Paulocontinue_loop = True 355b9c547cSRui Pauloterminate_now = False 365b9c547cSRui Paulosummary_file = None 375b9c547cSRui Paulosuccess_file = None 385b9c547cSRui Paulo 395b9c547cSRui Paulodef summary(txt): 40*4bc52338SCy Schubert print(txt) 415b9c547cSRui Paulo if summary_file: 425b9c547cSRui Paulo with open(summary_file, 'a') as f: 435b9c547cSRui Paulo f.write(txt + "\n") 445b9c547cSRui Paulo 455b9c547cSRui Paulodef success_report(txt): 465b9c547cSRui Paulo summary(txt) 475b9c547cSRui Paulo if success_file: 485b9c547cSRui Paulo with open(success_file, 'a') as f: 495b9c547cSRui Paulo f.write(txt + "\n") 505b9c547cSRui Paulo 515b9c547cSRui Paulodef wpas_connect(): 525b9c547cSRui Paulo ifaces = [] 535b9c547cSRui Paulo if os.path.isdir(wpas_ctrl): 545b9c547cSRui Paulo try: 555b9c547cSRui Paulo ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] 56*4bc52338SCy Schubert except OSError as error: 57*4bc52338SCy Schubert print("Could not find wpa_supplicant: ", error) 585b9c547cSRui Paulo return None 595b9c547cSRui Paulo 605b9c547cSRui Paulo if len(ifaces) < 1: 61*4bc52338SCy Schubert print("No wpa_supplicant control interface found") 625b9c547cSRui Paulo return None 635b9c547cSRui Paulo 645b9c547cSRui Paulo for ctrl in ifaces: 655b9c547cSRui Paulo if ifname: 665b9c547cSRui Paulo if ifname not in ctrl: 675b9c547cSRui Paulo continue 685b9c547cSRui Paulo try: 69*4bc52338SCy Schubert print("Trying to use control interface " + ctrl) 705b9c547cSRui Paulo wpas = wpaspy.Ctrl(ctrl) 715b9c547cSRui Paulo return wpas 72*4bc52338SCy Schubert except Exception as e: 735b9c547cSRui Paulo pass 745b9c547cSRui Paulo return None 755b9c547cSRui Paulo 765b9c547cSRui Paulo 775b9c547cSRui Paulodef wpas_tag_read(message): 785b9c547cSRui Paulo wpas = wpas_connect() 795b9c547cSRui Paulo if (wpas == None): 805b9c547cSRui Paulo return False 815b9c547cSRui Paulo cmd = "WPS_NFC_TAG_READ " + str(message).encode("hex") 825b9c547cSRui Paulo global force_freq 835b9c547cSRui Paulo if force_freq: 845b9c547cSRui Paulo cmd = cmd + " freq=" + force_freq 855b9c547cSRui Paulo if "FAIL" in wpas.request(cmd): 865b9c547cSRui Paulo return False 875b9c547cSRui Paulo return True 885b9c547cSRui Paulo 895b9c547cSRui Paulo 905b9c547cSRui Paulodef wpas_get_handover_req(): 915b9c547cSRui Paulo wpas = wpas_connect() 925b9c547cSRui Paulo if (wpas == None): 935b9c547cSRui Paulo return None 945b9c547cSRui Paulo res = wpas.request("NFC_GET_HANDOVER_REQ NDEF P2P-CR").rstrip() 955b9c547cSRui Paulo if "FAIL" in res: 965b9c547cSRui Paulo return None 975b9c547cSRui Paulo return res.decode("hex") 985b9c547cSRui Paulo 995b9c547cSRui Paulodef wpas_get_handover_req_wps(): 1005b9c547cSRui Paulo wpas = wpas_connect() 1015b9c547cSRui Paulo if (wpas == None): 1025b9c547cSRui Paulo return None 1035b9c547cSRui Paulo res = wpas.request("NFC_GET_HANDOVER_REQ NDEF WPS-CR").rstrip() 1045b9c547cSRui Paulo if "FAIL" in res: 1055b9c547cSRui Paulo return None 1065b9c547cSRui Paulo return res.decode("hex") 1075b9c547cSRui Paulo 1085b9c547cSRui Paulo 1095b9c547cSRui Paulodef wpas_get_handover_sel(tag=False): 1105b9c547cSRui Paulo wpas = wpas_connect() 1115b9c547cSRui Paulo if (wpas == None): 1125b9c547cSRui Paulo return None 1135b9c547cSRui Paulo if tag: 1145b9c547cSRui Paulo res = wpas.request("NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG").rstrip() 1155b9c547cSRui Paulo else: 1165b9c547cSRui Paulo res = wpas.request("NFC_GET_HANDOVER_SEL NDEF P2P-CR").rstrip() 1175b9c547cSRui Paulo if "FAIL" in res: 1185b9c547cSRui Paulo return None 1195b9c547cSRui Paulo return res.decode("hex") 1205b9c547cSRui Paulo 1215b9c547cSRui Paulo 1225b9c547cSRui Paulodef wpas_get_handover_sel_wps(): 1235b9c547cSRui Paulo wpas = wpas_connect() 1245b9c547cSRui Paulo if (wpas == None): 1255b9c547cSRui Paulo return None 1265b9c547cSRui Paulo res = wpas.request("NFC_GET_HANDOVER_SEL NDEF WPS-CR"); 1275b9c547cSRui Paulo if "FAIL" in res: 1285b9c547cSRui Paulo return None 1295b9c547cSRui Paulo return res.rstrip().decode("hex") 1305b9c547cSRui Paulo 1315b9c547cSRui Paulo 1325b9c547cSRui Paulodef wpas_report_handover(req, sel, type): 1335b9c547cSRui Paulo wpas = wpas_connect() 1345b9c547cSRui Paulo if (wpas == None): 1355b9c547cSRui Paulo return None 1365b9c547cSRui Paulo cmd = "NFC_REPORT_HANDOVER " + type + " P2P " + str(req).encode("hex") + " " + str(sel).encode("hex") 1375b9c547cSRui Paulo global force_freq 1385b9c547cSRui Paulo if force_freq: 1395b9c547cSRui Paulo cmd = cmd + " freq=" + force_freq 1405b9c547cSRui Paulo return wpas.request(cmd) 1415b9c547cSRui Paulo 1425b9c547cSRui Paulo 1435b9c547cSRui Paulodef wpas_report_handover_wsc(req, sel, type): 1445b9c547cSRui Paulo wpas = wpas_connect() 1455b9c547cSRui Paulo if (wpas == None): 1465b9c547cSRui Paulo return None 1475b9c547cSRui Paulo cmd = "NFC_REPORT_HANDOVER " + type + " WPS " + str(req).encode("hex") + " " + str(sel).encode("hex") 1485b9c547cSRui Paulo if force_freq: 1495b9c547cSRui Paulo cmd = cmd + " freq=" + force_freq 1505b9c547cSRui Paulo return wpas.request(cmd) 1515b9c547cSRui Paulo 1525b9c547cSRui Paulo 1535b9c547cSRui Paulodef p2p_handover_client(llc): 1545b9c547cSRui Paulo message = nfc.ndef.HandoverRequestMessage(version="1.2") 1555b9c547cSRui Paulo message.nonce = random.randint(0, 0xffff) 1565b9c547cSRui Paulo 1575b9c547cSRui Paulo global include_p2p_req 1585b9c547cSRui Paulo if include_p2p_req: 1595b9c547cSRui Paulo data = wpas_get_handover_req() 1605b9c547cSRui Paulo if (data == None): 1615b9c547cSRui Paulo summary("Could not get handover request carrier record from wpa_supplicant") 1625b9c547cSRui Paulo return 163*4bc52338SCy Schubert print("Handover request carrier record from wpa_supplicant: " + data.encode("hex")) 1645b9c547cSRui Paulo datamsg = nfc.ndef.Message(data) 1655b9c547cSRui Paulo message.add_carrier(datamsg[0], "active", datamsg[1:]) 1665b9c547cSRui Paulo 1675b9c547cSRui Paulo global include_wps_req 1685b9c547cSRui Paulo if include_wps_req: 169*4bc52338SCy Schubert print("Handover request (pre-WPS):") 1705b9c547cSRui Paulo try: 171*4bc52338SCy Schubert print(message.pretty()) 172*4bc52338SCy Schubert except Exception as e: 173*4bc52338SCy Schubert print(e) 1745b9c547cSRui Paulo 1755b9c547cSRui Paulo data = wpas_get_handover_req_wps() 1765b9c547cSRui Paulo if data: 177*4bc52338SCy Schubert print("Add WPS request in addition to P2P") 1785b9c547cSRui Paulo datamsg = nfc.ndef.Message(data) 1795b9c547cSRui Paulo message.add_carrier(datamsg[0], "active", datamsg[1:]) 1805b9c547cSRui Paulo 181*4bc52338SCy Schubert print("Handover request:") 1825b9c547cSRui Paulo try: 183*4bc52338SCy Schubert print(message.pretty()) 184*4bc52338SCy Schubert except Exception as e: 185*4bc52338SCy Schubert print(e) 186*4bc52338SCy Schubert print(str(message).encode("hex")) 1875b9c547cSRui Paulo 1885b9c547cSRui Paulo client = nfc.handover.HandoverClient(llc) 1895b9c547cSRui Paulo try: 1905b9c547cSRui Paulo summary("Trying to initiate NFC connection handover") 1915b9c547cSRui Paulo client.connect() 1925b9c547cSRui Paulo summary("Connected for handover") 1935b9c547cSRui Paulo except nfc.llcp.ConnectRefused: 1945b9c547cSRui Paulo summary("Handover connection refused") 1955b9c547cSRui Paulo client.close() 1965b9c547cSRui Paulo return 197*4bc52338SCy Schubert except Exception as e: 1985b9c547cSRui Paulo summary("Other exception: " + str(e)) 1995b9c547cSRui Paulo client.close() 2005b9c547cSRui Paulo return 2015b9c547cSRui Paulo 2025b9c547cSRui Paulo summary("Sending handover request") 2035b9c547cSRui Paulo 2045b9c547cSRui Paulo if not client.send(message): 2055b9c547cSRui Paulo summary("Failed to send handover request") 2065b9c547cSRui Paulo client.close() 2075b9c547cSRui Paulo return 2085b9c547cSRui Paulo 2095b9c547cSRui Paulo summary("Receiving handover response") 2105b9c547cSRui Paulo message = client._recv() 2115b9c547cSRui Paulo if message is None: 2125b9c547cSRui Paulo summary("No response received") 2135b9c547cSRui Paulo client.close() 2145b9c547cSRui Paulo return 2155b9c547cSRui Paulo if message.type != "urn:nfc:wkt:Hs": 2165b9c547cSRui Paulo summary("Response was not Hs - received: " + message.type) 2175b9c547cSRui Paulo client.close() 2185b9c547cSRui Paulo return 2195b9c547cSRui Paulo 220*4bc52338SCy Schubert print("Received message") 2215b9c547cSRui Paulo try: 222*4bc52338SCy Schubert print(message.pretty()) 223*4bc52338SCy Schubert except Exception as e: 224*4bc52338SCy Schubert print(e) 225*4bc52338SCy Schubert print(str(message).encode("hex")) 2265b9c547cSRui Paulo message = nfc.ndef.HandoverSelectMessage(message) 2275b9c547cSRui Paulo summary("Handover select received") 2285b9c547cSRui Paulo try: 229*4bc52338SCy Schubert print(message.pretty()) 230*4bc52338SCy Schubert except Exception as e: 231*4bc52338SCy Schubert print(e) 2325b9c547cSRui Paulo 2335b9c547cSRui Paulo for carrier in message.carriers: 234*4bc52338SCy Schubert print("Remote carrier type: " + carrier.type) 2355b9c547cSRui Paulo if carrier.type == "application/vnd.wfa.p2p": 236*4bc52338SCy Schubert print("P2P carrier type match - send to wpa_supplicant") 2375b9c547cSRui Paulo if "OK" in wpas_report_handover(data, carrier.record, "INIT"): 2385b9c547cSRui Paulo success_report("P2P handover reported successfully (initiator)") 2395b9c547cSRui Paulo else: 2405b9c547cSRui Paulo summary("P2P handover report rejected") 2415b9c547cSRui Paulo break 2425b9c547cSRui Paulo 243*4bc52338SCy Schubert print("Remove peer") 2445b9c547cSRui Paulo client.close() 245*4bc52338SCy Schubert print("Done with handover") 2465b9c547cSRui Paulo global only_one 2475b9c547cSRui Paulo if only_one: 248*4bc52338SCy Schubert print("only_one -> stop loop") 2495b9c547cSRui Paulo global continue_loop 2505b9c547cSRui Paulo continue_loop = False 2515b9c547cSRui Paulo 2525b9c547cSRui Paulo global no_wait 2535b9c547cSRui Paulo if no_wait: 254*4bc52338SCy Schubert print("Trying to exit..") 2555b9c547cSRui Paulo global terminate_now 2565b9c547cSRui Paulo terminate_now = True 2575b9c547cSRui Paulo 2585b9c547cSRui Paulo 2595b9c547cSRui Pauloclass HandoverServer(nfc.handover.HandoverServer): 2605b9c547cSRui Paulo def __init__(self, llc): 2615b9c547cSRui Paulo super(HandoverServer, self).__init__(llc) 2625b9c547cSRui Paulo self.sent_carrier = None 2635b9c547cSRui Paulo self.ho_server_processing = False 2645b9c547cSRui Paulo self.success = False 2655b9c547cSRui Paulo 2665b9c547cSRui Paulo # override to avoid parser error in request/response.pretty() in nfcpy 2675b9c547cSRui Paulo # due to new WSC handover format 2685b9c547cSRui Paulo def _process_request(self, request): 2695b9c547cSRui Paulo summary("received handover request {}".format(request.type)) 2705b9c547cSRui Paulo response = nfc.ndef.Message("\xd1\x02\x01Hs\x12") 2715b9c547cSRui Paulo if not request.type == 'urn:nfc:wkt:Hr': 2725b9c547cSRui Paulo summary("not a handover request") 2735b9c547cSRui Paulo else: 2745b9c547cSRui Paulo try: 2755b9c547cSRui Paulo request = nfc.ndef.HandoverRequestMessage(request) 2765b9c547cSRui Paulo except nfc.ndef.DecodeError as e: 2775b9c547cSRui Paulo summary("error decoding 'Hr' message: {}".format(e)) 2785b9c547cSRui Paulo else: 2795b9c547cSRui Paulo response = self.process_request(request) 2805b9c547cSRui Paulo summary("send handover response {}".format(response.type)) 2815b9c547cSRui Paulo return response 2825b9c547cSRui Paulo 2835b9c547cSRui Paulo def process_request(self, request): 2845b9c547cSRui Paulo self.ho_server_processing = True 2855b9c547cSRui Paulo clear_raw_mode() 286*4bc52338SCy Schubert print("HandoverServer - request received") 2875b9c547cSRui Paulo try: 288*4bc52338SCy Schubert print("Parsed handover request: " + request.pretty()) 289*4bc52338SCy Schubert except Exception as e: 290*4bc52338SCy Schubert print(e) 2915b9c547cSRui Paulo 2925b9c547cSRui Paulo sel = nfc.ndef.HandoverSelectMessage(version="1.2") 2935b9c547cSRui Paulo 2945b9c547cSRui Paulo found = False 2955b9c547cSRui Paulo 2965b9c547cSRui Paulo for carrier in request.carriers: 297*4bc52338SCy Schubert print("Remote carrier type: " + carrier.type) 2985b9c547cSRui Paulo if carrier.type == "application/vnd.wfa.p2p": 299*4bc52338SCy Schubert print("P2P carrier type match - add P2P carrier record") 3005b9c547cSRui Paulo found = True 3015b9c547cSRui Paulo self.received_carrier = carrier.record 302*4bc52338SCy Schubert print("Carrier record:") 3035b9c547cSRui Paulo try: 304*4bc52338SCy Schubert print(carrier.record.pretty()) 305*4bc52338SCy Schubert except Exception as e: 306*4bc52338SCy Schubert print(e) 3075b9c547cSRui Paulo data = wpas_get_handover_sel() 3085b9c547cSRui Paulo if data is None: 309*4bc52338SCy Schubert print("Could not get handover select carrier record from wpa_supplicant") 3105b9c547cSRui Paulo continue 311*4bc52338SCy Schubert print("Handover select carrier record from wpa_supplicant:") 312*4bc52338SCy Schubert print(data.encode("hex")) 3135b9c547cSRui Paulo self.sent_carrier = data 3145b9c547cSRui Paulo if "OK" in wpas_report_handover(self.received_carrier, self.sent_carrier, "RESP"): 3155b9c547cSRui Paulo success_report("P2P handover reported successfully (responder)") 3165b9c547cSRui Paulo else: 3175b9c547cSRui Paulo summary("P2P handover report rejected") 3185b9c547cSRui Paulo break 3195b9c547cSRui Paulo 3205b9c547cSRui Paulo message = nfc.ndef.Message(data); 3215b9c547cSRui Paulo sel.add_carrier(message[0], "active", message[1:]) 3225b9c547cSRui Paulo break 3235b9c547cSRui Paulo 3245b9c547cSRui Paulo for carrier in request.carriers: 3255b9c547cSRui Paulo if found: 3265b9c547cSRui Paulo break 327*4bc52338SCy Schubert print("Remote carrier type: " + carrier.type) 3285b9c547cSRui Paulo if carrier.type == "application/vnd.wfa.wsc": 329*4bc52338SCy Schubert print("WSC carrier type match - add WSC carrier record") 3305b9c547cSRui Paulo found = True 3315b9c547cSRui Paulo self.received_carrier = carrier.record 332*4bc52338SCy Schubert print("Carrier record:") 3335b9c547cSRui Paulo try: 334*4bc52338SCy Schubert print(carrier.record.pretty()) 335*4bc52338SCy Schubert except Exception as e: 336*4bc52338SCy Schubert print(e) 3375b9c547cSRui Paulo data = wpas_get_handover_sel_wps() 3385b9c547cSRui Paulo if data is None: 339*4bc52338SCy Schubert print("Could not get handover select carrier record from wpa_supplicant") 3405b9c547cSRui Paulo continue 341*4bc52338SCy Schubert print("Handover select carrier record from wpa_supplicant:") 342*4bc52338SCy Schubert print(data.encode("hex")) 3435b9c547cSRui Paulo self.sent_carrier = data 3445b9c547cSRui Paulo if "OK" in wpas_report_handover_wsc(self.received_carrier, self.sent_carrier, "RESP"): 3455b9c547cSRui Paulo success_report("WSC handover reported successfully") 3465b9c547cSRui Paulo else: 3475b9c547cSRui Paulo summary("WSC handover report rejected") 3485b9c547cSRui Paulo break 3495b9c547cSRui Paulo 3505b9c547cSRui Paulo message = nfc.ndef.Message(data); 3515b9c547cSRui Paulo sel.add_carrier(message[0], "active", message[1:]) 3525b9c547cSRui Paulo found = True 3535b9c547cSRui Paulo break 3545b9c547cSRui Paulo 355*4bc52338SCy Schubert print("Handover select:") 3565b9c547cSRui Paulo try: 357*4bc52338SCy Schubert print(sel.pretty()) 358*4bc52338SCy Schubert except Exception as e: 359*4bc52338SCy Schubert print(e) 360*4bc52338SCy Schubert print(str(sel).encode("hex")) 3615b9c547cSRui Paulo 3625b9c547cSRui Paulo summary("Sending handover select") 3635b9c547cSRui Paulo self.success = True 3645b9c547cSRui Paulo return sel 3655b9c547cSRui Paulo 3665b9c547cSRui Paulo 3675b9c547cSRui Paulodef clear_raw_mode(): 3685b9c547cSRui Paulo import sys, tty, termios 3695b9c547cSRui Paulo global prev_tcgetattr, in_raw_mode 3705b9c547cSRui Paulo if not in_raw_mode: 3715b9c547cSRui Paulo return 3725b9c547cSRui Paulo fd = sys.stdin.fileno() 3735b9c547cSRui Paulo termios.tcsetattr(fd, termios.TCSADRAIN, prev_tcgetattr) 3745b9c547cSRui Paulo in_raw_mode = False 3755b9c547cSRui Paulo 3765b9c547cSRui Paulo 3775b9c547cSRui Paulodef getch(): 3785b9c547cSRui Paulo import sys, tty, termios, select 3795b9c547cSRui Paulo global prev_tcgetattr, in_raw_mode 3805b9c547cSRui Paulo fd = sys.stdin.fileno() 3815b9c547cSRui Paulo prev_tcgetattr = termios.tcgetattr(fd) 3825b9c547cSRui Paulo ch = None 3835b9c547cSRui Paulo try: 3845b9c547cSRui Paulo tty.setraw(fd) 3855b9c547cSRui Paulo in_raw_mode = True 3865b9c547cSRui Paulo [i, o, e] = select.select([fd], [], [], 0.05) 3875b9c547cSRui Paulo if i: 3885b9c547cSRui Paulo ch = sys.stdin.read(1) 3895b9c547cSRui Paulo finally: 3905b9c547cSRui Paulo termios.tcsetattr(fd, termios.TCSADRAIN, prev_tcgetattr) 3915b9c547cSRui Paulo in_raw_mode = False 3925b9c547cSRui Paulo return ch 3935b9c547cSRui Paulo 3945b9c547cSRui Paulo 3955b9c547cSRui Paulodef p2p_tag_read(tag): 3965b9c547cSRui Paulo success = False 3975b9c547cSRui Paulo if len(tag.ndef.message): 3985b9c547cSRui Paulo for record in tag.ndef.message: 399*4bc52338SCy Schubert print("record type " + record.type) 4005b9c547cSRui Paulo if record.type == "application/vnd.wfa.wsc": 4015b9c547cSRui Paulo summary("WPS tag - send to wpa_supplicant") 4025b9c547cSRui Paulo success = wpas_tag_read(tag.ndef.message) 4035b9c547cSRui Paulo break 4045b9c547cSRui Paulo if record.type == "application/vnd.wfa.p2p": 4055b9c547cSRui Paulo summary("P2P tag - send to wpa_supplicant") 4065b9c547cSRui Paulo success = wpas_tag_read(tag.ndef.message) 4075b9c547cSRui Paulo break 4085b9c547cSRui Paulo else: 4095b9c547cSRui Paulo summary("Empty tag") 4105b9c547cSRui Paulo 4115b9c547cSRui Paulo if success: 4125b9c547cSRui Paulo success_report("Tag read succeeded") 4135b9c547cSRui Paulo 4145b9c547cSRui Paulo return success 4155b9c547cSRui Paulo 4165b9c547cSRui Paulo 4175b9c547cSRui Paulodef rdwr_connected_p2p_write(tag): 4185b9c547cSRui Paulo summary("Tag found - writing - " + str(tag)) 4195b9c547cSRui Paulo global p2p_sel_data 4205b9c547cSRui Paulo tag.ndef.message = str(p2p_sel_data) 4215b9c547cSRui Paulo success_report("Tag write succeeded") 422*4bc52338SCy Schubert print("Done - remove tag") 4235b9c547cSRui Paulo global only_one 4245b9c547cSRui Paulo if only_one: 4255b9c547cSRui Paulo global continue_loop 4265b9c547cSRui Paulo continue_loop = False 4275b9c547cSRui Paulo global p2p_sel_wait_remove 4285b9c547cSRui Paulo return p2p_sel_wait_remove 4295b9c547cSRui Paulo 4305b9c547cSRui Paulodef wps_write_p2p_handover_sel(clf, wait_remove=True): 431*4bc52338SCy Schubert print("Write P2P handover select") 4325b9c547cSRui Paulo data = wpas_get_handover_sel(tag=True) 4335b9c547cSRui Paulo if (data == None): 4345b9c547cSRui Paulo summary("Could not get P2P handover select from wpa_supplicant") 4355b9c547cSRui Paulo return 4365b9c547cSRui Paulo 4375b9c547cSRui Paulo global p2p_sel_wait_remove 4385b9c547cSRui Paulo p2p_sel_wait_remove = wait_remove 4395b9c547cSRui Paulo global p2p_sel_data 4405b9c547cSRui Paulo p2p_sel_data = nfc.ndef.HandoverSelectMessage(version="1.2") 4415b9c547cSRui Paulo message = nfc.ndef.Message(data); 4425b9c547cSRui Paulo p2p_sel_data.add_carrier(message[0], "active", message[1:]) 443*4bc52338SCy Schubert print("Handover select:") 4445b9c547cSRui Paulo try: 445*4bc52338SCy Schubert print(p2p_sel_data.pretty()) 446*4bc52338SCy Schubert except Exception as e: 447*4bc52338SCy Schubert print(e) 448*4bc52338SCy Schubert print(str(p2p_sel_data).encode("hex")) 4495b9c547cSRui Paulo 450*4bc52338SCy Schubert print("Touch an NFC tag") 4515b9c547cSRui Paulo clf.connect(rdwr={'on-connect': rdwr_connected_p2p_write}) 4525b9c547cSRui Paulo 4535b9c547cSRui Paulo 4545b9c547cSRui Paulodef rdwr_connected(tag): 4555b9c547cSRui Paulo global only_one, no_wait 4565b9c547cSRui Paulo summary("Tag connected: " + str(tag)) 4575b9c547cSRui Paulo 4585b9c547cSRui Paulo if tag.ndef: 459*4bc52338SCy Schubert print("NDEF tag: " + tag.type) 4605b9c547cSRui Paulo try: 461*4bc52338SCy Schubert print(tag.ndef.message.pretty()) 462*4bc52338SCy Schubert except Exception as e: 463*4bc52338SCy Schubert print(e) 4645b9c547cSRui Paulo success = p2p_tag_read(tag) 4655b9c547cSRui Paulo if only_one and success: 4665b9c547cSRui Paulo global continue_loop 4675b9c547cSRui Paulo continue_loop = False 4685b9c547cSRui Paulo else: 4695b9c547cSRui Paulo summary("Not an NDEF tag - remove tag") 4705b9c547cSRui Paulo return True 4715b9c547cSRui Paulo 4725b9c547cSRui Paulo return not no_wait 4735b9c547cSRui Paulo 4745b9c547cSRui Paulo 4755b9c547cSRui Paulodef llcp_worker(llc): 4765b9c547cSRui Paulo global init_on_touch 4775b9c547cSRui Paulo if init_on_touch: 478*4bc52338SCy Schubert print("Starting handover client") 4795b9c547cSRui Paulo p2p_handover_client(llc) 4805b9c547cSRui Paulo return 4815b9c547cSRui Paulo 4825b9c547cSRui Paulo global no_input 4835b9c547cSRui Paulo if no_input: 484*4bc52338SCy Schubert print("Wait for handover to complete") 4855b9c547cSRui Paulo else: 486*4bc52338SCy Schubert print("Wait for handover to complete - press 'i' to initiate ('w' for WPS only, 'p' for P2P only)") 4875b9c547cSRui Paulo global srv 4885b9c547cSRui Paulo global wait_connection 4895b9c547cSRui Paulo while not wait_connection and srv.sent_carrier is None: 4905b9c547cSRui Paulo if srv.ho_server_processing: 4915b9c547cSRui Paulo time.sleep(0.025) 4925b9c547cSRui Paulo elif no_input: 4935b9c547cSRui Paulo time.sleep(0.5) 4945b9c547cSRui Paulo else: 4955b9c547cSRui Paulo global include_wps_req, include_p2p_req 4965b9c547cSRui Paulo res = getch() 4975b9c547cSRui Paulo if res == 'i': 4985b9c547cSRui Paulo include_wps_req = True 4995b9c547cSRui Paulo include_p2p_req = True 5005b9c547cSRui Paulo elif res == 'p': 5015b9c547cSRui Paulo include_wps_req = False 5025b9c547cSRui Paulo include_p2p_req = True 5035b9c547cSRui Paulo elif res == 'w': 5045b9c547cSRui Paulo include_wps_req = True 5055b9c547cSRui Paulo include_p2p_req = False 5065b9c547cSRui Paulo else: 5075b9c547cSRui Paulo continue 5085b9c547cSRui Paulo clear_raw_mode() 509*4bc52338SCy Schubert print("Starting handover client") 5105b9c547cSRui Paulo p2p_handover_client(llc) 5115b9c547cSRui Paulo return 5125b9c547cSRui Paulo 5135b9c547cSRui Paulo clear_raw_mode() 514*4bc52338SCy Schubert print("Exiting llcp_worker thread") 5155b9c547cSRui Paulo 5165b9c547cSRui Paulodef llcp_startup(clf, llc): 517*4bc52338SCy Schubert print("Start LLCP server") 5185b9c547cSRui Paulo global srv 5195b9c547cSRui Paulo srv = HandoverServer(llc) 5205b9c547cSRui Paulo return llc 5215b9c547cSRui Paulo 5225b9c547cSRui Paulodef llcp_connected(llc): 523*4bc52338SCy Schubert print("P2P LLCP connected") 5245b9c547cSRui Paulo global wait_connection 5255b9c547cSRui Paulo wait_connection = False 5265b9c547cSRui Paulo global init_on_touch 5275b9c547cSRui Paulo if not init_on_touch: 5285b9c547cSRui Paulo global srv 5295b9c547cSRui Paulo srv.start() 5305b9c547cSRui Paulo if init_on_touch or not no_input: 5315b9c547cSRui Paulo threading.Thread(target=llcp_worker, args=(llc,)).start() 5325b9c547cSRui Paulo return True 5335b9c547cSRui Paulo 5345b9c547cSRui Paulodef terminate_loop(): 5355b9c547cSRui Paulo global terminate_now 5365b9c547cSRui Paulo return terminate_now 5375b9c547cSRui Paulo 5385b9c547cSRui Paulodef main(): 5395b9c547cSRui Paulo clf = nfc.ContactlessFrontend() 5405b9c547cSRui Paulo 5415b9c547cSRui Paulo parser = argparse.ArgumentParser(description='nfcpy to wpa_supplicant integration for P2P and WPS NFC operations') 5425b9c547cSRui Paulo parser.add_argument('-d', const=logging.DEBUG, default=logging.INFO, 5435b9c547cSRui Paulo action='store_const', dest='loglevel', 5445b9c547cSRui Paulo help='verbose debug output') 5455b9c547cSRui Paulo parser.add_argument('-q', const=logging.WARNING, action='store_const', 5465b9c547cSRui Paulo dest='loglevel', help='be quiet') 5475b9c547cSRui Paulo parser.add_argument('--only-one', '-1', action='store_true', 5485b9c547cSRui Paulo help='run only one operation and exit') 5495b9c547cSRui Paulo parser.add_argument('--init-on-touch', '-I', action='store_true', 5505b9c547cSRui Paulo help='initiate handover on touch') 5515b9c547cSRui Paulo parser.add_argument('--no-wait', action='store_true', 5525b9c547cSRui Paulo help='do not wait for tag to be removed before exiting') 5535b9c547cSRui Paulo parser.add_argument('--ifname', '-i', 5545b9c547cSRui Paulo help='network interface name') 5555b9c547cSRui Paulo parser.add_argument('--no-wps-req', '-N', action='store_true', 5565b9c547cSRui Paulo help='do not include WPS carrier record in request') 5575b9c547cSRui Paulo parser.add_argument('--no-input', '-a', action='store_true', 5585b9c547cSRui Paulo help='do not use stdout input to initiate handover') 5595b9c547cSRui Paulo parser.add_argument('--tag-read-only', '-t', action='store_true', 5605b9c547cSRui Paulo help='tag read only (do not allow connection handover)') 5615b9c547cSRui Paulo parser.add_argument('--handover-only', action='store_true', 5625b9c547cSRui Paulo help='connection handover only (do not allow tag read)') 5635b9c547cSRui Paulo parser.add_argument('--freq', '-f', 5645b9c547cSRui Paulo help='forced frequency of operating channel in MHz') 5655b9c547cSRui Paulo parser.add_argument('--summary', 5665b9c547cSRui Paulo help='summary file for writing status updates') 5675b9c547cSRui Paulo parser.add_argument('--success', 5685b9c547cSRui Paulo help='success file for writing success update') 5695b9c547cSRui Paulo parser.add_argument('command', choices=['write-p2p-sel'], 5705b9c547cSRui Paulo nargs='?') 5715b9c547cSRui Paulo args = parser.parse_args() 5725b9c547cSRui Paulo 5735b9c547cSRui Paulo global only_one 5745b9c547cSRui Paulo only_one = args.only_one 5755b9c547cSRui Paulo 5765b9c547cSRui Paulo global no_wait 5775b9c547cSRui Paulo no_wait = args.no_wait 5785b9c547cSRui Paulo 5795b9c547cSRui Paulo global force_freq 5805b9c547cSRui Paulo force_freq = args.freq 5815b9c547cSRui Paulo 5825b9c547cSRui Paulo logging.basicConfig(level=args.loglevel) 5835b9c547cSRui Paulo 5845b9c547cSRui Paulo global init_on_touch 5855b9c547cSRui Paulo init_on_touch = args.init_on_touch 5865b9c547cSRui Paulo 5875b9c547cSRui Paulo if args.ifname: 5885b9c547cSRui Paulo global ifname 5895b9c547cSRui Paulo ifname = args.ifname 590*4bc52338SCy Schubert print("Selected ifname " + ifname) 5915b9c547cSRui Paulo 5925b9c547cSRui Paulo if args.no_wps_req: 5935b9c547cSRui Paulo global include_wps_req 5945b9c547cSRui Paulo include_wps_req = False 5955b9c547cSRui Paulo 5965b9c547cSRui Paulo if args.summary: 5975b9c547cSRui Paulo global summary_file 5985b9c547cSRui Paulo summary_file = args.summary 5995b9c547cSRui Paulo 6005b9c547cSRui Paulo if args.success: 6015b9c547cSRui Paulo global success_file 6025b9c547cSRui Paulo success_file = args.success 6035b9c547cSRui Paulo 6045b9c547cSRui Paulo if args.no_input: 6055b9c547cSRui Paulo global no_input 6065b9c547cSRui Paulo no_input = True 6075b9c547cSRui Paulo 6085b9c547cSRui Paulo clf = nfc.ContactlessFrontend() 6095b9c547cSRui Paulo global wait_connection 6105b9c547cSRui Paulo 6115b9c547cSRui Paulo try: 6125b9c547cSRui Paulo if not clf.open("usb"): 613*4bc52338SCy Schubert print("Could not open connection with an NFC device") 6145b9c547cSRui Paulo raise SystemExit 6155b9c547cSRui Paulo 6165b9c547cSRui Paulo if args.command == "write-p2p-sel": 6175b9c547cSRui Paulo wps_write_p2p_handover_sel(clf, wait_remove=not args.no_wait) 6185b9c547cSRui Paulo raise SystemExit 6195b9c547cSRui Paulo 6205b9c547cSRui Paulo global continue_loop 6215b9c547cSRui Paulo while continue_loop: 622*4bc52338SCy Schubert print("Waiting for a tag or peer to be touched") 6235b9c547cSRui Paulo wait_connection = True 6245b9c547cSRui Paulo try: 6255b9c547cSRui Paulo if args.tag_read_only: 6265b9c547cSRui Paulo if not clf.connect(rdwr={'on-connect': rdwr_connected}): 6275b9c547cSRui Paulo break 6285b9c547cSRui Paulo elif args.handover_only: 6295b9c547cSRui Paulo if not clf.connect(llcp={'on-startup': llcp_startup, 6305b9c547cSRui Paulo 'on-connect': llcp_connected}, 6315b9c547cSRui Paulo terminate=terminate_loop): 6325b9c547cSRui Paulo break 6335b9c547cSRui Paulo else: 6345b9c547cSRui Paulo if not clf.connect(rdwr={'on-connect': rdwr_connected}, 6355b9c547cSRui Paulo llcp={'on-startup': llcp_startup, 6365b9c547cSRui Paulo 'on-connect': llcp_connected}, 6375b9c547cSRui Paulo terminate=terminate_loop): 6385b9c547cSRui Paulo break 639*4bc52338SCy Schubert except Exception as e: 640*4bc52338SCy Schubert print("clf.connect failed") 6415b9c547cSRui Paulo 6425b9c547cSRui Paulo global srv 6435b9c547cSRui Paulo if only_one and srv and srv.success: 6445b9c547cSRui Paulo raise SystemExit 6455b9c547cSRui Paulo 6465b9c547cSRui Paulo except KeyboardInterrupt: 6475b9c547cSRui Paulo raise SystemExit 6485b9c547cSRui Paulo finally: 6495b9c547cSRui Paulo clf.close() 6505b9c547cSRui Paulo 6515b9c547cSRui Paulo raise SystemExit 6525b9c547cSRui Paulo 6535b9c547cSRui Pauloif __name__ == '__main__': 6545b9c547cSRui Paulo main() 655