diff --git a/conf/blued.conf.example b/conf/blued.conf.example
index 48c8c3e57f34fbb82fedbbbe40ec210629dc7652..d023bc51ea7e2ef12af51509093d1473e0b2815f 100644
--- a/conf/blued.conf.example
+++ b/conf/blued.conf.example
@@ -31,9 +31,9 @@
 #
 # Name of the netgraph HCI node. Unless you have several bluetooth
 # chips, you should not have to change this.
-# Default: hci0ubt
+# Default: ubt0hci
 #
-#hci_node = "hci0ubt";
+#hci_node = "ubt0hci";
 
 #
 # User to drop to after initialisation is done.
diff --git a/daemon/src/blue_daemon.cpp b/daemon/src/blue_daemon.cpp
index 221b38e4325d226cb54d6494d07c5dc4c3ebe77f..3db1021feaf435ac3ac5b60c6723d746b26daa57 100644
--- a/daemon/src/blue_daemon.cpp
+++ b/daemon/src/blue_daemon.cpp
@@ -108,7 +108,7 @@ static pidfh *create_pid_file(const conf_options &opts)
 	return tmp;
 }
 
-blue_daemon::blue_daemon(nodeinfo btnode, const conf_options &opts,
+blue_daemon::blue_daemon(const conf_options &opts,
 		blue::util::shared_cap_chan chan, ev::loop_ref loop) :
 	loop(loop),
 	rpc_watcher(loop),
@@ -121,10 +121,13 @@ blue_daemon::blue_daemon(nodeinfo btnode, const conf_options &opts,
 {
 	connect_socket(opts);
 
-	hci_socket.bind(btnode.name);
-	hci_socket.connect(btnode.name);
+	hci_socket.bind(opts.hci_node);
+	hci_socket.connect(opts.hci_node);
 	hci_socket.register_socket_observer(this);
 
+	syslog(LOG_DEBUG, "Local HCI address: %s",
+	       get_local_address().str().c_str());
+
 	try
 	{
 		devices = db.load_devices(&hci_socket);
@@ -377,6 +380,11 @@ bool blue_daemon::known(blue::bdaddr addr) const
 	return devices.count(addr) > 0;
 }
 
+blue::bdaddr blue_daemon::get_local_address() const
+{
+	return hci_socket.get_address();
+}
+
 blue::rpc_op blue_daemon::pair_request(const blue::bdaddr &addr)
 {
 	blue::rpc_op ret;
diff --git a/daemon/src/blue_daemon.h b/daemon/src/blue_daemon.h
index 9cf62dc151b58f6a680a35a15843cf35e23fbd3c..53ed35042010f8c0d9d13d58455591a46dee45d7 100644
--- a/daemon/src/blue_daemon.h
+++ b/daemon/src/blue_daemon.h
@@ -30,7 +30,7 @@ class blue_daemon : public blue::hci_socket_observer,
 	public blue::device_observer, public rpc_observer
 {
 public:
-	blue_daemon(nodeinfo btnode, const conf_options &opts,
+	blue_daemon(const conf_options &opts,
 			blue::util::shared_cap_chan chan, ev::loop_ref loop);
 	virtual ~blue_daemon();
 
@@ -68,6 +68,13 @@ public:
 	 */
 	bool known(blue::bdaddr addr) const;
 
+	/*
+	 * Returns the local HCI socket address.
+	 *
+	 * throws std::runtime_error() on error.
+	 */
+	blue::bdaddr get_local_address() const;
+
 private:
 	/*
 	 * Callbacks from blue::btdevice, see lib/include/btdevice.h class
diff --git a/daemon/src/hid_daemon.cpp b/daemon/src/hid_daemon.cpp
index 99d278c398ad7f3ac664746e37302784c1ed2473..b4210ba0f12d164f4a8936e99f4b63d3d091a5c3 100644
--- a/daemon/src/hid_daemon.cpp
+++ b/daemon/src/hid_daemon.cpp
@@ -61,7 +61,7 @@ void hid_daemon::connect(blue::bdaddr addr)
 	try
 	{
 		std::optional<blue::hid::hid_descriptor> d =
-			blue::hid::get_descriptor(sdp_chan, addr);
+			blue::hid::get_descriptor(sdp_chan, hci->get_local_address(), addr);
 		if (!d)
 		{
 			syslog(LOG_DEBUG, "No HID descriptor could be queried for %s",
@@ -70,7 +70,8 @@ void hid_daemon::connect(blue::bdaddr addr)
 		}
 
 		unique_fd ctrl_fd =
-			cap_l2cap_connect(l2cap_chan, d->control_psm, *bdaddr);
+			cap_l2cap_connect(l2cap_chan, hci->get_local_address(),
+			                  d->control_psm, bdaddr);
 		if (ctrl_fd == -1)
 		{
 			syslog(LOG_ERR, "Failed to open control connection to %s: %s",
@@ -79,7 +80,8 @@ void hid_daemon::connect(blue::bdaddr addr)
 		}
 
 		unique_fd intr_fd =
-			cap_l2cap_connect(l2cap_chan, d->interrupt_psm, *bdaddr);
+			cap_l2cap_connect(l2cap_chan, hci->get_local_address(),
+			                  d->interrupt_psm, bdaddr);
 		if (intr_fd == -1)
 		{
 			syslog(LOG_ERR, "Failed to open interrupt connection to %s: %s",
@@ -87,9 +89,19 @@ void hid_daemon::connect(blue::bdaddr addr)
 			return;
 		}
 
-		devices.try_emplace(addr, kbd_chan, sdp_chan, this, cons, uinput,
-		                    addr, std::move(ctrl_fd), loop,
-		                    std::move(d.value()));
+		blue::hid::hid_device::hid_device_config config =
+		{
+			kbd_chan,
+			sdp_chan,
+			this,
+			cons,
+			uinput,
+			hci->get_local_address(),
+			addr,
+			std::move(ctrl_fd),
+			loop
+		};
+		devices.try_emplace(addr, std::move(config), std::move(d.value()));
 		devices.at(addr).intr_opened(std::move(intr_fd));
 	}
 	catch (const std::runtime_error &e)
@@ -122,8 +134,33 @@ void hid_daemon::ctrl_callback(unique_fd client_fd, blue::bdaddr remote)
 	try
 	{
 		if (hci->paired(remote))
-			devices.try_emplace(remote, kbd_chan, sdp_chan, this, cons,
-			                    uinput, remote, std::move(client_fd), loop);
+		{
+			std::optional<blue::hid::hid_descriptor> d =
+				blue::hid::get_descriptor(sdp_chan, hci->get_local_address(),
+				                          remote);
+			if (d)
+			{
+				blue::hid::hid_device::hid_device_config config =
+				{
+					kbd_chan,
+					sdp_chan,
+					this,
+					cons,
+					uinput,
+					hci->get_local_address(),
+					remote,
+					std::move(client_fd),
+					loop
+				};
+				devices.try_emplace(remote, std::move(config), std::move(d.value()));
+			}
+			else
+			{
+				syslog(LOG_DEBUG, "No HID descriptor could be queried for incoming %s",
+					   remote.str().c_str());
+				return;
+			}
+		}
 		else
 		{
 			syslog(LOG_NOTICE, "%s is not paired. Closing connection!",
diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp
index 09b42e98250174fe8d5a9b2d07b3f2356ee0fa24..1c88fdd662d807e683d9701ae64f54735e053515 100644
--- a/daemon/src/main.cpp
+++ b/daemon/src/main.cpp
@@ -37,21 +37,6 @@ private:
 	ev::loop_ref loop;
 };
 
-static nodeinfo get_node(const conf_options &opts)
-{
-	std::vector<nodeinfo> nodes;
-
-	ev::default_loop loop;
-	blue::hci_socket qs(loop);
-	qs.bind(opts.hci_node);
-	nodes = qs.find_hci_nodes();
-
-	if (nodes.empty())
-		throw std::runtime_error("Could not find any BT nodes.");
-
-	return nodes[0];
-}
-
 static uid_t get_uid(std::string user)
 {
 	passwd *p = getpwnam(user.c_str());
@@ -83,7 +68,7 @@ static conf_options parse_config(std::string path)
 		opts.socket_name =
 			obj.lookup("socket_name").string_value("rpc");
 		opts.db_path = obj.lookup("db_path").string_value("/var/db/blued.db");
-		opts.hci_node = obj.lookup("hci_node").string_value("hci0ubt");
+		opts.hci_node = obj.lookup("hci_node").string_value("ubt0hci");
 
 		try
 		{
@@ -208,7 +193,6 @@ int main(int argc, char* argv[])
 
 	try
 	{
-		nodeinfo n = get_node(opts);
 		ev::default_loop loop;
 		sig_handler int_handler(loop);
 		ev::sig s_int(loop);
@@ -223,7 +207,7 @@ int main(int argc, char* argv[])
 		s_term.set(SIGTERM);
 		s_term.start();
 
-		blue_daemon daemon(n, opts, channel, loop);
+		blue_daemon daemon(opts, channel, loop);
 
 		drop_privileges(opts);
 
diff --git a/lib/include/btdevice.h b/lib/include/btdevice.h
index 9781d58d0148185248f911dda723921c3d14d6ab..1403065463c475bd3c5be819975fa07c81d4cf37 100644
--- a/lib/include/btdevice.h
+++ b/lib/include/btdevice.h
@@ -72,8 +72,8 @@ protected:
  * Ex: Connect to a device with address addr
  *
  * 	blue::hci_socket s;
- * 	s.bind("hci0ubt");
- * 	hci_socket.connect("hci0ubt");
+ * 	s.bind("ubt0hci");
+ * 	hci_socket.connect("ubt0hci");
  * 	blue::btdevice device(addr, &s);
  * 	device.connect();
  *
diff --git a/lib/include/cap_l2cap.h b/lib/include/cap_l2cap.h
index 3b6b6a49ca8efa44badc4b7a8e59be2d594f6798..9c57c27bd3c09b556322b161e87af137092c20d0 100644
--- a/lib/include/cap_l2cap.h
+++ b/lib/include/cap_l2cap.h
@@ -27,7 +27,9 @@ namespace blue::l2cap
 	 *
 	 * returns -1 on error
 	 */
-	util::unique_fd cap_l2cap_listen(util::shared_cap_chan chan, uint16_t psm);
+	util::unique_fd cap_l2cap_listen(util::shared_cap_chan chan,
+	                                 const bdaddr_t *listen_addr,
+	                                 uint16_t psm);
 
 	/*
 	 * Returns an fd to an L2CAP socket connected to remote addr
@@ -37,8 +39,10 @@ namespace blue::l2cap
 	 *
 	 * returns -1 on error
 	 */
-	util::unique_fd cap_l2cap_connect(util::shared_cap_chan chan, uint16_t psm,
-		bdaddr_t addr);
+	util::unique_fd cap_l2cap_connect(util::shared_cap_chan chan,
+	                                  const bdaddr_t *local_addr,
+	                                  uint16_t psm,
+	                                  const bdaddr_t *addr);
 
 } // namespace blue::l2cap
 
diff --git a/lib/include/cap_sdp.h b/lib/include/cap_sdp.h
index 53a7fe59dbe6f3ebbfa3713d339df4fde5b13272..69191d5a5d01fafd8a65a6fc9c7408d5de12c459 100644
--- a/lib/include/cap_sdp.h
+++ b/lib/include/cap_sdp.h
@@ -28,7 +28,8 @@ namespace blue::sdp
 	};
 
 	/*
-	 * Opens a SDP session to remote device with address r.
+	 * Opens a SDP session to remote device with address r from local
+	 * address l.
 	 *
 	 * handle is an output parameter that gives an opaque handle for
 	 * passing to cap_sdp_search(). It should be freed by
@@ -39,8 +40,8 @@ namespace blue::sdp
 	 *
 	 * returns -1 on error, 0 on success
 	 */
-	int cap_sdp_open(util::shared_cap_chan chan, const bdaddr_t *r,
-		uint64_t &handle);
+	int cap_sdp_open(util::shared_cap_chan chan, const bdaddr_t *l,
+	                 const bdaddr_t *r, uint64_t &handle);
 
 	/*
 	 * Queries the device represented by handle acquired from
diff --git a/lib/include/hci_socket.h b/lib/include/hci_socket.h
index 2a670d86ee58a017cd7c66675e10dd9c1f41b2bb..3f0b1db23131753536e7cc2497e1164cc43fe710 100644
--- a/lib/include/hci_socket.h
+++ b/lib/include/hci_socket.h
@@ -200,8 +200,8 @@ protected:
  * 	blue::hci_socket s(loop);
  * 	observer o;
  *
- * 	s.bind("hci0ubt");
- * 	s.connect("hci0ubt");
+ * 	s.bind("ubt0hci");
+ * 	s.connect("ubt0hci");
  * 	s.register_socket_observer(&observer);
  * 	s.query_devices();
  *
@@ -271,6 +271,12 @@ public:
 	 * throws std::runtime_error() on error
 	 */
 	std::vector<nodeinfo> find_hci_nodes();
+	/*
+	 * Get the bdaddr of the HCI socket.
+	 *
+	 * throws std::runtime_error() on error.
+	 */
+	blue::bdaddr get_address() const;
 
 	/*
 	 * Send an HCI request out on the network.
diff --git a/lib/include/hid/bthid.h b/lib/include/hid/bthid.h
index dba85acdf5938c7566c56ab49cf7ebee92ee4e08..ea9e495b5c717aeda8f26bf4b289acdf17be801f 100644
--- a/lib/include/hid/bthid.h
+++ b/lib/include/hid/bthid.h
@@ -53,7 +53,8 @@ namespace blue::hid
 
 	/*
 	 * Request a Bluetooth HID descriptor from the remote device with
-	 * address addr.
+	 * address addr. The request is sent from local device with
+	 * address local_addr.
 	 *
 	 * sdp_chan is a channel to blue.sdp opened using
 	 * cap_service_open()
@@ -63,7 +64,7 @@ namespace blue::hid
 	 * If the device is not a HID device, the return value is empty.
 	 */
 	std::optional<hid_descriptor> get_descriptor(util::shared_cap_chan sdp_chan,
-			blue::bdaddr addr);
+			blue::bdaddr local_addr, blue::bdaddr addr);
 
 	// Mandatory device ID fields as per the Bluetooth DeviceID_SPEC V13.
 	constexpr uint16_t SpecificationID = 0x0200;
@@ -85,7 +86,8 @@ namespace blue::hid
 
 	/*
 	 * Request a Bluetooth device ID descriptor from the remote device
-	 * with address addr.
+	 * with address addr. The request is made from local HCI device
+	 * with address local_addr.
 	 *
 	 * sdp_chan is a channel to blue.sdp opened using
 	 * cap_service_open()
@@ -96,7 +98,7 @@ namespace blue::hid
 	 * empty.
 	 */
 	std::optional<device_id> get_devid(util::shared_cap_chan sdp_chan,
-			blue::bdaddr addr);
+			blue::bdaddr local_addr, blue::bdaddr addr);
 
 } // namespace blue::bthid
 
diff --git a/lib/include/hid/hid_device.h b/lib/include/hid/hid_device.h
index 9681f8d67ef8e44ce8682c020d579415d316ae94..3ab9524461f060905793846d65de69ba86aa49d7 100644
--- a/lib/include/hid/hid_device.h
+++ b/lib/include/hid/hid_device.h
@@ -59,34 +59,37 @@ public:
 	 * If the hid_device object is destroyed, the l2cap connection to
 	 * the HID device will be closed.
 	 *
-	 * Arguments:
-	 *  kbd_chan - service channel to blue.kbd
-	 *  sdp_chan - service channel to blue.sdp
-	 *  parent   - pointer to parent inheriting hid_watcher
-	 *  cons_fd  - fd pointing to /dev/consolectl
-	 *  uinput   - true if events should be passed to X via uinput
-	 *  addr     - bluetooth address of the HID device
-	 *  ctrl     - fd pointing to a l2cap control connection
-	 *  loop     - libev event loop for IO processing
-	 *
-	 *  optional:
-	 *       d    - HID descriptor for the device, it will be queried
-	 *              if it is not supplied
+	 * Config:
+	 *  kbd_chan   - service channel to blue.kbd
+	 *  sdp_chan   - service channel to blue.sdp
+	 *  parent     - pointer to parent inheriting hid_watcher
+	 *  cons_fd    - fd pointing to /dev/consolectl
+	 *  uinput     - true if events should be passed to X via uinput
+	 *  addr       - bluetooth address of the HID device
+	 *  ctrl       - fd pointing to a l2cap control connection
+	 *  loop       - libev event loop for IO processing
+	 *  d          - HID descriptor for the device
 	 *
 	 *  throws std::runtime_error() on error
 	 */
-	hid_device(util::shared_cap_chan kbd_chan, util::shared_cap_chan sdp_chan,
-			hid_watcher *parent, int cons_fd, bool uinput,
-			blue::bdaddr addr, util::unique_fd ctrl, ev::loop_ref loop);
-	hid_device(util::shared_cap_chan kbd_chan, util::shared_cap_chan sdp_chan,
-			hid_watcher *parent, int cons_fd, bool uinput,
-			blue::bdaddr addr, util::unique_fd ctrl, ev::loop_ref loop,
-			blue::hid::hid_descriptor &&d);
+	struct hid_device_config
+	{
+		util::shared_cap_chan kbd_chan;
+		util::shared_cap_chan sdp_chan;
+		hid_watcher *parent;
+		int cons_fd;
+		bool uinput;
+		blue::bdaddr local_addr;
+		blue::bdaddr addr;
+		util::unique_fd ctrl;
+		ev::loop_ref loop;
+	};
+	hid_device(hid_device_config &&config, blue::hid::hid_descriptor &&d);
 	~hid_device();
 
 	/*
-	 * intr_opened() takes an fd pointing to an interrupt channel for
-	 * the device.
+	 * intr_opened() takes an kbd capability and an fd pointing to an
+	 * interrupt channel for the device.
 	 *
 	 * The device will not be functional until the interrupt channel
 	 * has been opened.
@@ -103,7 +106,8 @@ private:
 	hid_device& operator=(hid_device &&) = delete;
 
 	void init_state();
-	void populate_devid();
+	void populate_devid(util::shared_cap_chan sdp_chan,
+	                    blue::bdaddr local_addr);
 	void populate_default_devid();
 
 	const blue::bdaddr &get_addr() const;
@@ -132,8 +136,6 @@ private:
 	void ctrl_callback(ev::io &watcher, int events);
 	void intr_callback(ev::io &watcher, int events);
 
-
-	util::shared_cap_chan sdp_chan;
 	util::shared_cap_chan kbd_chan;
 
 	blue::bdaddr addr;
diff --git a/lib/src/cap_l2cap.cpp b/lib/src/cap_l2cap.cpp
index eeb6bcc5bfaf089b9c3b888f5f33e8db93c1fb24..acc2286c6b1bd584aecdcd728c790bf2e2a408b4 100644
--- a/lib/src/cap_l2cap.cpp
+++ b/lib/src/cap_l2cap.cpp
@@ -17,7 +17,7 @@ extern "C"
 namespace blue::l2cap
 {
 
-static sockaddr_l2cap create_addr(uint16_t psm, const bdaddr_t *bd_addr)
+static sockaddr_l2cap create_addr(const bdaddr_t *bd_addr, uint16_t psm)
 {
 	sockaddr_l2cap addr{};
 
@@ -31,10 +31,10 @@ static sockaddr_l2cap create_addr(uint16_t psm, const bdaddr_t *bd_addr)
 	return addr;
 }
 
-static int bind_socket(uint16_t psm)
+static int bind_socket(const bdaddr_t *local_addr, uint16_t psm)
 {
 
-	sockaddr_l2cap addr = create_addr(psm, NG_HCI_BDADDR_ANY);
+	sockaddr_l2cap addr = create_addr(local_addr, psm);
 
 	int fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP);
 	if (fd == -1)
@@ -50,11 +50,13 @@ static int bind_socket(uint16_t psm)
 	return fd;
 }
 
-util::unique_fd cap_l2cap_listen(util::shared_cap_chan chan, uint16_t psm)
+util::unique_fd cap_l2cap_listen(util::shared_cap_chan chan, const bdaddr_t *listen_addr,
+		uint16_t psm)
 {
 	nvlist_t *nvl = nvlist_create(0);
 
 	nvlist_add_string(nvl, "cmd", "l2cap_listen");
+	nvlist_add_binary(nvl, "listenaddr", listen_addr, sizeof(bdaddr_t));
 	nvlist_add_number(nvl, "psm", psm);
 
 	nvl = cap_xfer_nvlist(chan.get(), nvl);
@@ -82,8 +84,19 @@ static int impl_l2cap_listen(const nvlist_t *limits,
 {
 	int fd = -1;
 	uint16_t psm = static_cast<uint16_t>(nvlist_get_number(nvlin, "psm"));
+	size_t addr_size;
+	bdaddr_t listen_addr;
+
+	const void *l = nvlist_get_binary(nvlin, "listenaddr", &addr_size);
 
-	if ((fd = bind_socket(psm)) == -1)
+	if (sizeof(bdaddr_t) != addr_size)
+		return EINVAL;
+
+	std::copy(reinterpret_cast<const bdaddr_t *>(l),
+	          reinterpret_cast<const bdaddr_t *>(l) + 1,
+	          &listen_addr);
+
+	if ((fd = bind_socket(&listen_addr, psm)) == -1)
 		return errno;
 
 	if (listen(fd, 128) == -1)
@@ -99,14 +112,16 @@ static int impl_l2cap_listen(const nvlist_t *limits,
 	return 0;
 }
 
-util::unique_fd cap_l2cap_connect(util::shared_cap_chan chan, uint16_t psm,
-		bdaddr_t addr)
+util::unique_fd cap_l2cap_connect(util::shared_cap_chan chan,
+		const bdaddr_t *local_addr, uint16_t psm,
+		const bdaddr_t *addr)
 {
 	nvlist_t *nvl = nvlist_create(0);
 
 	nvlist_add_string(nvl, "cmd", "l2cap_connect");
+	nvlist_add_binary(nvl, "localaddr", local_addr, sizeof(bdaddr_t));
 	nvlist_add_number(nvl, "psm", psm);
-	nvlist_add_binary(nvl, "addr", &addr, sizeof(addr));
+	nvlist_add_binary(nvl, "addr", addr, sizeof(bdaddr_t));
 
 	nvl = cap_xfer_nvlist(chan.get(), nvl);
 	if (nvl == nullptr)
@@ -134,17 +149,31 @@ static int impl_l2cap_connect(const nvlist_t *limits,
 	int fd = -1;
 	size_t addr_size;
 	uint16_t psm = static_cast<uint16_t>(nvlist_get_number(nvlin, "psm"));
-	const bdaddr_t *addr =
-		reinterpret_cast<const bdaddr_t *>(
-			nvlist_get_binary(nvlin, "addr", &addr_size));
+	bdaddr_t addr;
+	bdaddr_t local_addr;
+
+	const void *l = nvlist_get_binary(nvlin, "localaddr", &addr_size);
 
 	if (sizeof(bdaddr_t) != addr_size)
 		return EINVAL;
 
-	if ((fd = bind_socket(0)) == -1)
+	std::copy(reinterpret_cast<const bdaddr_t *>(l),
+	          reinterpret_cast<const bdaddr_t *>(l) + 1,
+	          &local_addr);
+
+	const void *a = nvlist_get_binary(nvlin, "addr", &addr_size);
+
+	if (sizeof(bdaddr_t) != addr_size)
+		return EINVAL;
+
+	std::copy(reinterpret_cast<const bdaddr_t *>(a),
+	          reinterpret_cast<const bdaddr_t *>(a) + 1,
+	          &addr);
+
+	if ((fd = bind_socket(&local_addr, 0)) == -1)
 		return errno;
 
-	sockaddr_l2cap sa = create_addr(psm, addr);
+	sockaddr_l2cap sa = create_addr(&addr, psm);
 	const sockaddr *sp = reinterpret_cast<const sockaddr *>(&sa);
 	if (connect(fd, sp, sizeof(sa)) == -1)
 	{
diff --git a/lib/src/cap_sdp.cpp b/lib/src/cap_sdp.cpp
index aa084bf3c09fadc6883d4ab1b8bcbe046412c254..209042ea84403cced2bf9bfbf53b0d275f8bda25 100644
--- a/lib/src/cap_sdp.cpp
+++ b/lib/src/cap_sdp.cpp
@@ -33,12 +33,13 @@ sdp_attr::operator sdp_attr_t()
 	return ret;
 }
 
-int cap_sdp_open(util::shared_cap_chan chan, const bdaddr_t *r,
-		uint64_t &handle)
+int cap_sdp_open(util::shared_cap_chan chan, const bdaddr_t *l,
+                 const bdaddr_t *r, uint64_t &handle)
 {
 	nvlist_t *nvl = nvlist_create(0);
 
 	nvlist_add_string(nvl, "cmd", "sdp_open");
+	nvlist_add_binary(nvl, "localaddr", l, sizeof(bdaddr_t));
 	nvlist_add_binary(nvl, "remoteaddr", r, sizeof(bdaddr_t));
 
 	nvl = cap_xfer_nvlist(chan.get(), nvl);
@@ -63,8 +64,18 @@ static int impl_sdp_open(const nvlist_t *limits, nvlist_t *nvlin,
 		nvlist_t *nvlout)
 {
 	size_t addr_size;
+	bdaddr_t local;
 	bdaddr_t remote;
 
+	const void *l = nvlist_get_binary(nvlin, "localaddr", &addr_size);
+
+	if (sizeof(bdaddr_t) != addr_size)
+		return EINVAL;
+
+	std::copy(reinterpret_cast<const bdaddr_t *>(l),
+	          reinterpret_cast<const bdaddr_t *>(l) + 1,
+	          &local);
+
 	const void *r = nvlist_get_binary(nvlin, "remoteaddr", &addr_size);
 
 	if (sizeof(bdaddr_t) != addr_size)
@@ -74,7 +85,7 @@ static int impl_sdp_open(const nvlist_t *limits, nvlist_t *nvlin,
 	          reinterpret_cast<const bdaddr_t *>(r) + 1,
 	          &remote);
 
-	void *h = sdp_open(NG_HCI_BDADDR_ANY, &remote);
+	void *h = sdp_open(&local, &remote);
 	if (!h)
 		return ENOMEM;
 
diff --git a/lib/src/hci_socket.cpp b/lib/src/hci_socket.cpp
index 64efafff72e402bef0a09b1509420602540301af..fb852d4e68400e64b66cc6a0715aca2a46e368b7 100644
--- a/lib/src/hci_socket.cpp
+++ b/lib/src/hci_socket.cpp
@@ -88,8 +88,9 @@ void hci_socket::bind(const std::string &node)
 	addr.hci_family = AF_BLUETOOTH;
 	strncpy(addr.hci_node, node.c_str(), sizeof(addr.hci_node));
 	if (::bind(fd, reinterpret_cast<sockaddr *>(&addr), sizeof(addr)) < 0)
-		throw std::runtime_error("Could not bind HCI socket: " +
+		throw std::runtime_error("Could not bind HCI socket " + node + ": " +
 				std::string(strerror(errno)));
+	syslog(LOG_DEBUG, "Bound HCI node: %s", addr.hci_node);
 }
 
 void hci_socket::connect(const std::string &node)
@@ -122,6 +123,16 @@ std::vector<nodeinfo> hci_socket::find_hci_nodes()
 	return nodes;
 }
 
+bdaddr hci_socket::get_address() const
+{
+	ng_btsocket_hci_raw_node_bdaddr addr;
+	if (ioctl(fd, SIOC_HCI_RAW_NODE_GET_BDADDR, &addr, sizeof(addr)) < 0)
+		throw std::runtime_error("Could not get HCI address: " +
+		                         std::string(strerror(errno)));
+
+	return addr.bdaddr;
+}
+
 void hci_socket::set_event_filter(const std::vector<int> &filters)
 {
 	ng_btsocket_hci_raw_filter filter{};
diff --git a/lib/src/hid/bthid.cpp b/lib/src/hid/bthid.cpp
index 9456671d2684423dafd6e9a8e005bef81469a3ac..146b92aee5b330577034b871b54ad37f90a04953 100644
--- a/lib/src/hid/bthid.cpp
+++ b/lib/src/hid/bthid.cpp
@@ -263,12 +263,12 @@ hid_descriptor &hid_descriptor::operator=(hid_descriptor &&other)
 }
 
 std::optional<hid_descriptor> get_descriptor(util::shared_cap_chan sdp_chan,
-		blue::bdaddr addr)
+		blue::bdaddr local_addr, blue::bdaddr addr)
 {
 	hid_descriptor ret;
 	uint64_t handle;
 
-	if (blue::sdp::cap_sdp_open(sdp_chan, addr, handle) == -1)
+	if (blue::sdp::cap_sdp_open(sdp_chan, local_addr, addr, handle) == -1)
 		throw std::runtime_error("Could not open SDP connection.");
 
 	/*
@@ -357,12 +357,12 @@ std::optional<hid_descriptor> get_descriptor(util::shared_cap_chan sdp_chan,
 }
 
 std::optional<device_id> get_devid(util::shared_cap_chan sdp_chan,
-		blue::bdaddr addr)
+		blue::bdaddr local_addr, blue::bdaddr addr)
 {
 	device_id ret;
 	uint64_t handle;
 
-	if (blue::sdp::cap_sdp_open(sdp_chan, addr, handle) == -1)
+	if (blue::sdp::cap_sdp_open(sdp_chan, local_addr, addr, handle) == -1)
 		throw std::runtime_error("Could not open SDP connection.");
 
 	std::vector<uint16_t> pp =
diff --git a/lib/src/hid/hid_device.cpp b/lib/src/hid/hid_device.cpp
index c5b5fb4fe4d60651da13bb0754d91fa294b04b75..3a069309757722eb827dc46808023dfae5c80b54 100644
--- a/lib/src/hid/hid_device.cpp
+++ b/lib/src/hid/hid_device.cpp
@@ -10,53 +10,19 @@
 namespace blue::hid
 {
 
-hid_device::hid_device(util::shared_cap_chan kbd_chan,
-		util::shared_cap_chan sdp_chan, hid_watcher *parent,
-		int cons_fd, bool uinput, blue::bdaddr addr,
-		util::unique_fd ctrl_in, ev::loop_ref loop) :
-	sdp_chan(sdp_chan),
-	kbd_chan(kbd_chan),
-	addr(addr),
-	ctrl(std::move(ctrl_in)),
-	ctrl_watcher(loop),
-	intr_watcher(loop),
-	parent(parent),
-	cons_fd(cons_fd),
-	uinput(uinput)
-{
-
-	std::optional<blue::hid::hid_descriptor> d =
-		blue::hid::get_descriptor(sdp_chan, addr);
-	if (!d)
-		throw std::runtime_error("Could not query device HID descriptor");
-	desc = std::move(d.value());
-
-	init_state();
-	populate_devid();
-
-	ctrl_watcher.set<hid_device, &hid_device::ctrl_callback>(this);
-	ctrl_watcher.set(ctrl, ev::READ);
-	ctrl_watcher.start();
-}
-
-hid_device::hid_device(util::shared_cap_chan kbd_chan,
-		util::shared_cap_chan sdp_chan, hid_watcher *parent,
-		int cons_fd, bool uinput, blue::bdaddr addr,
-		util::unique_fd ctrl_in, ev::loop_ref loop,
-		blue::hid::hid_descriptor &&d) :
-	sdp_chan(sdp_chan),
-	kbd_chan(kbd_chan),
-	addr(addr),
+hid_device::hid_device(hid_device_config &&config, blue::hid::hid_descriptor &&d) :
+	kbd_chan(config.kbd_chan),
+	addr(config.addr),
 	desc(std::move(d)),
-	ctrl(std::move(ctrl_in)),
-	ctrl_watcher(loop),
-	intr_watcher(loop),
-	parent(parent),
-	cons_fd(cons_fd),
-	uinput(uinput)
+	ctrl(std::move(config.ctrl)),
+	ctrl_watcher(config.loop),
+	intr_watcher(config.loop),
+	parent(config.parent),
+	cons_fd(config.cons_fd),
+	uinput(config.uinput)
 {
 	init_state();
-	populate_devid();
+	populate_devid(config.sdp_chan, config.local_addr);
 
 	ctrl_watcher.set<hid_device, &hid_device::ctrl_callback>(this);
 	ctrl_watcher.set(ctrl, ev::READ);
@@ -82,12 +48,13 @@ void hid_device::init_state()
 	}
 }
 
-void hid_device::populate_devid()
+void hid_device::populate_devid(util::shared_cap_chan sdp_chan,
+                                blue::bdaddr local_addr)
 {
 	try
 	{
 		std::optional<blue::hid::device_id> devid =
-			blue::hid::get_devid(sdp_chan, addr);
+			blue::hid::get_devid(sdp_chan, local_addr, addr);
 		if (devid)
 		{
 			vendor_id = devid->vendor_id;
diff --git a/lib/src/l2cap_socket.cpp b/lib/src/l2cap_socket.cpp
index 555ce9c59ab13784625ac8456e3ffaa79cb7e893..79ff6a25918a470e3722776739f3f61f6176a0ff 100644
--- a/lib/src/l2cap_socket.cpp
+++ b/lib/src/l2cap_socket.cpp
@@ -19,7 +19,7 @@ namespace blue::l2cap
 l2cap_listen_socket::l2cap_listen_socket(util::shared_cap_chan chan,
 		ev::loop_ref loop, l2cap_listen_observer *parent, uint16_t psm) :
 	parent(parent),
-	fd(blue::l2cap::cap_l2cap_listen(chan, psm)),
+	fd(blue::l2cap::cap_l2cap_listen(chan, NG_HCI_BDADDR_ANY, psm)),
 	l2cap_watcher(loop)
 {
 	if (fd == -1)