Index: uspace/app/lsusb/main.c
===================================================================
--- uspace/app/lsusb/main.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/app/lsusb/main.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -44,10 +44,51 @@
 #include <devman.h>
 #include <devmap.h>
+#include <usb/hub.h>
 #include <usb/host.h>
 
 #define NAME "lsusb"
 
-#define MAX_FAILED_ATTEMPTS 4
+#define MAX_FAILED_ATTEMPTS 10
 #define MAX_PATH_LENGTH 1024
+
+static void print_found_hc(size_t class_index, const char *path)
+{
+	// printf(NAME ": host controller %zu is `%s'.\n", class_index, path);
+	printf("Bus %02zu: %s\n", class_index, path);
+}
+static void print_found_dev(usb_address_t addr, const char *path)
+{
+	// printf(NAME ":     device with address %d is `%s'.\n", addr, path);
+	printf("  Device %02d: %s\n", addr, path);
+}
+
+static void print_hc_devices(devman_handle_t hc_handle)
+{
+	int rc;
+	usb_hc_connection_t conn;
+
+	usb_hc_connection_initialize(&conn, hc_handle);
+	rc = usb_hc_connection_open(&conn);
+	if (rc != EOK) {
+		printf(NAME ": failed to connect to HC: %s.\n",
+		    str_error(rc));
+		return;
+	}
+	usb_address_t addr;
+	for (addr = 1; addr < 5; addr++) {
+		devman_handle_t dev_handle;
+		rc = usb_hc_get_handle_by_address(&conn, addr, &dev_handle);
+		if (rc != EOK) {
+			continue;
+		}
+		char path[MAX_PATH_LENGTH];
+		rc = devman_get_device_path(dev_handle, path, MAX_PATH_LENGTH);
+		if (rc != EOK) {
+			continue;
+		}
+		print_found_dev(addr, path);
+	}
+	usb_hc_connection_close(&conn);
+}
 
 int main(int argc, char *argv[])
@@ -69,6 +110,6 @@
 			continue;
 		}
-		printf(NAME ": host controller %zu is `%s'.\n",
-		    class_index, path);
+		print_found_hc(class_index, path);
+		print_hc_devices(hc_handle);
 	}
 
Index: uspace/drv/ehci-hcd/hc_iface.c
===================================================================
--- uspace/drv/ehci-hcd/hc_iface.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/drv/ehci-hcd/hc_iface.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -106,4 +106,19 @@
 }
 
+/** Find device handle by USB address.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	UNSUPPORTED("find_by_address");
+
+	return ENOTSUP;
+}
+
 /** Release previously requested address.
  *
@@ -321,4 +336,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/drv/ohci/iface.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -122,4 +122,24 @@
 	return EOK;
 }
+
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+
 /*----------------------------------------------------------------------------*/
 /** Release address interface function
@@ -402,4 +422,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/drv/ohci/root_hub.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -237,5 +237,5 @@
 		return ENOMEM;
 
-	usb_log_info("OHCI root hub with %d ports initialized.\n",
+	usb_log_info("OHCI root hub with %zu ports initialized.\n",
 	    instance->port_count);
 
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/drv/uhci-hcd/iface.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -122,4 +122,23 @@
 	return EOK;
 }
+
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	assert(fun);
+	hc_t *hc = fun_to_hc(fun);
+	assert(hc);
+	bool found =
+	    usb_device_keeper_find_by_address(&hc->manager, address, handle);
+	return found ? EOK : ENOENT;
+}
+
 /*----------------------------------------------------------------------------*/
 /** Release address interface function
@@ -352,4 +371,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/drv/vhc/connhost.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -94,4 +94,20 @@
 }
 
+/** Find device handle by address interface function.
+ *
+ * @param[in] fun DDF function that was called.
+ * @param[in] address Address in question.
+ * @param[out] handle Where to store device handle if found.
+ * @return Error code.
+ */
+static int find_by_address(ddf_fun_t *fun, usb_address_t address,
+    devman_handle_t *handle)
+{
+	VHC_DATA(vhc, fun);
+	bool found =
+	    usb_device_keeper_find_by_address(&vhc->dev_keeper, address, handle);
+	return found ? EOK : ENOENT;
+}
+
 /** Release previously requested address.
  *
@@ -444,4 +460,5 @@
 	.request_address = request_address,
 	.bind_address = bind_address,
+	.find_by_address = find_by_address,
 	.release_address = release_address,
 
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -52,4 +52,5 @@
 static void remote_usbhc_request_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_find_by_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -61,4 +62,5 @@
 	remote_usbhc_request_address,
 	remote_usbhc_bind_address,
+	remote_usbhc_find_by_address,
 	remote_usbhc_release_address,
 
@@ -161,4 +163,25 @@
 
 	async_answer_0(callid, rc);
+}
+
+void remote_usbhc_find_by_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->find_by_address) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+	devman_handle_t handle;
+	int rc = usb_iface->find_by_address(fun, address, &handle);
+
+	if (rc == EOK) {
+		async_answer_1(callid, EOK, handle);
+	} else {
+		async_answer_0(callid, rc);
+	}
 }
 
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/drv/include/usb_iface.h	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -49,4 +49,19 @@
 	 * - arbitrary error code if returned by remote implementation
 	 * - EOK - handle found, first parameter contains the USB address
+	 *
+	 * The handle must be the one used for binding USB address with
+	 * it (IPC_M_USBHC_BIND_ADDRESS), otherwise the host controller
+	 * (that this request would eventually reach) would not be able
+	 * to find it.
+	 * The problem is that this handle is actually assigned to the
+	 * function inside driver of the parent device (usually hub driver).
+	 * To bypass this problem, the initial caller specify handle as
+	 * zero and the first parent assigns the actual value.
+	 * See usb_iface_get_address_hub_child_impl() implementation
+	 * that could be assigned to device ops of a child device of in a
+	 * hub driver.
+	 * For example, the USB multi interface device driver (MID)
+	 * passes this initial zero without any modification because the
+	 * handle must be resolved by its parent.
 	 */
 	IPC_M_USB_GET_ADDRESS,
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -105,4 +105,13 @@
 	IPC_M_USBHC_BIND_ADDRESS,
 
