Index: uspace/drv/usbhid/descdump.h
===================================================================
--- uspace/drv/usbhid/descdump.h	(revision dd455b1a7cea220c7a6dbf1a048e84abd0b19ac1)
+++ uspace/drv/usbhid/descdump.h	(revision 74d6e90077988a0b7d055819ba72db1778bf9bc5)
@@ -37,5 +37,5 @@
 #define USBHID_DESCDUMP_H_
 
-#include <usb/classes/hid.h>
+#include "hid.h"
 
 void dump_standard_configuration_descriptor(
Index: uspace/drv/usbhid/descparser.h
===================================================================
--- uspace/drv/usbhid/descparser.h	(revision dd455b1a7cea220c7a6dbf1a048e84abd0b19ac1)
+++ uspace/drv/usbhid/descparser.h	(revision 74d6e90077988a0b7d055819ba72db1778bf9bc5)
@@ -37,5 +37,5 @@
 #define USBHID_DESCPARSER_H_
 
-#include <usb/classes/hid.h>
+#include "hid.h"
 
 int usbkbd_parse_descriptors(const uint8_t *data, size_t size,
Index: uspace/drv/usbhid/hid.h
===================================================================
--- uspace/drv/usbhid/hid.h	(revision 74d6e90077988a0b7d055819ba72db1778bf9bc5)
+++ uspace/drv/usbhid/hid.h	(revision 74d6e90077988a0b7d055819ba72db1778bf9bc5)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * Common definitions.
+ */
+
+#ifndef USBHID_HID_H_
+#define USBHID_HID_H_
+
+#include <usb/classes/hid.h>
+#include <driver.h>
+#include <usb/pipes.h>
+
+/**
+ *
+ */
+typedef struct {
+	usb_standard_interface_descriptor_t iface_desc;
+	usb_standard_endpoint_descriptor_t *endpoints;
+	usb_standard_hid_descriptor_t hid_desc;
+	uint8_t *report_desc;
+	//usb_standard_hid_class_descriptor_info_t *class_desc_info;
+	//uint8_t **class_descs;
+} usb_hid_iface_t;
+
+/**
+ *
+ */
+typedef struct {
+	usb_standard_configuration_descriptor_t config_descriptor;
+	usb_hid_iface_t *interfaces;
+} usb_hid_configuration_t;
+
+/**
+ * @brief USB/HID keyboard device type.
+ *
+ * Quite dummy right now.
+ */
+typedef struct {
+	device_t *device;
+	usb_hid_configuration_t *conf;
+	usb_address_t address;
+	usb_hid_report_parser_t *parser;
+
+	usb_device_connection_t wire;
+	usb_endpoint_pipe_t poll_pipe;
+} usb_hid_dev_kbd_t;
+
+// TODO: more configurations!
+
+#endif
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision dd455b1a7cea220c7a6dbf1a048e84abd0b19ac1)
+++ uspace/drv/usbhid/main.c	(revision 74d6e90077988a0b7d055819ba72db1778bf9bc5)
@@ -43,4 +43,5 @@
 #include <io/console.h>
 #include <errno.h>
+#include <str_error.h>
 #include <fibril.h>
 #include <usb/classes/hid.h>
@@ -49,4 +50,5 @@
 #include <usb/descriptor.h>
 #include <io/console.h>
+#include "hid.h"
 #include "descparser.h"
 #include "descdump.h"
@@ -379,6 +381,5 @@
 	if (rc < 0) {
 		printf("Problem setting phone to HC.\n");
-		free(kbd_dev);
-		return NULL;
+		goto error_leave;
 	}
 
@@ -386,6 +387,5 @@
 	if (rc < 0) {
 		printf("Problem getting address of the device.\n");
-		free(kbd_dev);
-		return NULL;
+		goto error_leave;
 	}
 
@@ -397,7 +397,4 @@
 //	}
 
-	// default endpoint
-	kbd_dev->poll_endpoint = GUESSED_POLL_ENDPOINT;
-	
 	/*
 	 * will need all descriptors:
@@ -410,5 +407,33 @@
 	usbkbd_process_descriptors(kbd_dev);
 
+
+
+	/*
+	 * Initialize the backing connection to the host controller.
+	 */
+	rc = usb_device_connection_initialize_from_device(&kbd_dev->wire, dev);
+	if (rc != EOK) {
+		printf("Problem initializing connection to device: %s.\n",
+		    str_error(rc));
+		goto error_leave;
+	}
+
+	/*
+	 * Initialize device pipes.
+	 */
+	rc = usb_endpoint_pipe_initialize(&kbd_dev->poll_pipe, &kbd_dev->wire,
+	    GUESSED_POLL_ENDPOINT, USB_TRANSFER_INTERRUPT, USB_DIRECTION_IN);
+	if (rc != EOK) {
+		printf("Failed to initialize interrupt in pipe: %s.\n",
+		    str_error(rc));
+		goto error_leave;
+	}
+
+
 	return kbd_dev;
+
+error_leave:
+	free(kbd_dev);
+	return NULL;
 }
 
