Index: uspace/lib/drv/generic/driver.c
===================================================================
--- uspace/lib/drv/generic/driver.c	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/generic/driver.c	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -802,4 +802,5 @@
 	assert(fun->bound == false);
 	assert(fun->name != NULL);
+	assert(fun->dev != NULL);
 	
 	add_to_functions_list(fun);
@@ -906,5 +907,5 @@
 
 /** Set function ops. */
-void ddf_fun_set_ops(ddf_fun_t *fun, ddf_dev_ops_t *dev_ops)
+void ddf_fun_set_ops(ddf_fun_t *fun, const ddf_dev_ops_t *dev_ops)
 {
 	assert(fun->conn_handler == NULL);
Index: uspace/lib/drv/generic/private/driver.h
===================================================================
--- uspace/lib/drv/generic/private/driver.h	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/generic/private/driver.h	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -93,5 +93,5 @@
 	
 	/** Implementation of operations provided by this function */
-	ddf_dev_ops_t *ops;
+	const ddf_dev_ops_t *ops;
 	
 	/** Connection handler or @c NULL to use the DDF default handler. */
Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/generic/remote_usb.c	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -35,35 +35,44 @@
 
 #include <async.h>
+#include <macros.h>
 #include <errno.h>
-#include <macros.h>
+#include <devman.h>
 
 #include "usb_iface.h"
 #include "ddf/driver.h"
 
+
+usb_dev_session_t *usb_dev_connect(devman_handle_t handle)
+{
+	return devman_device_connect(EXCHANGE_PARALLEL, handle, IPC_FLAG_BLOCKING);
+}
+
+usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *dev)
+{
+	// TODO All usb requests are atomic so this is safe,
+	// it will need to change once USING EXCHANGE PARALLEL is safe with
+	// devman_parent_device_connect
+	return devman_parent_device_connect(EXCHANGE_ATOMIC,
+	    ddf_dev_get_handle(dev), IPC_FLAG_BLOCKING);
+}
+
+void usb_dev_disconnect(usb_dev_session_t *sess)
+{
+	if (sess)
+		async_hangup(sess);
+}
+
 typedef enum {
-	IPC_M_USB_GET_MY_ADDRESS,
 	IPC_M_USB_GET_MY_INTERFACE,
-	IPC_M_USB_GET_HOST_CONTROLLER_HANDLE,
+	IPC_M_USB_GET_MY_DEVICE_HANDLE,
+	IPC_M_USB_RESERVE_DEFAULT_ADDRESS,
+	IPC_M_USB_RELEASE_DEFAULT_ADDRESS,
+	IPC_M_USB_DEVICE_ENUMERATE,
+	IPC_M_USB_DEVICE_REMOVE,
+	IPC_M_USB_REGISTER_ENDPOINT,
+	IPC_M_USB_UNREGISTER_ENDPOINT,
+	IPC_M_USB_READ,
+	IPC_M_USB_WRITE,
 } usb_iface_funcs_t;
-
-/** Tell USB address assigned to device.
- * @param exch Vaid IPC exchange
- * @param address Pointer to address storage place.
- * @return Error code.
- *
- * Exch param is an open communication to device implementing usb_iface.
- */
-int usb_get_my_address(async_exch_t *exch, usb_address_t *address)
-{
-	if (!exch)
-		return EBADMEM;
-	sysarg_t addr;
-	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_MY_ADDRESS, &addr);
-
-	if (ret == EOK && address != NULL)
-		*address = (usb_address_t) addr;
-	return ret;
-}
 
 /** Tell interface number given device can use.
@@ -85,31 +94,210 @@
 }
 
-/** Tell devman handle of device host controller.
+/** Tell devman handle of the usb device function.
  * @param[in] exch IPC communication exchange
- * @param[out] hc_handle devman handle of the HC used by the target device.
+ * @param[out] handle devman handle of the HC used by the target device.
  * @return Error code.
  */
