161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#!/usr/bin/python
261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt# Tests p2p_find
361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt# Will list all devices found/lost within a time frame (timeout)
461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt# Then Program will exit
561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt######### MAY NEED TO RUN AS SUDO #############
661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport dbus
861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport sys, os
961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport time
1061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport gobject
1161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport threading
1261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtimport getopt
1361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtfrom dbus.mainloop.glib import DBusGMainLoop
1461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
1561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdef usage():
1661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Usage:"
1761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  %s -i <interface_name> [-t <timeout>] \ " \
1861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		% sys.argv[0]
1961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  		[-w <wpas_dbus_interface>]"
2061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Options:"
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -i = interface name"
2261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -t = timeout = 0s (infinite)"
2361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  -w = wpas dbus interface = fi.w1.wpa_supplicant1"
2461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Example:"
2561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "  %s -i wlan0 -t 10" % sys.argv[0]
2661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt# Required Signals
2861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdef deviceFound(devicepath):
2961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Device found: %s" % (devicepath)
3061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtdef deviceLost(devicepath):
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	print "Device lost: %s" % (devicepath)
3361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtclass P2P_Find (threading.Thread):
3561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Needed Variables
3661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global bus
3761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_object
3861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global interface_object
3961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global p2p_interface
4061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global interface_name
4161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas
4261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interface
4361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global timeout
4461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global path
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Dbus Paths
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_opath
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interfaces_opath
4961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interfaces_interface
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	global wpas_dbus_interfaces_p2pdevice
5161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Constructor
5361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	def __init__(self,interface_name,wpas_dbus_interface,timeout):
5461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Initializes variables and threads
5561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.timeout = int(timeout)
5661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.interface_name = interface_name
5761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_interface = wpas_dbus_interface
5861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
5961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Initializes thread and daemon allows for ctrl-c kill
6061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		threading.Thread.__init__(self)
6161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.daemon = True
6261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
6361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Generating interface/object paths
6461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_opath = "/" + \
6561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface.replace(".","/")
6661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_wpas_dbus_interfaces_opath = self.wpas_dbus_opath + \
6761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				"/Interfaces"
6861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_interfaces_interface = \
6961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface + ".Interface"
7061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_dbus_interfaces_p2pdevice = \
7161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interfaces_interface \
7261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				+ ".P2PDevice"
7361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
7461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Getting interfaces and objects
7561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		DBusGMainLoop(set_as_default=True)
7661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.bus = dbus.SystemBus()
7761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas_object = self.bus.get_object(
7861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface,
7961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_opath)
8061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.wpas = dbus.Interface(self.wpas_object,
8161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface)
8261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
8361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Try to see if supplicant knows about interface
8461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# If not, throw an exception
8561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		try:
8661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			self.path = self.wpas.GetInterface(
8761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					self.interface_name)
8861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		except dbus.DBusException, exc:
8961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			error = 'Error:\n  Interface ' + self.interface_name \
9061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				+ ' was not found'
9161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			print error
9261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			usage()
9361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			os._exit(0)
9461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
9561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.interface_object = self.bus.get_object(
9661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interface, self.path)
9761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.p2p_interface = dbus.Interface(self.interface_object,
9861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				self.wpas_dbus_interfaces_p2pdevice)
9961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		#Adds listeners for find and lost
10161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.bus.add_signal_receiver(deviceFound,
10261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
10361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			signal_name="DeviceFound")
10461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.bus.add_signal_receiver(deviceLost,
10561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			dbus_interface=self.wpas_dbus_interfaces_p2pdevice,
10661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			signal_name="DeviceLost")
10761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
10961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Sets up p2p_find
11061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		P2PFindDict = dbus.Dictionary(
11161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				{'Timeout':int(self.timeout)})
11261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		self.p2p_interface.Find(P2PFindDict)
11361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
11461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Run p2p_find
11561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	def run(self):
11661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Allows other threads to keep working while MainLoop runs
11761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Required for timeout implementation
11861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gobject.MainLoop().get_context().iteration(True)
11961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gobject.threads_init()
12061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		gobject.MainLoop().run()
12161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtif __name__ == "__main__":
12361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Defaults for optional inputs
12561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	timeout = 0
12661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	wpas_dbus_interface = 'fi.w1.wpa_supplicant1'
12761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
12861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# interface_name is required
12961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	interface_name = None
13061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Using getopts to handle options
13261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	try:
13361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		options, args = getopt.getopt(sys.argv[1:],"hi:t:w:")
13461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	except getopt.GetoptError:
13661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
13761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		quit()
13861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
13961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# If theres a switch, override default option
14061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	for key, value in options:
14161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Help
14261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (key == "-h"):
14361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			usage()
14461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			quit()
14561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Interface Name
14661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-i"):
14761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			interface_name = value
14861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Timeout
14961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-t"):
15061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if ( int(value) >= 0):
15161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				timeout = value
15261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else:
15361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				print "Error:\n  Timeout cannot be negative"
15461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				usage()
15561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				quit()
15661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Dbus interface
15761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		elif (key == "-w"):
15861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpas_dbus_interface = value
15961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		else:
16061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			assert False, "unhandled option"
16161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
16261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Interface name is required and was not given
16361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (interface_name == None):
16461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		print "Error:\n  interface_name is required"
16561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
16661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		quit()
16761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
16861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Constructor
16961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	try:
17061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		p2p_find_test = P2P_Find(interface_name, wpas_dbus_interface, timeout)
17161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	except:
17361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		print "Error:\n  Invalid wpas_dbus_interface"
17461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		usage()
17561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		quit()
17661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
17761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	# Start P2P_Find
17861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p2p_find_test.start()
17961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	try:
18161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# If timeout is 0, then run forever
18261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (timeout == 0):
18361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			while(True):
18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				pass
18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		# Else sleep for (timeout)
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		else:
18761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			time.sleep(p2p_find_test.timeout)
18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	except:
19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		pass
19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	quit()
193