Index: uspace/lib/drv/generic/remote_usb.c
===================================================================
--- uspace/lib/drv/generic/remote_usb.c	(revision 91db50ac4a0d8739daf1220f83a40c68c562e4cd)
+++ uspace/lib/drv/generic/remote_usb.c	(revision 32eceb4ff0c0ddeba47997beaa5d0677aee84d3a)
@@ -40,4 +40,6 @@
 #include "driver.h"
 
+#define USB_MAX_PAYLOAD_SIZE 1020
+
 static void remote_usb_get_buffer(device_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usb_interrupt_out(device_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -60,4 +62,9 @@
 };
 
+typedef struct {
+	ipc_callid_t caller;
+	void *buffer;
+	size_t size;
+} async_transaction_t;
 
 
@@ -65,5 +72,55 @@
     ipc_callid_t callid, ipc_call_t *call)
 {
-	ipc_answer_0(callid, ENOTSUP);
+	ipcarg_t buffer_hash = IPC_GET_ARG1(*call);
+	async_transaction_t * trans = (async_transaction_t *)buffer_hash;
+	if (trans == NULL) {
+		ipc_answer_0(callid, ENOENT);
+		return;
+	}
+	if (trans->buffer == NULL) {
+		ipc_answer_0(callid, EINVAL);
+		free(trans);
+		return;
+	}
+
+	ipc_callid_t cid;
+	size_t accepted_size;
+	if (!async_data_read_receive(&cid, &accepted_size)) {
+		ipc_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (accepted_size > trans->size) {
+		accepted_size = trans->size;
+	}
+	async_data_read_finalize(callid, trans->buffer, accepted_size);
+
+	ipc_answer_1(callid, EOK, accepted_size);
+
+	free(trans->buffer);
+	free(trans);
+}
+
+
+static void callback_out(device_t *device,
+    usb_transaction_outcome_t outcome, void *arg)
+{
+	async_transaction_t *trans = (async_transaction_t *)arg;
+
+	// FIXME - answer according to outcome
+	ipc_answer_0(trans->caller, EOK);
+
+	free(trans);
+}
+
+static void callback_in(device_t *device,
+    usb_transaction_outcome_t outcome, size_t actual_size, void *arg)
+{
+	async_transaction_t *trans = (async_transaction_t *)arg;
+
+	// FIXME - answer according to outcome
+	ipc_answer_1(trans->caller, EOK, (ipcarg_t)trans);
+
+	trans->size = actual_size;
 }
 
@@ -71,5 +128,42 @@
 	    ipc_callid_t callid, ipc_call_t *call)
 {
-	ipc_answer_0(callid, ENOTSUP);
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	size_t expected_len = IPC_GET_ARG3(*call);
+	usb_target_t target = {
+		.address = IPC_GET_ARG1(*call),
+		.endpoint = IPC_GET_ARG2(*call)
+	};
+
+	size_t len = 0;
+	void *buffer = NULL;
+	if (expected_len > 0) {
+		int rc = async_data_write_accept(&buffer, false,
+		    1, USB_MAX_PAYLOAD_SIZE,
+		    0, &len);
+
+		if (rc != EOK) {
+			ipc_answer_0(callid, rc);
+			return;
+		}
+	}
+
+	if (!usb_iface->interrupt_out) {
+		ipc_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	trans->caller = callid;
+	trans->buffer = NULL;
+	trans->size = 0;
+
+	int rc = usb_iface->interrupt_out(device, target, buffer, len,
+	    callback_out, trans);
+
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		free(trans);
+	}
 }
 
@@ -77,6 +171,32 @@
 	    ipc_callid_t callid, ipc_call_t *call)
 {
-	ipc_answer_0(callid, ENOTSUP);
-}
+	usb_iface_t *usb_iface = (usb_iface_t *) iface;
+
+	size_t len = IPC_GET_ARG3(*call);
+	usb_target_t target = {
+		.address = IPC_GET_ARG1(*call),
+		.endpoint = IPC_GET_ARG2(*call)
+	};
+
+	if (!usb_iface->interrupt_in) {
+		ipc_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	trans->caller = callid;
+	trans->buffer = malloc(len);
+	trans->size = len;
+
+	int rc = usb_iface->interrupt_in(device, target, trans->buffer, len,
+	    callback_in, trans);
+
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		free(trans->buffer);
+		free(trans);
+	}
+}
+
 
 /**