@@ -435,20 +460,7 @@
 static void usbkbd_poll_keyboard(usb_hid_dev_kbd_t *kbd_dev)
 {
-	int rc;
-	usb_handle_t handle;
+	int rc, sess_rc;
 	uint8_t buffer[BUFFER_SIZE];
 	size_t actual_size;
-	//usb_endpoint_t poll_endpoint = 1;
-
-//	usb_address_t my_address = usb_drv_get_my_address(dev->parent_phone,
-//	    dev);
-//	if (my_address < 0) {
-//		return;
-//	}
-
-	usb_target_t poll_target = {
-		.address = kbd_dev->address,
-		.endpoint = kbd_dev->poll_endpoint
-	};
 
 	printf("Polling keyboard...\n");
@@ -456,15 +468,25 @@
 	while (true) {
 		async_usleep(1000 * 1000 * 2);
-		rc = usb_drv_async_interrupt_in(kbd_dev->device->parent_phone,
-		    poll_target, buffer, BUFFER_SIZE, &actual_size, &handle);
+
+		sess_rc = usb_endpoint_pipe_start_session(&kbd_dev->poll_pipe);
+		if (sess_rc != EOK) {
+			printf("Failed to start a session: %s.\n",
+			    str_error(sess_rc));
+			continue;
+		}
+
+		rc = usb_endpoint_pipe_read(&kbd_dev->poll_pipe, buffer,
+		    BUFFER_SIZE, &actual_size);
+		sess_rc = usb_endpoint_pipe_end_session(&kbd_dev->poll_pipe);
 
 		if (rc != EOK) {
-			printf("Error in usb_drv_async_interrupt_in(): %d\n", rc);
+			printf("Error polling the keyboard: %s.\n",
+			    str_error(rc));
 			continue;
 		}
 
-		rc = usb_drv_async_wait_for(handle);
-		if (rc != EOK) {
-			printf("Error in usb_drv_async_wait_for(): %d\n", rc);
+		if (sess_rc != EOK) {
+			printf("Error closing session: %s.\n",
+			    str_error(sess_rc));
 			continue;
 		}
Index: uspace/drv/vhc/connhost.c
===================================================================
--- uspace/drv/vhc/connhost.c	(revision dd455b1a7cea220c7a6dbf1a048e84abd0b19ac1)
+++ uspace/drv/vhc/connhost.c	(revision 74d6e90077988a0b7d055819ba72db1778bf9bc5)
@@ -42,4 +42,5 @@
 #include "hc.h"
 
+
 typedef struct {
 	usb_direction_t direction;
@@ -47,11 +48,27 @@
 	usbhc_iface_transfer_in_callback_t in_callback;
 	device_t *dev;
+	size_t reported_size;
 	void *arg;
 } transfer_info_t;
 
+typedef struct {
+	usb_direction_t direction;
+	usb_target_t target;
+	usbhc_iface_transfer_out_callback_t out_callback;
+	usbhc_iface_transfer_in_callback_t in_callback;
+	device_t *dev;
+	void *arg;
+	void *data_buffer;
+	size_t data_buffer_size;
+} control_transfer_info_t;
+
 static void universal_callback(void *buffer, size_t size,
     usb_transaction_outcome_t outcome, void *arg)
 {
 	transfer_info_t *transfer = (transfer_info_t *) arg;
+
+	if (transfer->reported_size != (size_t) -1) {
+		size = transfer->reported_size;
+	}
 
 	switch (transfer->direction) {
@@ -84,4 +101,113 @@
 	transfer->arg = arg;
 	transfer->dev = dev;
+	transfer->reported_size = (size_t) -1;
+
+	return transfer;
+}
+
+static void control_abort_prematurely(control_transfer_info_t *transfer,
+    size_t size, usb_transaction_outcome_t outcome)
+{
+	switch (transfer->direction) {
+		case USB_DIRECTION_IN:
+			transfer->in_callback(transfer->dev,
+			    outcome, size,
+			    transfer->arg);
+			break;
+		case USB_DIRECTION_OUT:
+			transfer->out_callback(transfer->dev,
+			    outcome,
+			    transfer->arg);
+			break;
+		default:
+			assert(false && "unreachable");
+			break;
+	}
+}
+
+static void control_callback_two(void *buffer, size_t size,
+    usb_transaction_outcome_t outcome, void *arg)
+{
+	control_transfer_info_t *ctrl_transfer = (control_transfer_info_t *) arg;
+
+	if (outcome != USB_OUTCOME_OK) {
+		control_abort_prematurely(ctrl_transfer, outcome, size);
+		free(ctrl_transfer);
+		return;
+	}
+
+	transfer_info_t *transfer  = create_transfer_info(ctrl_transfer->dev,
+	    ctrl_transfer->direction, ctrl_transfer->arg);
+	transfer->out_callback = ctrl_transfer->out_callback;
+	transfer->in_callback = ctrl_transfer->in_callback;
+	transfer->reported_size = size;
+
+	switch (ctrl_transfer->direction) {
+		case USB_DIRECTION_IN:
+			hc_add_transaction_to_device(false, ctrl_transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    NULL, 0,
+			    universal_callback, transfer);
+			break;
+		case USB_DIRECTION_OUT:
+			hc_add_transaction_from_device(ctrl_transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    NULL, 0,
+			    universal_callback, transfer);
+			break;
+		default:
+			assert(false && "unreachable");
+			break;
+	}
+
+	free(ctrl_transfer);
+}
+
+static void control_callback_one(void *buffer, size_t size,
+    usb_transaction_outcome_t outcome, void *arg)
+{
+	control_transfer_info_t *transfer = (control_transfer_info_t *) arg;
+
+	if (outcome != USB_OUTCOME_OK) {
+		control_abort_prematurely(transfer, outcome, size);
+		free(transfer);
+		return;
+	}
+
+	switch (transfer->direction) {
+		case USB_DIRECTION_IN:
+			hc_add_transaction_from_device(transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    control_callback_two, transfer);
+			break;
+		case USB_DIRECTION_OUT:
+			hc_add_transaction_to_device(false, transfer->target,
+			    USB_TRANSFER_CONTROL,
+			    transfer->data_buffer, transfer->data_buffer_size,
+			    control_callback_two, transfer);
+			break;
+		default:
+			assert(false && "unreachable");
+			break;
+	}
+}
+
+static control_transfer_info_t *create_control_transfer_info(device_t *dev,
+    usb_direction_t direction, usb_target_t target,
+    void *data_buffer, size_t data_buffer_size,
+    void *arg)
+{
+	control_transfer_info_t *transfer
+	    = malloc(sizeof(control_transfer_info_t));
+
+	transfer->direction = direction;
+	transfer->target = target;
+	transfer->in_callback = NULL;
+	transfer->out_callback = NULL;
+	transfer->arg = arg;
+	transfer->dev = dev;
+	transfer->data_buffer = data_buffer;
+	transfer->data_buffer_size = data_buffer_size;
 
 	return transfer;
@@ -193,4 +319,21 @@
 }
 
+static int control_write(device_t *dev, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data, size_t data_size,
+    usbhc_iface_transfer_out_callback_t callback, void *arg)
+{
+	control_transfer_info_t *transfer
+	    = create_control_transfer_info(dev, USB_DIRECTION_OUT, target,
+	    data, data_size, arg);
+	transfer->out_callback = callback;
+
+	hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
+	    setup_packet, setup_packet_size,
+	    control_callback_one, transfer);
+
+	return EOK;
+}
+
 static int control_read_setup(device_t *dev, usb_target_t target,
     void *data, size_t size,
@@ -217,4 +360,21 @@
 	    NULL, 0,
 	    callback, arg);
+}
+
+static int control_read(device_t *dev, usb_target_t target,
+    void *setup_packet, size_t setup_packet_size,
+    void *data, size_t data_size,
+    usbhc_iface_transfer_in_callback_t callback, void *arg)
+{
+	control_transfer_info_t *transfer
+	    = create_control_transfer_info(dev, USB_DIRECTION_IN, target,
+	    data, data_size, arg);
+	transfer->in_callback = callback;
+
+	hc_add_transaction_to_device(true, target, USB_TRANSFER_CONTROL,
+	    setup_packet, setup_packet_size,
+	    control_callback_one, transfer);
+
+	return EOK;
 }
 
@@ -290,7 +450,11 @@
 	.control_write_status = control_write_status,
 
+	.control_write = control_write,
+
 	.control_read_setup = control_read_setup,
 	.control_read_data = control_read_data,
-	.control_read_status = control_read_status
+	.control_read_status = control_read_status,
+
+	.control_read = control_read
 };
 