+	/** Get handle binded with given USB address.
+	 * Parameters
+	 * - USB address
+	 * Answer:
+	 * - EOK - address binded, first parameter is the devman handle
+	 * - ENOENT - address is not in use at the moment
+	 */
+	IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
+
 	/** Release address in use.
 	 * Arguments:
@@ -207,4 +216,5 @@
 	int (*request_address)(ddf_fun_t *, usb_speed_t, usb_address_t *);
 	int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
+	int (*find_by_address)(ddf_fun_t *, usb_address_t, devman_handle_t *);
 	int (*release_address)(ddf_fun_t *, usb_address_t);
 
Index: uspace/lib/usb/include/usb/host/device_keeper.h
===================================================================
--- uspace/lib/usb/include/usb/host/device_keeper.h	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/usb/include/usb/host/device_keeper.h	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -80,4 +80,7 @@
     devman_handle_t handle);
 
+bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t *handle);
+
 usb_speed_t usb_device_keeper_get_speed(usb_device_keeper_t *instance,
     usb_address_t address);
Index: uspace/lib/usb/include/usb/hub.h
===================================================================
--- uspace/lib/usb/include/usb/hub.h	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/usb/include/usb/hub.h	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -63,4 +63,6 @@
     const usb_hc_attached_device_t *);
 int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
+int usb_hc_get_handle_by_address(usb_hc_connection_t *, usb_address_t,
+    devman_handle_t *);
 
 #endif
Index: uspace/lib/usb/src/host/device_keeper.c
===================================================================
--- uspace/lib/usb/src/host/device_keeper.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/usb/src/host/device_keeper.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -157,4 +157,34 @@
 	return ENOENT;
 }
+
+/** Find devman handled assigned to USB address.
+ *
+ * @param[in] instance Device keeper structure to use.
+ * @param[in] address Address the caller wants to find.
+ * @param[out] handle Where to store found handle.
+ * @return Whether such address is currently occupied.
+ */
+bool usb_device_keeper_find_by_address(usb_device_keeper_t *instance,
+    usb_address_t address, devman_handle_t *handle)
+{
+	assert(instance);
+	fibril_mutex_lock(&instance->guard);
+	if ((address < 0) || (address >= USB_ADDRESS_COUNT)) {
+		fibril_mutex_unlock(&instance->guard);
+		return false;
+	}
+	if (!instance->devices[address].occupied) {
+		fibril_mutex_unlock(&instance->guard);
+		return false;
+	}
+
+	if (handle != NULL) {
+		*handle = instance->devices[address].handle;
+	}
+
+	fibril_mutex_unlock(&instance->guard);
+	return true;
+}
+
 /*----------------------------------------------------------------------------*/
 /** Get speed associated with the address
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 11349a852e86ea2e72b2ef3e7b100153778c78c4)
+++ uspace/lib/usb/src/hub.c	(revision 511cfc89a660d088fe845070ec48c2c2ab50e551)
@@ -117,4 +117,28 @@
 	    DEV_IFACE_ID(USBHC_DEV_IFACE),
 	    IPC_M_USBHC_RELEASE_ADDRESS, address);
+}
+
+/** Get handle of USB device with given address.
+ *
+ * @param[in] connection Opened connection to host controller.
+ * @param[in] address Address of device in question.
+ * @param[out] handle Where to write the device handle.
+ * @return Error code.
+ */
+int usb_hc_get_handle_by_address(usb_hc_connection_t *connection,
+    usb_address_t address, devman_handle_t *handle)
+{
+	CHECK_CONNECTION(connection);
+
+	sysarg_t tmp;
+	int rc = async_req_2_1(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_GET_HANDLE_BY_ADDRESS,
+	    address, &tmp);
+	if ((rc == EOK) && (handle != NULL)) {
+		*handle = tmp;
+	}
+
+	return rc;
 }
 
