1252190Srpaulo#!/usr/bin/python
2252190Srpaulo# Tests p2p_connect
3252190Srpaulo# Will try to connect to another peer
4252190Srpaulo# and form a group
5252190Srpaulo######### MAY NEED TO RUN AS SUDO #############
6252190Srpaulo
7252190Srpauloimport dbus
8252190Srpauloimport sys, os
9252190Srpauloimport time
10252190Srpauloimport gobject
11252190Srpauloimport getopt
12252190Srpaulofrom dbus.mainloop.glib import DBusGMainLoop
13252190Srpaulo
14252190Srpaulo
15252190Srpaulodef usage():
16252190Srpaulo	print "Usage:"
17252190Srpaulo	print "  %s -i <interface_name> -m <wps_method> \ " \
18252190Srpaulo		% sys.argv[0]
19252190Srpaulo	print "		-a <addr> [-p <pin>] [-g <go_intent>] \ "
20252190Srpaulo	print "  		[-w <wpas_dbus_interface>]"
21252190Srpaulo	print "Options:"
22252190Srpaulo	print "  -i = interface name"
23252190Srpaulo	print "  -m = wps method"
24252190Srpaulo	print "  -a = peer address"
25252190Srpaulo	print "  -p = pin number (8 digits)"
26252190Srpaulo	print "  -g = group owner intent"
27252190Srpaulo	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
28252190Srpaulo	print "Example:"
29252190Srpaulo	print "  %s -i wlan0 -a 0015008352c0 -m display -p 12345670" % sys.argv[0]
30252190Srpaulo
31252190Srpaulo
32252190Srpaulo# Required Signals
33252190Srpaulodef GONegotiationSuccess(status):
34252190Srpaulo	print "Go Negotiation Success"
35252190Srpaulo
36252190Srpaulodef GONegotiationFailure(status):
37252190Srpaulo	print 'Go Negotiation Failed. Status:'
38252190Srpaulo	print format(status)
39252190Srpaulo	os._exit(0)
40252190Srpaulo
41252190Srpaulodef GroupStarted(properties):
42252190Srpaulo	if properties.has_key("group_object"):
43252190Srpaulo		print 'Group Formation Complete %s' \
44252190Srpaulo			% properties["group_object"]
45252190Srpaulo	os._exit(0)
46252190Srpaulo
47252190Srpaulodef WpsFailure(status, etc):
48252190Srpaulo	print "WPS Authentication Failure".format(status)
49252190Srpaulo	print etc
50252190Srpaulo	os._exit(0)
51252190Srpaulo
52252190Srpauloclass P2P_Connect():
53252190Srpaulo	# Needed Variables
54252190Srpaulo	global bus
55252190Srpaulo	global wpas_object
56252190Srpaulo	global interface_object
57252190Srpaulo	global p2p_interface
58252190Srpaulo	global ifname
59252190Srpaulo	global wpas
60252190Srpaulo	global wpas_dbus_interface
61252190Srpaulo	global timeout
62252190Srpaulo	global path
63252190Srpaulo	global wps_method
64252190Srpaulo	global go_intent
65252190Srpaulo	global addr
66252190Srpaulo	global pin
67252190Srpaulo
68252190Srpaulo	# Dbus Paths
69252190Srpaulo	global wpas_dbus_opath
70252190Srpaulo	global wpas_dbus_interfaces_opath
71252190Srpaulo	global wpas_dbus_interfaces_interface
72252190Srpaulo	global wpas_dbus_interfaces_p2pdevice
73252190Srpaulo
74252190Srpaulo	# Dictionary of Arguements
75252190Srpaulo	global p2p_connect_arguements
76252190Srpaulo
77252190Srpaulo	# Constructor
78252190Srpaulo	def __init__(self,ifname,wpas_dbus_interface,addr,
79252190Srpaulo					pin,wps_method,go_intent):
80252190Srpaulo		# Initializes variables and threads
81252190Srpaulo		self.ifname = ifname
82252190Srpaulo		self.wpas_dbus_interface = wpas_dbus_interface
83252190Srpaulo		self.wps_method = wps_method
84252190Srpaulo		self.go_intent = go_intent
85252190Srpaulo		self.addr = addr
86252190Srpaulo		self.pin = pin
87252190Srpaulo
88252190Srpaulo		# Generating interface/object paths
89252190Srpaulo		self.wpas_dbus_opath = \
90252190Srpaulo			"/" + self.wpas_dbus_interface.replace(".","/")
91252190Srpaulo		self.wpas_wpas_dbus_interfaces_opath = \
92252190Srpaulo			self.wpas_dbus_opath + "/Interfaces"
93252190Srpaulo		self.wpas_dbus_interfaces_interface = \
94252190Srpaulo			self.wpas_dbus_interface + ".Interface"
95252190Srpaulo		self.wpas_dbus_interfaces_p2pdevice = \
96252190Srpaulo			self.wpas_dbus_interfaces_interface + ".P2PDevice"
97252190Srpaulo
98252190Srpaulo		# Getting interfaces and objects
99252190Srpaulo		DBusGMainLoop(set_as_default=True)
100252190Srpaulo		self.bus = dbus.SystemBus()
101252190Srpaulo		self.wpas_object = self.bus.get_object(
102252190Srpaulo				self.wpas_dbus_interface,
103252190Srpaulo				self.wpas_dbus_opath)
104252190Srpaulo		self.wpas = dbus.Interface(
105252190Srpaulo				self.wpas_object, self.wpas_dbus_interface)
106252190Srpaulo
107252190Srpaulo		# See if wpa_supplicant already knows about this interface
108252190Srpaulo		self.path = None
109252190Srpaulo		try:
110252190Srpaulo			self.path = self.wpas.GetInterface(ifname)
111252190Srpaulo		except:
112252190Srpaulo			if not str(exc).startswith(
113252190Srpaulo				self.wpas_dbus_interface + \
114252190Srpaulo				".InterfaceUnknown:"):
115252190Srpaulo				raise exc
116252190Srpaulo			try:
117252190Srpaulo				path = self.wpas.CreateInterface(
118252190Srpaulo					{'Ifname': ifname, 'Driver': 'test'})
119252190Srpaulo				time.sleep(1)
120252190Srpaulo
121252190Srpaulo			except dbus.DBusException, exc:
122252190Srpaulo				if not str(exc).startswith(
123252190Srpaulo					self.wpas_dbus_interface + \
124252190Srpaulo					".InterfaceExists:"):
125252190Srpaulo					raise exc
126252190Srpaulo
127252190Srpaulo		# Get Interface and objects
128252190Srpaulo		self.interface_object = self.bus.get_object(
129252190Srpaulo				self.wpas_dbus_interface,self.path)
130252190Srpaulo		self.p2p_interface = dbus.Interface(
131252190Srpaulo				self.interface_object,
132252190Srpaulo				self.wpas_dbus_interfaces_p2pdevice)
133252190Srpaulo
134252190Srpaulo		# Add signals
135252190Srpaulo		self.bus.add_signal_receiver(GONegotiationSuccess,
136252190Srpaulo			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
137252190Srpaulo			signal_name="GONegotiationSuccess")
138252190Srpaulo		self.bus.add_signal_receiver(GONegotiationFailure,
139252190Srpaulo			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
140252190Srpaulo			signal_name="GONegotiationFailure")
141252190Srpaulo		self.bus.add_signal_receiver(GroupStarted,
142252190Srpaulo			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
143252190Srpaulo			signal_name="GroupStarted")
144252190Srpaulo		self.bus.add_signal_receiver(WpsFailure,
145252190Srpaulo			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
146252190Srpaulo			signal_name="WpsFailed")
147252190Srpaulo
148252190Srpaulo
149252190Srpaulo	#Constructing all the arguements needed to connect
150252190Srpaulo	def constructArguements(self):
151252190Srpaulo		# Adding required arguements
152252190Srpaulo		self.p2p_connect_arguements = {'wps_method':self.wps_method,
153252190Srpaulo			'peer':dbus.ObjectPath(self.path+'/Peers/'+self.addr)}
154252190Srpaulo
155252190Srpaulo		# Display requires a pin, and a go intent of 15
156252190Srpaulo		if (self.wps_method == 'display'):
157252190Srpaulo			if (self.pin != None):
158252190Srpaulo				self.p2p_connect_arguements.update({'pin':self.pin})
159252190Srpaulo			else:
160252190Srpaulo				print "Error:\n  Pin required for wps_method=display"
161252190Srpaulo				usage()
162252190Srpaulo				quit()
163252190Srpaulo
164252190Srpaulo			if (self.go_intent != None and int(self.go_intent) != 15):
165252190Srpaulo				print "go_intent overwritten to 15"
166252190Srpaulo
167252190Srpaulo			self.go_intent = '15'
168252190Srpaulo
169252190Srpaulo		# Keypad requires a pin, and a go intent of less than 15
170252190Srpaulo		elif (self.wps_method == 'keypad'):
171252190Srpaulo			if (self.pin != None):
172252190Srpaulo				self.p2p_connect_arguements.update({'pin':self.pin})
173252190Srpaulo			else:
174252190Srpaulo				print "Error:\n  Pin required for wps_method=keypad"
175252190Srpaulo				usage()
176252190Srpaulo				quit()
177252190Srpaulo
178252190Srpaulo			if (self.go_intent != None and int(self.go_intent) == 15):
179252190Srpaulo				error = "Error :\n Group Owner intent cannot be" + \
180252190Srpaulo					" 15 for wps_method=keypad"
181252190Srpaulo				print error
182252190Srpaulo				usage()
183252190Srpaulo				quit()
184252190Srpaulo
185252190Srpaulo		# Doesn't require pin
186252190Srpaulo		# for ./wpa_cli, p2p_connect [mac] [pin#], wps_method=keypad
187252190Srpaulo		elif (self.wps_method == 'pin'):
188252190Srpaulo			if (self.pin != None):
189252190Srpaulo				print "pin ignored"
190252190Srpaulo
191252190Srpaulo		# No pin is required for pbc so it is ignored
192252190Srpaulo		elif (self.wps_method == 'pbc'):
193252190Srpaulo			if (self.pin != None):
194252190Srpaulo				print "pin ignored"
195252190Srpaulo
196252190Srpaulo		else:
197252190Srpaulo			print "Error:\n  wps_method not supported or does not exist"
198252190Srpaulo			usage()
199252190Srpaulo			quit()
200252190Srpaulo
201252190Srpaulo		# Go_intent is optional for all arguements
202252190Srpaulo		if (self.go_intent != None):
203252190Srpaulo			self.p2p_connect_arguements.update(
204252190Srpaulo				{'go_intent':dbus.Int32(self.go_intent)})
205252190Srpaulo
206252190Srpaulo	# Running p2p_connect
207252190Srpaulo	def run(self):
208252190Srpaulo		try:
209252190Srpaulo			result_pin = self.p2p_interface.Connect(
210252190Srpaulo				self.p2p_connect_arguements)
211252190Srpaulo
212252190Srpaulo		except dbus.DBusException, exc:
213252190Srpaulo				raise exc
214252190Srpaulo
215252190Srpaulo		if (self.wps_method == 'pin' and \
216252190Srpaulo		not self.p2p_connect_arguements.has_key('pin') ):
217252190Srpaulo			print "Connect return with pin value of %d " % int(result_pin)
218252190Srpaulo		gobject.MainLoop().run()
219252190Srpaulo
220252190Srpauloif __name__ == "__main__":
221252190Srpaulo
222252190Srpaulo	# Required
223252190Srpaulo	interface_name = None
224252190Srpaulo	wps_method = None
225252190Srpaulo	addr = None
226252190Srpaulo
227252190Srpaulo	# Conditionally optional
228252190Srpaulo	pin = None
229252190Srpaulo
230252190Srpaulo	# Optional
231252190Srpaulo	wpas_dbus_interface = 'fi.w1.wpa_supplicant1'
232252190Srpaulo	go_intent = None
233252190Srpaulo
234252190Srpaulo	# Using getopts to handle options
235252190Srpaulo	try:
236252190Srpaulo		options, args = getopt.getopt(sys.argv[1:],"hi:m:a:p:g:w:")
237252190Srpaulo
238252190Srpaulo	except getopt.GetoptError:
239252190Srpaulo		usage()
240252190Srpaulo		quit()
241252190Srpaulo
242252190Srpaulo	# If theres a switch, override default option
243252190Srpaulo	for key, value in options:
244252190Srpaulo		# Help
245252190Srpaulo		if (key == "-h"):
246252190Srpaulo			usage()
247252190Srpaulo			quit()
248252190Srpaulo		# Interface Name
249252190Srpaulo		elif (key == "-i"):
250252190Srpaulo			interface_name = value
251252190Srpaulo		# WPS Method
252252190Srpaulo		elif (key == "-m"):
253252190Srpaulo			wps_method = value
254252190Srpaulo		# Address
255252190Srpaulo		elif (key == "-a"):
256252190Srpaulo			addr = value
257252190Srpaulo		# Pin
258252190Srpaulo		elif (key == "-p"):
259252190Srpaulo			pin = value
260252190Srpaulo		# Group Owner Intent
261252190Srpaulo		elif (key == "-g"):
262252190Srpaulo			go_intent = value
263252190Srpaulo		# Dbus interface
264252190Srpaulo		elif (key == "-w"):
265252190Srpaulo			wpas_dbus_interface = value
266252190Srpaulo		else:
267252190Srpaulo			assert False, "unhandled option"
268252190Srpaulo
269252190Srpaulo	# Required Arguements check
270252190Srpaulo	if (interface_name == None or wps_method == None or addr == None):
271252190Srpaulo		print "Error:\n  Required arguements not specified"
272252190Srpaulo		usage()
273252190Srpaulo		quit()
274252190Srpaulo
275252190Srpaulo	# Group Owner Intent Check
276252190Srpaulo	if (go_intent != None and (int(go_intent) > 15 or int(go_intent) < 0) ):
277252190Srpaulo		print "Error:\n  Group Owner Intent must be between 0 and 15 inclusive"
278252190Srpaulo		usage()
279252190Srpaulo		quit()
280252190Srpaulo
281252190Srpaulo	# Pin Check
282252190Srpaulo	if (pin != None and len(pin) != 8):
283252190Srpaulo		print "Error:\n  Pin is not 8 digits"
284252190Srpaulo		usage()
285252190Srpaulo		quit()
286252190Srpaulo
287252190Srpaulo	try:
288252190Srpaulo		p2p_connect_test = P2P_Connect(interface_name,wpas_dbus_interface,
289252190Srpaulo			addr,pin,wps_method,go_intent)
290252190Srpaulo
291252190Srpaulo	except:
292252190Srpaulo		print "Error:\n  Invalid Arguements"
293252190Srpaulo		usage()
294252190Srpaulo		quit()
295252190Srpaulo
296252190Srpaulo	p2p_connect_test.constructArguements()
297252190Srpaulo	p2p_connect_test.run()
298252190Srpaulo
299252190Srpaulo	os._exit(0)
300