Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision 867b3757d6898c102509e02a34857fa95c832191)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
@@ -45,4 +45,5 @@
 #include <usb/usb.h>
 
+#include <assert.h>
 #include <fibril_synch.h>
 #include <stdbool.h>
@@ -51,6 +52,33 @@
 typedef struct endpoint endpoint_t;
 typedef struct bus bus_t;
+typedef struct ddf_fun ddf_fun_t;
+
+typedef struct device {
+	/* Device tree keeping */
+	link_t link;
+	list_t devices;
+	fibril_mutex_t guard;
+
+	/* Associated DDF function, if any */
+	ddf_fun_t *fun;
+
+	/* Invalid for the roothub device */
+	unsigned port;
+	struct device *hub;
+
+	/* Transaction translator */
+	usb_tt_address_t tt;
+
+	/* The following are not set by the library */
+	usb_speed_t speed;
+	usb_address_t address;
+
+	/* This structure is meant to be extended by overriding. */
+} device_t;
 
 typedef struct {
+	int (*enumerate_device)(bus_t *, hcd_t *, device_t *);
+	int (*remove_device)(bus_t *, hcd_t *, device_t *);
+
 	endpoint_t *(*create_endpoint)(bus_t *);
 	int (*register_endpoint)(bus_t *, endpoint_t *);
@@ -59,5 +87,4 @@
 
 	int (*request_address)(bus_t *, usb_address_t*, bool, usb_speed_t);
-	int (*get_speed)(bus_t *, usb_address_t, usb_speed_t *);
 	int (*release_address)(bus_t *, usb_address_t);
 
@@ -77,4 +104,6 @@
 	fibril_mutex_t guard;
 
+	size_t device_size;
+
 	/* Do not call directly, ops are synchronized. */
 	bus_ops_t ops;
@@ -83,5 +112,16 @@
 } bus_t;
 
-void bus_init(bus_t *);
+void bus_init(bus_t *, size_t);
+int device_init(device_t *);
+
+extern int bus_add_ep(bus_t *bus, device_t *device, usb_endpoint_t endpoint,
+    usb_direction_t dir, usb_transfer_type_t type, size_t max_packet_size,
+    unsigned packets, size_t size);
+extern int bus_remove_ep(bus_t *bus, usb_target_t target, usb_direction_t dir);
+
+int device_set_default_name(device_t *);
+
+int bus_enumerate_device(bus_t *, hcd_t *, device_t *);
+int bus_remove_device(bus_t *, hcd_t *, device_t *);
 
 endpoint_t *bus_create_endpoint(bus_t *);
@@ -93,6 +133,17 @@
 
 int bus_request_address(bus_t *, usb_address_t *, bool, usb_speed_t);
-int bus_get_speed(bus_t *, usb_address_t, usb_speed_t *);
 int bus_release_address(bus_t *, usb_address_t);
+
+static inline int bus_reserve_default_address(bus_t *bus, usb_speed_t speed) {
+	usb_address_t addr = USB_ADDRESS_DEFAULT;
+
+	const int r = bus_request_address(bus, &addr, true, speed);
+	assert(addr == USB_ADDRESS_DEFAULT);
+	return r;
+}
+
+static inline int bus_release_default_address(bus_t *bus) {
+	return bus_release_address(bus, USB_ADDRESS_DEFAULT);
+}
 
 int bus_reset_toggle(bus_t *, usb_target_t, bool);
Index: uspace/lib/usbhost/include/usb/host/ddf_helpers.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/ddf_helpers.h	(revision 867b3757d6898c102509e02a34857fa95c832191)
+++ uspace/lib/usbhost/include/usb/host/ddf_helpers.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
@@ -59,5 +59,4 @@
 typedef struct {
 	hcd_ops_t ops;
-	usb_speed_t hc_speed;
 	const char *name;
 
@@ -83,4 +82,8 @@
 int hcd_setup_virtual_root_hub(hcd_t *, ddf_dev_t *);
 
+device_t *hcd_ddf_device_create(ddf_dev_t *, size_t);
+void hcd_ddf_device_destroy(device_t *);
+int hcd_ddf_device_explore(hcd_t *, device_t *);
+
 hcd_t *dev_to_hcd(ddf_dev_t *dev);
 
@@ -93,15 +96,4 @@
 void ddf_hcd_gen_irq_handler(ipc_callid_t iid, ipc_call_t *call, ddf_dev_t *dev);
 
-/* For xHCI, we need to drive the roothub without roothub having assigned an
- * address. Thus we cannot create function for it, and we have to carry the
- * usb_dev_t somewhere.
- *
- * This is sort of hacky, but at least does not expose the internals of ddf_helpers.
- */
-typedef struct hcd_roothub hcd_roothub_t;
-
-hcd_roothub_t *hcd_roothub_create(hcd_t *, ddf_dev_t *, usb_speed_t);
-int hcd_roothub_new_device(hcd_roothub_t *, unsigned port);
-
 #endif
 
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 867b3757d6898c102509e02a34857fa95c832191)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
@@ -47,4 +47,5 @@
 
 typedef struct bus bus_t;
+typedef struct device device_t;
 
 /** Host controller side endpoint structure. */
@@ -56,4 +57,6 @@
 	/** Part of linked list. */
 	link_t link;
+	/** USB device */
+	device_t *device;
 	/** USB address. */
 	usb_target_t target;
@@ -78,6 +81,4 @@
 	/** Signals change of active status. */
 	fibril_condvar_t avail;
-	/** High speed TT data */
-	usb_tt_address_t tt;
 
 	/* This structure is meant to be extended by overriding. */
Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision 867b3757d6898c102509e02a34857fa95c832191)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision dbf32b10e7146a1f953c4eda94c63b8ac246f0ba)
@@ -103,13 +103,4 @@
 extern usb_address_t hcd_request_address(hcd_t *, usb_speed_t);
 
-extern int hcd_release_address(hcd_t *, usb_address_t);
-
-extern int hcd_reserve_default_address(hcd_t *, usb_speed_t);
-
-static inline int hcd_release_default_address(hcd_t *hcd)
-{
-	return hcd_release_address(hcd, USB_ADDRESS_DEFAULT);
-}
-
 extern int hcd_add_ep(hcd_t *, usb_target_t, usb_direction_t,
     usb_transfer_type_t, size_t, unsigned int, size_t, usb_tt_address_t);
