Index: uspace/lib/usbhost/include/usb/host/hcd.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/hcd.h	(revision 5994cc369bffdc443847380a09fcd418bfbacb78)
+++ uspace/lib/usbhost/include/usb/host/hcd.h	(revision 9c7ed9ceda1ac65348816b6919aef3f2096a4dab)
@@ -38,4 +38,5 @@
 
 #include <assert.h>
+#include <adt/list.h>
 #include <usbhc_iface.h>
 
@@ -56,4 +57,6 @@
 	/** Endpoint manager. */
 	usb_endpoint_manager_t ep_manager;
+	/** Added devices */
+	list_t devices;
 
 	/** Device specific driver data. */
@@ -80,4 +83,6 @@
 	usb_device_manager_init(&hcd->dev_manager, max_speed);
 	usb_endpoint_manager_init(&hcd->ep_manager, bandwidth, bw_count);
+	list_initialize(&hcd->devices);
+
 	hcd->private_data = NULL;
 	hcd->schedule = NULL;
@@ -110,4 +115,9 @@
 }
 
+
+int hcd_add_device(hcd_t *instance, ddf_dev_t *parent,
+    usb_address_t address, usb_speed_t speed, const char *name,
+    const match_id_list_t *mids);
+
 int hcd_setup_device(ddf_dev_t *device);
 int hcd_setup_hub(hcd_t *instance, usb_address_t *address, ddf_dev_t *dev);
Index: uspace/lib/usbhost/src/hcd.c
===================================================================
--- uspace/lib/usbhost/src/hcd.c	(revision 5994cc369bffdc443847380a09fcd418bfbacb78)
+++ uspace/lib/usbhost/src/hcd.c	(revision 9c7ed9ceda1ac65348816b6919aef3f2096a4dab)
@@ -43,5 +43,4 @@
 typedef struct hc_dev {
 	ddf_fun_t *hc_fun;
-	ddf_fun_t *rh_fun;
 } hc_dev_t;
 
@@ -62,4 +61,6 @@
 
 typedef struct usb_dev {
+	link_t link;
+	ddf_fun_t *fun;
 	usb_address_t address;
 	usb_speed_t speed;
@@ -106,5 +107,5 @@
 };
 /** Standard USB RH options (RH interface) */
-static ddf_dev_ops_t rh_ops = {
+static ddf_dev_ops_t usb_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface,
 };
@@ -115,4 +116,50 @@
 };
 
+int hcd_add_device(hcd_t *instance, ddf_dev_t *parent,
+    usb_address_t address, usb_speed_t speed, const char *name,
+    const match_id_list_t *mids)
+{
+	assert(instance);
+	assert(parent);
+	hc_dev_t *hc_dev = ddf_dev_data_get(parent);
+	devman_handle_t hc_handle = ddf_fun_get_handle(hc_dev->hc_fun);
+
+	//TODO more checks
+	ddf_fun_t *fun = ddf_fun_create(parent, fun_inner, name);
+	if (!fun)
+		return ENOMEM;
+	usb_dev_t *info = ddf_fun_data_alloc(fun, sizeof(usb_dev_t));
+	if (!info) {
+		ddf_fun_destroy(fun);
+		return ENOMEM;
+	}
+	info->address = address;
+	info->speed = speed;
+	info->handle = hc_handle;
+	info->fun = fun;
+	link_initialize(&info->link);
+
+	ddf_fun_set_ops(fun, &usb_ops);
+	list_foreach(mids->ids, iter) {
+		match_id_t *mid = list_get_instance(iter, match_id_t, link);
+		ddf_fun_add_match_id(fun, mid->id, mid->score);
+	}
+
+	int ret = ddf_fun_bind(fun);
+	if (ret != EOK) {
+		ddf_fun_destroy(fun);
+		return ret;
+	}
+
+	ret = usb_device_manager_bind_address(&instance->dev_manager,
+	    address, ddf_fun_get_handle(fun));
+	if (ret != EOK)
+		usb_log_warning("Failed to bind root hub address: %s.\n",
+		    str_error(ret));
+
+	list_append(&info->link, &instance->devices);
+	return EOK;
+}
+
 /** Announce root hub to the DDF
  *
@@ -126,15 +173,4 @@
 	assert(address);
 	assert(device);
-
-	hc_dev_t *hc_dev = ddf_dev_data_get(device);
-	hc_dev->rh_fun = ddf_fun_create(device, fun_inner, "rh");
-	if (!hc_dev->rh_fun)
-		return ENOMEM;
-	usb_dev_t *rh = ddf_fun_data_alloc(hc_dev->rh_fun, sizeof(usb_dev_t));
-	if (!rh) {
-		ddf_fun_destroy(hc_dev->rh_fun);
-		return ENOMEM;
-	}
-
 
 	int ret = usb_device_manager_request_address(&instance->dev_manager,
@@ -143,13 +179,6 @@
 		usb_log_error("Failed to get root hub address: %s\n",
 		    str_error(ret));
-		ddf_fun_destroy(hc_dev->rh_fun);
 		return ret;
 	}
-
-	rh->address = *address;
-	rh->speed = USB_SPEED_FULL;
-	rh->handle = ddf_fun_get_handle(hc_dev->hc_fun);
-
-	ddf_fun_set_ops(hc_dev->rh_fun, &rh_ops);
 
 #define CHECK_RET_UNREG_RETURN(ret, message...) \
@@ -161,5 +190,4 @@
 	usb_device_manager_release_address( \
 	    &instance->dev_manager, *address); \
-	ddf_fun_destroy(hc_dev->rh_fun); \
 	return ret; \
 } else (void)0
@@ -170,21 +198,16 @@
 	    0, NULL, NULL);
 	CHECK_RET_UNREG_RETURN(ret,
-	    "Failed to register root hub control endpoint: %s.\n",
-	    str_error(ret));
-
-	ret = ddf_fun_add_match_id(hc_dev->rh_fun, "usb&class=hub", 100);
+	    "Failed to add root hub control endpoint: %s.\n", str_error(ret));
+
+	match_id_t mid = { .id = "usb&class=hub", .score = 100 };
+	link_initialize(&mid.link);
+	match_id_list_t mid_list;
+	init_match_ids(&mid_list);
+	add_match_id(&mid_list, &mid);
+
+	ret = hcd_add_device(
+	    instance, device, *address, USB_SPEED_FULL, "rh", &mid_list);
 	CHECK_RET_UNREG_RETURN(ret,
-	    "Failed to add root hub match-id: %s.\n", str_error(ret));
-
-	ret = ddf_fun_bind(hc_dev->rh_fun);
-	CHECK_RET_UNREG_RETURN(ret,
-	    "Failed to bind root hub function: %s.\n", str_error(ret));
-
-	ret = usb_device_manager_bind_address(&instance->dev_manager,
-	    *address, ddf_fun_get_handle(hc_dev->rh_fun));
-	if (ret != EOK)
-		usb_log_warning("Failed to bind root hub address: %s.\n",
-		    str_error(ret));
-
+	    "Failed to add hcd device: %s.\n", str_error(ret));
 
 	return EOK;