-int usb_get_hc_handle(async_exch_t *exch, devman_handle_t *hc_handle)
-{
-	if (!exch)
-		return EBADMEM;
-	devman_handle_t h;
+int usb_get_my_device_handle(async_exch_t *exch, devman_handle_t *handle)
+{
+	devman_handle_t h = 0;
 	const int ret = async_req_1_1(exch, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
-	if (ret == EOK && hc_handle)
-		*hc_handle = (devman_handle_t)h;
+	    IPC_M_USB_GET_MY_DEVICE_HANDLE, &h);
+	if (ret == EOK && handle)
+		*handle = (devman_handle_t)h;
 	return ret;
 }
 
-
-static void remote_usb_get_my_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+/** Reserve default USB address.
+ * @param[in] exch IPC communication exchange
+ * @param[in] speed Communication speed of the newly attached device
+ * @return Error code.
+ */
+int usb_reserve_default_address(async_exch_t *exch, usb_speed_t speed)
+{
+	if (!exch)
+		return EBADMEM;
+	return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_RESERVE_DEFAULT_ADDRESS, speed);
+}
+
+/** Release default USB address.
+ * @param[in] exch IPC communication exchange
+ * @return Error code.
+ */
+int usb_release_default_address(async_exch_t *exch)
+{
+	if (!exch)
+		return EBADMEM;
+	return async_req_1_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_RELEASE_DEFAULT_ADDRESS);
+}
+
+/** Trigger USB device enumeration
+ * @param[in] exch IPC communication exchange
+ * @param[out] handle Identifier of the newly added device (if successful)
+ * @return Error code.
+ */
+int usb_device_enumerate(async_exch_t *exch, unsigned port)
+{
+	if (!exch)
+		return EBADMEM;
+	const int ret = async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_DEVICE_ENUMERATE, port);
+	return ret;
+}
+
+/** Trigger USB device enumeration
+ * @param[in] exch IPC communication exchange
+ * @param[in] handle Identifier of the device
+ * @return Error code.
+ */
+int usb_device_remove(async_exch_t *exch, unsigned port)
+{
+	if (!exch)
+		return EBADMEM;
+	return async_req_2_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_DEVICE_REMOVE, port);
+}
+
+int static_assert[sizeof(sysarg_t) >= 4 ? 1 : -1];
+typedef union {
+	uint8_t arr[sizeof(sysarg_t)];
+	sysarg_t arg;
+} pack8_t;
+
+int usb_register_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
+    usb_transfer_type_t type, usb_direction_t direction,
+    size_t mps, unsigned packets, unsigned interval)
+{
+	if (!exch)
+		return EBADMEM;
+	pack8_t pack;
+	pack.arr[0] = type;
+	pack.arr[1] = direction;
+	pack.arr[2] = interval;
+	pack.arr[3] = packets;
+
+	return async_req_4_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_REGISTER_ENDPOINT, endpoint, pack.arg, mps);
+
+}
+
+int usb_unregister_endpoint(async_exch_t *exch, usb_endpoint_t endpoint,
+    usb_direction_t direction)
+{
+	if (!exch)
+		return EBADMEM;
+	return async_req_3_0(exch, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_UNREGISTER_ENDPOINT, endpoint, direction);
+}
+
+int usb_read(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
+    void *data, size_t size, size_t *rec_size)
+{
+	if (!exch)
+		return EBADMEM;
+
+	if (size == 0 && setup == 0)
+		return EOK;
+
+	/* Make call identifying target USB device and type of transfer. */
+	aid_t opening_request = async_send_4(exch,
+	    DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_READ, endpoint,
+	    (setup & UINT32_MAX), (setup >> 32), NULL);
+
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/* Retrieve the data. */
+	ipc_call_t data_request_call;
+	aid_t data_request =
+	    async_data_read(exch, data, size, &data_request_call);
+
+	if (data_request == 0) {
+		// FIXME: How to let the other side know that we want to abort?
+		async_forget(opening_request);
+		return ENOMEM;
+	}
+
+	/* Wait for the answer. */
+	sysarg_t data_request_rc;
+	sysarg_t opening_request_rc;
+	async_wait_for(data_request, &data_request_rc);
+	async_wait_for(opening_request, &opening_request_rc);
+
+	if (data_request_rc != EOK) {
+		/* Prefer the return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*rec_size = IPC_GET_ARG2(data_request_call);
+	return EOK;
+}
+
+int usb_write(async_exch_t *exch, usb_endpoint_t endpoint, uint64_t setup,
+    const void *data, size_t size)
+{
+	if (!exch)
+		return EBADMEM;
+
+	if (size == 0 && setup == 0)
+		return EOK;
+
+	aid_t opening_request = async_send_5(exch,
+	    DEV_IFACE_ID(USB_DEV_IFACE), IPC_M_USB_WRITE, endpoint, size,
+	    (setup & UINT32_MAX), (setup >> 32), NULL);
+
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/* Send the data if any. */
+	if (size > 0) {
+		const int ret = async_data_write_start(exch, data, size);
+		if (ret != EOK) {
+			async_forget(opening_request);
+			return ret;
+		}
+	}
+
+	/* Wait for the answer. */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
 static void remote_usb_get_my_interface(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usb_get_hc_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_get_my_device_handle(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_reserve_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_release_default_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_device_enumerate(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_device_remove(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usb_read(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
+static void remote_usb_write(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call);
 
 /** Remote USB interface operations. */
 static const remote_iface_func_ptr_t remote_usb_iface_ops [] = {
-	[IPC_M_USB_GET_MY_ADDRESS] = remote_usb_get_my_address,
 	[IPC_M_USB_GET_MY_INTERFACE] = remote_usb_get_my_interface,
-	[IPC_M_USB_GET_HOST_CONTROLLER_HANDLE] = remote_usb_get_hc_handle,
+	[IPC_M_USB_GET_MY_DEVICE_HANDLE] = remote_usb_get_my_device_handle,
+	[IPC_M_USB_RESERVE_DEFAULT_ADDRESS] = remote_usb_reserve_default_address,
+	[IPC_M_USB_RELEASE_DEFAULT_ADDRESS] = remote_usb_release_default_address,
+	[IPC_M_USB_DEVICE_ENUMERATE] = remote_usb_device_enumerate,
+	[IPC_M_USB_DEVICE_REMOVE] = remote_usb_device_remove,
+	[IPC_M_USB_REGISTER_ENDPOINT] = remote_usb_register_endpoint,
+	[IPC_M_USB_UNREGISTER_ENDPOINT] = remote_usb_unregister_endpoint,
+	[IPC_M_USB_READ] = remote_usb_read,
+	[IPC_M_USB_WRITE] = remote_usb_write,
 };
 
@@ -118,26 +306,6 @@
 const remote_iface_t remote_usb_iface = {
 	.method_count = ARRAY_SIZE(remote_usb_iface_ops),
-	.methods = remote_usb_iface_ops
+	.methods = remote_usb_iface_ops,
 };
-
-
-void remote_usb_get_my_address(ddf_fun_t *fun, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	const usb_iface_t *usb_iface = (usb_iface_t *) iface;
-
-	if (usb_iface->get_my_address == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	usb_address_t address;
-	const int ret = usb_iface->get_my_address(fun, &address);
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, address);
-	}
-}
 
 void remote_usb_get_my_interface(ddf_fun_t *fun, void *iface,
@@ -160,10 +328,10 @@
 }
 
-void remote_usb_get_hc_handle(ddf_fun_t *fun, void *iface,
+void remote_usb_get_my_device_handle(ddf_fun_t *fun, void *iface,
     ipc_callid_t callid, ipc_call_t *call)
 {
 	const usb_iface_t *usb_iface = (usb_iface_t *) iface;
 
-	if (usb_iface->get_hc_handle == NULL) {
+	if (usb_iface->get_my_device_handle == NULL) {
 		async_answer_0(callid, ENOTSUP);
 		return;
@@ -171,5 +339,5 @@
 
 	devman_handle_t handle;
-	const int ret = usb_iface->get_hc_handle(fun, &handle);
+	const int ret = usb_iface->get_my_device_handle(fun, &handle);
 	if (ret != EOK) {
 		async_answer_0(callid, ret);
@@ -178,4 +346,265 @@
 	async_answer_1(callid, EOK, (sysarg_t) handle);
 }
+
+void remote_usb_reserve_default_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->reserve_default_address == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_speed_t speed = DEV_IPC_GET_ARG1(*call);
+	const int ret = usb_iface->reserve_default_address(fun, speed);
+	async_answer_0(callid, ret);
+}
+
+void remote_usb_release_default_address(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->release_default_address == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	const int ret = usb_iface->release_default_address(fun);
+	async_answer_0(callid, ret);
+}
+
+static void remote_usb_device_enumerate(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->device_enumerate == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	const unsigned port = DEV_IPC_GET_ARG1(*call);
+	const int ret = usb_iface->device_enumerate(fun, port);
+	async_answer_0(callid, ret);
+}
+
+static void remote_usb_device_remove(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	const usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (usb_iface->device_remove == NULL) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	const unsigned port = DEV_IPC_GET_ARG1(*call);
+	const int ret = usb_iface->device_remove(fun, port);
+	async_answer_0(callid, ret);
+}
+
+static void remote_usb_register_endpoint(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (!usb_iface->register_endpoint) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	const usb_endpoint_t endpoint = DEV_IPC_GET_ARG1(*call);
+	const pack8_t pack = { .arg = DEV_IPC_GET_ARG2(*call)};
+	const size_t max_packet_size = DEV_IPC_GET_ARG3(*call);
+
+	const usb_transfer_type_t transfer_type = pack.arr[0];
+	const usb_direction_t direction = pack.arr[1];
+	unsigned packets = pack.arr[2];
+	unsigned interval = pack.arr[3];
+
+	const int ret = usb_iface->register_endpoint(fun, endpoint,
+	    transfer_type, direction, max_packet_size, packets, interval);
+
+	async_answer_0(callid, ret);
+}
+
+static void remote_usb_unregister_endpoint(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	if (!usb_iface->unregister_endpoint) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG1(*call);
+	usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG2(*call);
+
+	int rc = usb_iface->unregister_endpoint(fun, endpoint, direction);
+
+	async_answer_0(callid, rc);
+}
+
+typedef struct {
+	ipc_callid_t caller;
+	ipc_callid_t data_caller;
+	void *buffer;
+} async_transaction_t;
+
+static void async_transaction_destroy(async_transaction_t *trans)
+{
+	if (trans == NULL) {
+		return;
+	}
+	if (trans->buffer != NULL) {
+		free(trans->buffer);
+	}
+
+	free(trans);
+}
+
+static async_transaction_t *async_transaction_create(ipc_callid_t caller)
+{
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	if (trans == NULL) {
+		return NULL;
+	}
+
+	trans->caller = caller;
+	trans->data_caller = 0;
+	trans->buffer = NULL;
+
+	return trans;
+}
+
+static void callback_out(int outcome, void *arg)
+{
+	async_transaction_t *trans = arg;
+
+	async_answer_0(trans->caller, outcome);
+
+	async_transaction_destroy(trans);
+}
+
+static void callback_in(int outcome, size_t actual_size, void *arg)
+{
+	async_transaction_t *trans = (async_transaction_t *)arg;
+
+	if (outcome != EOK) {
+		async_answer_0(trans->caller, outcome);
+		if (trans->data_caller) {
+			async_answer_0(trans->data_caller, EINTR);
+		}
+		async_transaction_destroy(trans);
+		return;
+	}
+
+	if (trans->data_caller) {
+		async_data_read_finalize(trans->data_caller,
+		    trans->buffer, actual_size);
+	}
+
+	async_answer_0(trans->caller, EOK);
+
+	async_transaction_destroy(trans);
+}
+
+void remote_usb_read(
+    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(fun);
+	assert(iface);
+	assert(call);
+
+	const usb_iface_t *usb_iface = iface;
+
+	if (!usb_iface->read) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
+	const uint64_t setup =
+	    ((uint64_t)DEV_IPC_GET_ARG2(*call)) |
+	    (((uint64_t)DEV_IPC_GET_ARG3(*call)) << 32);
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	size_t size = 0;
+	if (!async_data_read_receive(&trans->data_caller, &size)) {
+		async_answer_0(callid, EPARTY);
+		return;
+	}
+
+	trans->buffer = malloc(size);
+	if (trans->buffer == NULL) {
+		async_answer_0(trans->data_caller, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+		async_transaction_destroy(trans);
+	}
+
+	const int rc = usb_iface->read(
+	    fun, ep, setup, trans->buffer, size, callback_in, trans);
+
+	if (rc != EOK) {
+		async_answer_0(trans->data_caller, rc);
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
+
+void remote_usb_write(
+    ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+{
+	assert(fun);
+	assert(iface);
+	assert(call);
+
+	const usb_iface_t *usb_iface = iface;
+
+	if (!usb_iface->write) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	const usb_endpoint_t ep = DEV_IPC_GET_ARG1(*call);
+	const size_t data_buffer_len = DEV_IPC_GET_ARG2(*call);
+	const uint64_t setup =
+	    ((uint64_t)DEV_IPC_GET_ARG3(*call)) |
+	    (((uint64_t)DEV_IPC_GET_ARG4(*call)) << 32);
+
+	async_transaction_t *trans = async_transaction_create(callid);
+	if (trans == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	size_t size = 0;
+	if (data_buffer_len > 0) {
+		const int rc = async_data_write_accept(&trans->buffer, false,
+		    1, data_buffer_len, 0, &size);
+
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			async_transaction_destroy(trans);
+			return;
+		}
+	}
+
+	const int rc = usb_iface->write(
+	    fun, ep, setup, trans->buffer, size, callback_out, trans);
+
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		async_transaction_destroy(trans);
+	}
+}
 /**
  * @}
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -85,70 +85,4 @@
  */
 typedef enum {
-	/** Asks for address assignment by host controller.
-	 * Answer:
-	 * - ELIMIT - host controller run out of address
-	 * - EOK - address assigned
-	 * Answer arguments:
-	 * - assigned address
-	 *
-	 * The address must be released by via IPC_M_USBHC_RELEASE_ADDRESS.
-	 */
-	IPC_M_USBHC_REQUEST_ADDRESS,
-
-	/** Bind USB address with devman handle.
-	 * Parameters:
-	 * - USB address
-	 * - devman handle
-	 * Answer:
-	 * - EOK - address binded
-	 * - ENOENT - address is not in use
-	 */
-	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:
-	 * - address to be released
-	 * Answer:
-	 * - ENOENT - address not in use
-	 * - EPERM - trying to release default USB address
-	 */
-	IPC_M_USBHC_RELEASE_ADDRESS,
-
-	/** Register endpoint attributes at host controller.
-	 * This is used to reserve portion of USB bandwidth.
-	 * When speed is invalid, speed of the device is used.
-	 * Parameters:
-	 * - USB address + endpoint number
-	 *   - packed as ADDR << 16 + EP
-	 * - speed + transfer type + direction
-	 *   - packed as ( SPEED << 8 + TYPE ) << 8 + DIR
-	 * - maximum packet size + interval (in milliseconds)
-	 *   - packed as MPS << 16 + INT
-	 * Answer:
-	 * - EOK - reservation successful
-	 * - ELIMIT - not enough bandwidth to satisfy the request
-	 */
-	IPC_M_USBHC_REGISTER_ENDPOINT,
-
-	/** Revert endpoint registration.
-	 * Parameters:
-	 * - USB address
-	 * - endpoint number
-	 * - data direction
-	 * Answer:
-	 * - EOK - endpoint unregistered
-	 * - ENOENT - unknown endpoint
-	 */
-	IPC_M_USBHC_UNREGISTER_ENDPOINT,
-
 	/** Get data from device.
 	 * See explanation at usb_iface_funcs_t (IN transaction).
@@ -161,73 +95,4 @@
 	IPC_M_USBHC_WRITE,
 } usbhc_iface_funcs_t;
-
-int usbhc_request_address(async_exch_t *exch, usb_address_t *address,
-    bool strict, usb_speed_t speed)
-{
-	if (!exch || !address)
-		return EBADMEM;
-	sysarg_t new_address;
-	const int ret = async_req_4_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REQUEST_ADDRESS, *address, strict, speed, &new_address);
-	if (ret == EOK)
-		*address = (usb_address_t)new_address;
-	return ret;
-}
-
-int usbhc_bind_address(async_exch_t *exch, usb_address_t address,
-    devman_handle_t handle)
-{
-	if (!exch)
-		return EBADMEM;
-	return async_req_3_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_BIND_ADDRESS, address, handle);
-}
-
-int usbhc_get_handle(async_exch_t *exch, usb_address_t address,
-    devman_handle_t *handle)
-{
-	if (!exch)
-		return EBADMEM;
-	sysarg_t h;
-	const int ret = async_req_2_1(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_HANDLE_BY_ADDRESS, address, &h);
-	if (ret == EOK && handle)
-		*handle = (devman_handle_t)h;
-	return ret;
-}
-
-int usbhc_release_address(async_exch_t *exch, usb_address_t address)
-{
-	if (!exch)
-		return EBADMEM;
-	return async_req_2_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_ADDRESS, address);
-}
-
-int usbhc_register_endpoint(async_exch_t *exch, usb_address_t address,
-    usb_endpoint_t endpoint, usb_transfer_type_t type,
-    usb_direction_t direction, size_t mps, unsigned interval)
-{
-	if (!exch)
-		return EBADMEM;
-	const usb_target_t target =
-	    {{ .address = address, .endpoint = endpoint }};
-#define _PACK2(high, low) (((high & 0xffff) << 16) | (low & 0xffff))
-
-	return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REGISTER_ENDPOINT, target.packed,
-	    _PACK2(type, direction), _PACK2(mps, interval));
-
-#undef _PACK2
-}
-
-int usbhc_unregister_endpoint(async_exch_t *exch, usb_address_t address,
-    usb_endpoint_t endpoint, usb_direction_t direction)
-{
-	if (!exch)
-		return EBADMEM;
-	return async_req_4_0(exch, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_UNREGISTER_ENDPOINT, address, endpoint, direction);
-}
 
 int usbhc_read(async_exch_t *exch, usb_address_t address,
@@ -323,25 +188,9 @@
 }
 
-
-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_get_handle(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 *);
-static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_read(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_write(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-//static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
 /** Remote USB host controller interface operations. */
 static const remote_iface_func_ptr_t remote_usbhc_iface_ops[] = {
-	[IPC_M_USBHC_REQUEST_ADDRESS] = remote_usbhc_request_address,
-	[IPC_M_USBHC_RELEASE_ADDRESS] = remote_usbhc_release_address,
-	[IPC_M_USBHC_BIND_ADDRESS] = remote_usbhc_bind_address,
-	[IPC_M_USBHC_GET_HANDLE_BY_ADDRESS] = remote_usbhc_get_handle,
-
-	[IPC_M_USBHC_REGISTER_ENDPOINT] = remote_usbhc_register_endpoint,
-	[IPC_M_USBHC_UNREGISTER_ENDPOINT] = remote_usbhc_unregister_endpoint,
-
 	[IPC_M_USBHC_READ] = remote_usbhc_read,
 	[IPC_M_USBHC_WRITE] = remote_usbhc_write,
@@ -386,82 +235,5 @@
 }
 
-void remote_usbhc_request_address(ddf_fun_t *fun, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbhc_iface_t *usb_iface = iface;
-
-	if (!usb_iface->request_address) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	usb_address_t address = DEV_IPC_GET_ARG1(*call);
-	const bool strict = DEV_IPC_GET_ARG2(*call);
-	const usb_speed_t speed = DEV_IPC_GET_ARG3(*call);
-
-	const int rc = usb_iface->request_address(fun, &address, strict, speed);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-	} else {
-		async_answer_1(callid, EOK, (sysarg_t) address);
-	}
-}
-
-void remote_usbhc_bind_address(ddf_fun_t *fun, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbhc_iface_t *usb_iface = iface;
-
-	if (!usb_iface->bind_address) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
-	const devman_handle_t handle = (devman_handle_t) DEV_IPC_GET_ARG2(*call);
-
-	const int ret = usb_iface->bind_address(fun, address, handle);
-	async_answer_0(callid, ret);
-}
-
-void remote_usbhc_get_handle(ddf_fun_t *fun, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbhc_iface_t *usb_iface = iface;
-
-	if (!usb_iface->get_handle) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
-	devman_handle_t handle;
-	const int ret = usb_iface->get_handle(fun, address, &handle);
-
-	if (ret == EOK) {
-		async_answer_1(callid, ret, handle);
-	} else {
-		async_answer_0(callid, ret);
-	}
-}
-
-void remote_usbhc_release_address(ddf_fun_t *fun, void *iface,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbhc_iface_t *usb_iface = iface;
-
-	if (!usb_iface->release_address) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	const usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
-
-	const int ret = usb_iface->release_address(fun, address);
-	async_answer_0(callid, ret);
-}
-
-static void callback_out(ddf_fun_t *fun,
-    int outcome, void *arg)
+static void callback_out(int outcome, void *arg)
 {
 	async_transaction_t *trans = arg;
@@ -472,6 +244,5 @@
 }
 
-static void callback_in(ddf_fun_t *fun,
-    int outcome, size_t actual_size, void *arg)
+static void callback_in(int outcome, size_t actual_size, void *arg)
 {
 	async_transaction_t *trans = (async_transaction_t *)arg;
@@ -496,56 +267,4 @@
 }
 
-void remote_usbhc_register_endpoint(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->register_endpoint) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-#define _INIT_FROM_HIGH_DATA2(type, var, arg_no) \
-	type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) >> 16)
-#define _INIT_FROM_LOW_DATA2(type, var, arg_no) \
-	type var = (type) (DEV_IPC_GET_ARG##arg_no(*call) & 0xffff)
-
-	const usb_target_t target = { .packed = DEV_IPC_GET_ARG1(*call) };
-
-	_INIT_FROM_HIGH_DATA2(usb_transfer_type_t, transfer_type, 2);
-	_INIT_FROM_LOW_DATA2(usb_direction_t, direction, 2);
-
-	_INIT_FROM_HIGH_DATA2(size_t, max_packet_size, 3);
-	_INIT_FROM_LOW_DATA2(unsigned int, interval, 3);
-
-#undef _INIT_FROM_HIGH_DATA2
-#undef _INIT_FROM_LOW_DATA2
-
-	int rc = usb_iface->register_endpoint(fun, target.address,
-	    target.endpoint, transfer_type, direction, max_packet_size, interval);
-
-	async_answer_0(callid, rc);
-}
-
-void remote_usbhc_unregister_endpoint(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->unregister_endpoint) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
-	usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
-	usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
-
-	int rc = usb_iface->unregister_endpoint(fun,
-	    address, endpoint, direction);
-
-	async_answer_0(callid, rc);
-}
-
 void remote_usbhc_read(
     ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
Index: uspace/lib/drv/include/ddf/driver.h
===================================================================
--- uspace/lib/drv/include/ddf/driver.h	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/include/ddf/driver.h	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -132,5 +132,5 @@
 extern int ddf_fun_offline(ddf_fun_t *);
 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int);
-extern void ddf_fun_set_ops(ddf_fun_t *, ddf_dev_ops_t *);
+extern void ddf_fun_set_ops(ddf_fun_t *, const ddf_dev_ops_t *);
 extern void ddf_fun_set_conn_handler(ddf_fun_t *, async_client_conn_t);
 extern int ddf_fun_add_to_category(ddf_fun_t *, const char *);
Index: uspace/lib/drv/include/usb_iface.h
===================================================================
--- uspace/lib/drv/include/usb_iface.h	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/include/usb_iface.h	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -42,13 +42,51 @@
 #include <usb/usb.h>
 
-int usb_get_my_address(async_exch_t *, usb_address_t *);
+typedef async_sess_t usb_dev_session_t;
+
+usb_dev_session_t *usb_dev_connect(devman_handle_t);
+usb_dev_session_t *usb_dev_connect_to_self(ddf_dev_t *);
+void usb_dev_disconnect(usb_dev_session_t *);
+
 int usb_get_my_interface(async_exch_t *, int *);
-int usb_get_hc_handle(async_exch_t *, devman_handle_t *);
+int usb_get_my_device_handle(async_exch_t *, devman_handle_t *);
+
+int usb_reserve_default_address(async_exch_t *, usb_speed_t);
+int usb_release_default_address(async_exch_t *);
+
+int usb_device_enumerate(async_exch_t *, unsigned port);
+int usb_device_remove(async_exch_t *, unsigned port);
+
+int usb_register_endpoint(async_exch_t *, usb_endpoint_t, usb_transfer_type_t,
+    usb_direction_t, size_t, unsigned, unsigned);
+int usb_unregister_endpoint(async_exch_t *, usb_endpoint_t, usb_direction_t);
+int usb_read(async_exch_t *, usb_endpoint_t, uint64_t, void *, size_t, size_t *);
+int usb_write(async_exch_t *, usb_endpoint_t, uint64_t, const void *, size_t);
+
+/** Callback for outgoing transfer. */
+typedef void (*usb_iface_transfer_out_callback_t)(int, void *);
+
+/** Callback for incoming transfer. */
+typedef void (*usb_iface_transfer_in_callback_t)(int, size_t, void *);
 
 /** USB device communication interface. */
 typedef struct {
-	int (*get_my_address)(ddf_fun_t *, usb_address_t *);
 	int (*get_my_interface)(ddf_fun_t *, int *);
-	int (*get_hc_handle)(ddf_fun_t *, devman_handle_t *);
+	int (*get_my_device_handle)(ddf_fun_t *, devman_handle_t *);
+
+	int (*reserve_default_address)(ddf_fun_t *, usb_speed_t);
+	int (*release_default_address)(ddf_fun_t *);
+
+	int (*device_enumerate)(ddf_fun_t *, unsigned);
+	int (*device_remove)(ddf_fun_t *, unsigned);
+
+	int (*register_endpoint)(ddf_fun_t *, usb_endpoint_t,
+	    usb_transfer_type_t, usb_direction_t, size_t, unsigned, unsigned);
+	int (*unregister_endpoint)(ddf_fun_t *, usb_endpoint_t,
+	    usb_direction_t);
+
+	int (*read)(ddf_fun_t *, usb_endpoint_t, uint64_t, uint8_t *, size_t,
+	    usb_iface_transfer_in_callback_t, void *);
+	int (*write)(ddf_fun_t *, usb_endpoint_t, uint64_t, const uint8_t *,
+	    size_t, usb_iface_transfer_out_callback_t, void *);
 } usb_iface_t;
 
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 88205440caa3e827197cd095139acca02b989d5e)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 200373928c6b0d2d85f0afee8d1fa4db29c2c656)
@@ -44,12 +44,4 @@
 #include <stdbool.h>
 
-int usbhc_request_address(async_exch_t *, usb_address_t *, bool, usb_speed_t);
-int usbhc_bind_address(async_exch_t *, usb_address_t, devman_handle_t);
-int usbhc_get_handle(async_exch_t *, usb_address_t, devman_handle_t *);
-int usbhc_release_address(async_exch_t *, usb_address_t);
-int usbhc_register_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
-    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
-int usbhc_unregister_endpoint(async_exch_t *, usb_address_t, usb_endpoint_t,
-    usb_direction_t);
 int usbhc_read(async_exch_t *, usb_address_t, usb_endpoint_t,
     uint64_t, void *, size_t, size_t *);
@@ -58,27 +50,13 @@
 
 /** Callback for outgoing transfer. */
-typedef void (*usbhc_iface_transfer_out_callback_t)(ddf_fun_t *, int, void *);
+typedef void (*usbhc_iface_transfer_out_callback_t)(int, void *);
 
 /** Callback for incoming transfer. */
-typedef void (*usbhc_iface_transfer_in_callback_t)(ddf_fun_t *,
-    int, size_t, void *);
+typedef void (*usbhc_iface_transfer_in_callback_t)(int, size_t, void *);
 
 /** USB host controller communication interface. */
 typedef struct {
-	int (*request_address)(ddf_fun_t *, usb_address_t *, bool, usb_speed_t);
-	int (*bind_address)(ddf_fun_t *, usb_address_t, devman_handle_t);
-	int (*get_handle)(ddf_fun_t *, usb_address_t,
-	    devman_handle_t *);
-	int (*release_address)(ddf_fun_t *, usb_address_t);
-
-	int (*register_endpoint)(ddf_fun_t *,
-	    usb_address_t, usb_endpoint_t,
-	    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
-	int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
-	    usb_direction_t);
-
 	int (*read)(ddf_fun_t *, usb_target_t, uint64_t, uint8_t *, size_t,
 	    usbhc_iface_transfer_in_callback_t, void *);
-
 	int (*write)(ddf_fun_t *, usb_target_t, uint64_t, const uint8_t *,
 	    size_t, usbhc_iface_transfer_out_callback_t, void *);
