Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision f841608e9431d715f646c6aff86d5e74c14b0c2c)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision fe4dd14b607dfc4f86f5c66da2dc991b70531dd3)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010-2011 Vojtech Horky
  * All rights reserved.
  *
@@ -52,4 +52,6 @@
 static void remote_usbhc_control_read_data(device_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_control_read_status(device_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_control_write(device_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_control_read(device_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_reserve_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_release_default_address(device_t *, void *, ipc_callid_t, ipc_call_t *);
@@ -81,5 +83,8 @@
 	remote_usbhc_control_read_setup,
 	remote_usbhc_control_read_data,
-	remote_usbhc_control_read_status
+	remote_usbhc_control_read_status,
+
+	remote_usbhc_control_write,
+	remote_usbhc_control_read
 };
 
@@ -95,4 +100,5 @@
 	ipc_callid_t caller;
 	void *buffer;
+	void *setup_packet;
 	size_t size;
 } async_transaction_t;
@@ -297,4 +303,5 @@
 	trans->caller = callid;
 	trans->buffer = buffer;
+	trans->setup_packet = NULL;
 	trans->size = len;
 
@@ -336,4 +343,5 @@
 	trans->caller = callid;
 	trans->buffer = malloc(len);
+	trans->setup_packet = NULL;
 	trans->size = len;
 
@@ -391,4 +399,5 @@
 	trans->caller = callid;
 	trans->buffer = NULL;
+	trans->setup_packet = NULL;
 	trans->size = 0;
 
@@ -496,4 +505,109 @@
 }
 
+void remote_usbhc_control_write(device_t *device, void *iface,
+ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	if (!usb_iface->control_write) {
+		ipc_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+
+	int rc;
+
+	void *setup_packet = NULL;
+	void *data_buffer = NULL;
+	size_t setup_packet_len = 0;
+	size_t data_buffer_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		return;
+	}
+	rc = async_data_write_accept(&data_buffer, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &data_buffer_len);
+	if (rc != EOK) {
+		free(setup_packet);
+		ipc_answer_0(callid, rc);
+		return;
+	}
+
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	trans->caller = callid;
+	trans->setup_packet = setup_packet;
+	trans->buffer = data_buffer;
+	trans->size = data_buffer_len;
+
+	rc = usb_iface->control_write(device, target,
+	    setup_packet, setup_packet_len,
+	    data_buffer, data_buffer_len,
+	    callback_out, trans);
+
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		free(setup_packet);
+		free(data_buffer);
+		free(trans);
+	}
+}
+
+
+void remote_usbhc_control_read(device_t *device, void *iface,
+ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+	assert(usb_iface != NULL);
+
+	if (!usb_iface->control_read) {
+		ipc_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	size_t data_len = DEV_IPC_GET_ARG3(*call);
+	usb_target_t target = {
+		.address = DEV_IPC_GET_ARG1(*call),
+		.endpoint = DEV_IPC_GET_ARG2(*call)
+	};
+
+	int rc;
+
+	void *setup_packet = NULL;
+	size_t setup_packet_len = 0;
+
+	rc = async_data_write_accept(&setup_packet, false,
+	    1, USB_MAX_PAYLOAD_SIZE, 0, &setup_packet_len);
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		return;
+	}
+
+	async_transaction_t *trans = malloc(sizeof(async_transaction_t));
+	trans->caller = callid;
+	trans->setup_packet = setup_packet;
+	trans->buffer = malloc(data_len);
+	trans->size = data_len;
+
+	rc = usb_iface->control_read(device, target,
+	    setup_packet, setup_packet_len,
+	    trans->buffer, trans->size,
+	    callback_in, trans);
+
+	if (rc != EOK) {
+		ipc_answer_0(callid, rc);
+		free(setup_packet);
+		free(trans->buffer);
+		free(trans);
+	}
+}
+
 
 
