| #!/usr/bin/python |
| |
| from __future__ import absolute_import, print_function, unicode_literals |
| |
| from gi.repository import GObject |
| |
| import sys |
| import dbus |
| import dbus.service |
| import dbus.mainloop.glib |
| from optparse import OptionParser |
| import bluezutils |
| |
| BUS_NAME = 'org.bluez' |
| AGENT_INTERFACE = 'org.bluez.Agent1' |
| AGENT_PATH = "/test/agent" |
| |
| bus = None |
| device_obj = None |
| dev_path = None |
| |
| def ask(prompt): |
| try: |
| return raw_input(prompt) |
| except: |
| return input(prompt) |
| |
| def set_trusted(path): |
| props = dbus.Interface(bus.get_object("org.bluez", path), |
| "org.freedesktop.DBus.Properties") |
| props.Set("org.bluez.Device1", "Trusted", True) |
| |
| def dev_connect(path): |
| dev = dbus.Interface(bus.get_object("org.bluez", path), |
| "org.bluez.Device1") |
| dev.Connect() |
| |
| class Rejected(dbus.DBusException): |
| _dbus_error_name = "org.bluez.Error.Rejected" |
| |
| class Agent(dbus.service.Object): |
| exit_on_release = True |
| |
| def set_exit_on_release(self, exit_on_release): |
| self.exit_on_release = exit_on_release |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="", out_signature="") |
| def Release(self): |
| print("Release") |
| if self.exit_on_release: |
| mainloop.quit() |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="os", out_signature="") |
| def AuthorizeService(self, device, uuid): |
| print("AuthorizeService (%s, %s)" % (device, uuid)) |
| authorize = ask("Authorize connection (yes/no): ") |
| if (authorize == "yes"): |
| return |
| raise Rejected("Connection rejected by user") |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="o", out_signature="s") |
| def RequestPinCode(self, device): |
| print("RequestPinCode (%s)" % (device)) |
| set_trusted(device) |
| return ask("Enter PIN Code: ") |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="o", out_signature="u") |
| def RequestPasskey(self, device): |
| print("RequestPasskey (%s)" % (device)) |
| set_trusted(device) |
| passkey = ask("Enter passkey: ") |
| return dbus.UInt32(passkey) |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="ouq", out_signature="") |
| def DisplayPasskey(self, device, passkey, entered): |
| print("DisplayPasskey (%s, %06u entered %u)" % |
| (device, passkey, entered)) |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="os", out_signature="") |
| def DisplayPinCode(self, device, pincode): |
| print("DisplayPinCode (%s, %s)" % (device, pincode)) |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="ou", out_signature="") |
| def RequestConfirmation(self, device, passkey): |
| print("RequestConfirmation (%s, %06d)" % (device, passkey)) |
| confirm = ask("Confirm passkey (yes/no): ") |
| if (confirm == "yes"): |
| set_trusted(device) |
| return |
| raise Rejected("Passkey doesn't match") |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="o", out_signature="") |
| def RequestAuthorization(self, device): |
| print("RequestAuthorization (%s)" % (device)) |
| auth = ask("Authorize? (yes/no): ") |
| if (auth == "yes"): |
| return |
| raise Rejected("Pairing rejected") |
| |
| @dbus.service.method(AGENT_INTERFACE, |
| in_signature="", out_signature="") |
| def Cancel(self): |
| print("Cancel") |
| |
| def pair_reply(): |
| print("Device paired") |
| set_trusted(dev_path) |
| dev_connect(dev_path) |
| mainloop.quit() |
| |
| def pair_error(error): |
| err_name = error.get_dbus_name() |
| if err_name == "org.freedesktop.DBus.Error.NoReply" and device_obj: |
| print("Timed out. Cancelling pairing") |
| device_obj.CancelPairing() |
| else: |
| print("Creating device failed: %s" % (error)) |
| |
| |
| mainloop.quit() |
| |
| if __name__ == '__main__': |
| dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) |
| |
| bus = dbus.SystemBus() |
| |
| capability = "KeyboardDisplay" |
| |
| parser = OptionParser() |
| parser.add_option("-i", "--adapter", action="store", |
| type="string", |
| dest="adapter_pattern", |
| default=None) |
| parser.add_option("-c", "--capability", action="store", |
| type="string", dest="capability") |
| parser.add_option("-t", "--timeout", action="store", |
| type="int", dest="timeout", |
| default=60000) |
| (options, args) = parser.parse_args() |
| if options.capability: |
| capability = options.capability |
| |
| path = "/test/agent" |
| agent = Agent(bus, path) |
| |
| mainloop = GObject.MainLoop() |
| |
| obj = bus.get_object(BUS_NAME, "/org/bluez"); |
| manager = dbus.Interface(obj, "org.bluez.AgentManager1") |
| manager.RegisterAgent(path, capability) |
| |
| print("Agent registered") |
| |
| # Fix-up old style invocation (BlueZ 4) |
| if len(args) > 0 and args[0].startswith("hci"): |
| options.adapter_pattern = args[0] |
| del args[:1] |
| |
| if len(args) > 0: |
| device = bluezutils.find_device(args[0], |
| options.adapter_pattern) |
| dev_path = device.object_path |
| agent.set_exit_on_release(False) |
| device.Pair(reply_handler=pair_reply, error_handler=pair_error) |
| device_obj = device |
| else: |
| manager.RequestDefaultAgent(path) |
| |
| mainloop.run() |
| |
| #adapter.UnregisterAgent(path) |
| #print("Agent unregistered") |