Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/Makefile	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -35,16 +35,18 @@
 	src/addrkeep.c \
 	src/class.c \
+	src/ddfiface.c \
 	src/debug.c \
 	src/dp.c \
-	src/drvpsync.c \
-	src/hcdhubd.c \
-	src/hcdrv.c \
+	src/dump.c \
 	src/hidparser.c \
-	src/localdrv.c \
+	src/hub.c \
+	src/pipes.c \
+	src/pipesinit.c \
+	src/pipesio.c \
 	src/recognise.c \
-	src/remotedrv.c \
+	src/request.c \
 	src/usb.c \
-	src/usbdrvreq.c \
-	src/usbdrv.c
+	src/usbdevice.c \
+	src/usbmem.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/lib/usb/include/usb/addrkeep.h
===================================================================
--- uspace/lib/usb/include/usb/addrkeep.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/addrkeep.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2010 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB address keeping for host controller drivers.
+ */
+#ifndef LIBUSB_ADDRKEEP_H_
+#define LIBUSB_ADDRKEEP_H_
+
+#include <usb/usb.h>
+#include <fibril_synch.h>
+#include <devman.h>
+
+/** Info about used address. */
+typedef struct {
+	/** Linked list member. */
+	link_t link;
+	/** Address. */
+	usb_address_t address;
+	/** Corresponding devman handle. */
+	devman_handle_t devman_handle;
+} usb_address_keeping_used_t;
+
+/** Structure for keeping track of free and used USB addresses. */
+typedef struct {
+	/** Head of list of used addresses. */
+	link_t used_addresses;
+	/** Upper bound for USB addresses. */
+	usb_address_t max_address;
+	/** Mutex protecting used address. */
+	fibril_mutex_t used_addresses_guard;
+	/** Condition variable for used addresses. */
+	fibril_condvar_t used_addresses_condvar;
+
+	/** Condition variable mutex for default address. */
+	fibril_mutex_t default_condvar_guard;
+	/** Condition variable for default address. */
+	fibril_condvar_t default_condvar;
+	/** Whether is default address available. */
+	bool default_available;
+} usb_address_keeping_t;
+
+void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
+
+void usb_address_keeping_reserve_default(usb_address_keeping_t *);
+void usb_address_keeping_release_default(usb_address_keeping_t *);
+
+usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
+int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
+void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
+    devman_handle_t);
+usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
+    devman_handle_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/classes/classes.h
===================================================================
--- uspace/lib/usb/include/usb/classes/classes.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/classes.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/include/usb/classes/hid.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hid.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hid.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -37,6 +37,6 @@
 
 #include <usb/usb.h>
-#include <driver.h>
 #include <usb/classes/hidparser.h>
+#include <usb/descriptor.h>
 
 /** USB/HID device requests. */
@@ -51,4 +51,21 @@
 } usb_hid_request_t;
 
+typedef enum {
+	USB_HID_REPORT_TYPE_INPUT = 1,
+	USB_HID_REPORT_TYPE_OUTPUT = 2,
+	USB_HID_REPORT_TYPE_FEATURE = 3
+} usb_hid_report_type_t;
+
+typedef enum {
+	USB_HID_PROTOCOL_BOOT = 0,
+	USB_HID_PROTOCOL_REPORT = 1
+} usb_hid_protocol_t;
+
+/** USB/HID subclass constants. */
+typedef enum {
+	USB_HID_SUBCLASS_NONE = 0,
+	USB_HID_SUBCLASS_BOOT = 1
+} usb_hid_subclass_t;
+
 /** USB/HID interface protocols. */
 typedef enum {
@@ -56,5 +73,5 @@
 	USB_HID_PROTOCOL_KEYBOARD = 1,
 	USB_HID_PROTOCOL_MOUSE = 2
-} usb_hid_protocol_t;
+} usb_hid_iface_protocol_t;
 
 /** Part of standard USB HID descriptor specifying one class descriptor.
@@ -63,9 +80,9 @@
  */
 typedef struct {
-	/** Type of class descriptor (Report or Physical). */
-	uint8_t class_descriptor_type;
-	/** Length of class descriptor. */
-	uint16_t class_descriptor_length;
-} __attribute__ ((packed)) usb_standard_hid_descriptor_class_item_t;
+	/** Type of class-specific descriptor (Report or Physical). */
+	uint8_t type;
+	/** Length of class-specific descriptor in bytes. */
+	uint16_t length;
+} __attribute__ ((packed)) usb_standard_hid_class_descriptor_info_t;
 
 /** Standard USB HID descriptor.
@@ -73,9 +90,14 @@
  * (See HID Specification, p.22)
  * 
- * It is actually only the "header" of the descriptor, as it may have arbitrary
- * length if more than one class descritor is provided.
+ * It is actually only the "header" of the descriptor, it does not contain
+ * the last two mandatory fields (type and length of the first class-specific
+ * descriptor).
  */
 typedef struct {
-	/** Size of this descriptor in bytes. */
+	/** Total size of this descriptor in bytes. 
+	 *
+	 * This includes all class-specific descriptor info - type + length 
+	 * for each descriptor.
+	 */
 	uint8_t length;
 	/** Descriptor type (USB_DESCTYPE_HID). */
@@ -85,22 +107,14 @@
 	/** Country code of localized hardware. */
 	uint8_t country_code;
-	/** Total number of class (i.e. Report and Physical) descriptors. */
-	uint8_t class_count;
-	/** First mandatory class descriptor info. */
-	usb_standard_hid_descriptor_class_item_t class_descriptor;
+	/** Total number of class-specific (i.e. Report and Physical) 
+	 * descriptors. 
+	 *
+	 * @note There is always only one Report descriptor.
+	 */
+	uint8_t class_desc_count;
+	/** First mandatory class descriptor (Report) info. */
+	usb_standard_hid_class_descriptor_info_t report_desc_info;
 } __attribute__ ((packed)) usb_standard_hid_descriptor_t;
 
-
-/**
- * @brief USB/HID keyboard device type.
- *
- * Quite dummy right now.
- */
-typedef struct {
-	device_t *device;
-	usb_address_t address;
-	usb_endpoint_t poll_endpoint;
-	usb_hid_report_parser_t *parser;
-} usb_hid_dev_kbd_t;
 
 #endif
Index: uspace/lib/usb/include/usb/classes/hidparser.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidparser.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hidparser.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,10 +37,7 @@
 
 #include <stdint.h>
-#include <adt/list.h>
-
-#include <hid_report_items.h>
 
 /**
- * Items prefix
+ * Item prefix
  */
 #define USB_HID_ITEM_SIZE(data) 	((uint8_t)(data & 0x3))
@@ -62,24 +59,4 @@
 #define USB_HID_ITEM_FLAG_VOLATILE(flags)	(flags & 0x80)
 #define USB_HID_ITEM_FLAG_BUFFERED(flags)	(flags & 0x100)
-
-
-/**
- * Collection Item Types
- */
-#define USB_HID_COLLECTION_TYPE_PHYSICAL		0x00
-#define USB_HID_COLLECTION_TYPE_APPLICATION		0x01
-#define USB_HID_COLLECTION_TYPE_LOGICAL			0x02
-#define USB_HID_COLLECTION_TYPE_REPORT			0x03
-#define USB_HID_COLLECTION_TYPE_NAMED_ARRAY		0x04
-#define USB_HID_COLLECTION_TYPE_USAGE_SWITCH	0x05
-
-/*
- * modifiers definitions
- */
-#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
-#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
-#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
-#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
-#define USB_HID_BOOT_KEYBOARD_KANA			0x10
 
 
@@ -128,4 +105,5 @@
 
 
+
 /** HID parser callbacks for IN items. */
 typedef struct {
@@ -139,9 +117,60 @@
 } usb_hid_report_in_callbacks_t;
 
+
+typedef enum {
+	USB_HID_MOD_LCTRL = 0x01,
+	USB_HID_MOD_LSHIFT = 0x02,
+	USB_HID_MOD_LALT = 0x04,
+	USB_HID_MOD_LGUI = 0x08,
+	USB_HID_MOD_RCTRL = 0x10,
+	USB_HID_MOD_RSHIFT = 0x20,
+	USB_HID_MOD_RALT = 0x40,
+	USB_HID_MOD_RGUI = 0x80,
+	USB_HID_MOD_COUNT = 8
+} usb_hid_modifiers_t;
+
+typedef enum {
+	USB_HID_LED_NUM_LOCK = 0x1,
+	USB_HID_LED_CAPS_LOCK = 0x2,
+	USB_HID_LED_SCROLL_LOCK = 0x4,
+	USB_HID_LED_COMPOSE = 0x8,
+	USB_HID_LED_KANA = 0x10,
+	USB_HID_LED_COUNT = 5
+} usb_hid_led_t;
+
+static const usb_hid_modifiers_t 
+    usb_hid_modifiers_consts[USB_HID_MOD_COUNT] = {
+	USB_HID_MOD_LCTRL,
+	USB_HID_MOD_LSHIFT,
+	USB_HID_MOD_LALT,
+	USB_HID_MOD_LGUI,
+	USB_HID_MOD_RCTRL,
+	USB_HID_MOD_RSHIFT,
+	USB_HID_MOD_RALT,
+	USB_HID_MOD_RGUI
+};
+
+//static const usb_hid_led_t usb_hid_led_consts[USB_HID_LED_COUNT] = {
+//	USB_HID_LED_NUM_LOCK,
+//	USB_HID_LED_CAPS_LOCK,
+//	USB_HID_LED_SCROLL_LOCK,
+//	USB_HID_LED_COMPOSE,
+//	USB_HID_LED_KANA
+//};
+
+//#define USB_HID_BOOT_KEYBOARD_NUM_LOCK		0x01
+//#define USB_HID_BOOT_KEYBOARD_CAPS_LOCK		0x02
+//#define USB_HID_BOOT_KEYBOARD_SCROLL_LOCK	0x04
+//#define USB_HID_BOOT_KEYBOARD_COMPOSE		0x08
+//#define USB_HID_BOOT_KEYBOARD_KANA			0x10
+
+/*
+ * modifiers definitions
+ */
+
 int usb_hid_boot_keyboard_input_report(const uint8_t *data, size_t size,
 	const usb_hid_report_in_callbacks_t *callbacks, void *arg);
 
 int usb_hid_boot_keyboard_output_report(uint8_t leds, uint8_t *data, size_t size);
-
 
 int usb_hid_parser_init(usb_hid_report_parser_t *parser);
@@ -157,4 +186,5 @@
 
 void usb_hid_descriptor_print(usb_hid_report_parser_t *parser);
+
 #endif
 /**
Index: uspace/lib/usb/include/usb/classes/hidut.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidut.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hidut.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/include/usb/classes/hidutkbd.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hidutkbd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hidutkbd.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010 Matus Dekanek
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -33,10 +33,8 @@
  * @brief USB hub related structures.
  */
-#ifndef LIBUSB_HUB_H_
-#define LIBUSB_HUB_H_
+#ifndef LIBUSB_CLASS_HUB_H_
+#define LIBUSB_CLASS_HUB_H_
 
 #include <sys/types.h>
-#include <usb/hcdhubd.h>
-
 
 /** Hub class feature selector.
@@ -68,5 +66,5 @@
  *	For more information see Universal Serial Bus Specification Revision 1.1 chapter 11.16.2
  */
-typedef struct hub_descriptor_type{
+typedef struct usb_hub_descriptor_type {
     /** Number of bytes in this descriptor, including this byte */
     //uint8_t bDescLength;
@@ -80,5 +78,5 @@
     /**
             D1...D0: Logical Power Switching Mode
-            00: Ganged power switching (all ports’ power at
+            00: Ganged power switching (all ports power at
             once)
             01: Individual port power switching
@@ -91,5 +89,5 @@
             00: Global Over-current Protection. The hub
             reports over-current as a summation of all
-            ports’ current draw, without a breakdown of
+            ports current draw, without a breakdown of
             individual port over-current status.
             01: Individual Port Over-current Protection. The
@@ -198,19 +196,4 @@
 extern size_t USB_HUB_MAX_DESCRIPTOR_SIZE;
 
-/**
- * @brief create uint8_t array with serialized descriptor
- *
- * @param descriptor
- */
-void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor);
-
-/**
- * @brief create deserialized desriptor structure out of serialized descriptor
- *
- * The serialized descriptor must be proper usb hub descriptor, otherwise an eerror might occur.
- *
- * @param sdescriptor serialized descriptor
- */
-usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * sdescriptor);
 
 
Index: uspace/lib/usb/include/usb/ddfiface.h
===================================================================
--- uspace/lib/usb/include/usb/ddfiface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/ddfiface.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions.
+ */
+#ifndef LIBUSB_DDFIFACE_H_
+#define LIBUSB_DDFIFACE_H_
+
+#include <sys/types.h>
+#include <usb/usbdevice.h>
+#include <usb_iface.h>
+
+int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_address_hub_impl(ddf_fun_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_impl;
+
+int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *, devman_handle_t *);
+int usb_iface_get_address_hub_child_impl(ddf_fun_t *, devman_handle_t,
+    usb_address_t *);
+extern usb_iface_t usb_iface_hub_child_impl;
+
+int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *, devman_handle_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/debug.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010-2011 Vojtech Horky
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -35,8 +35,53 @@
 #ifndef LIBUSB_DEBUG_H_
 #define LIBUSB_DEBUG_H_
+#include <stdio.h>
+#include <usb/usb.h>
+#include <assert.h>
 
 void usb_dprintf(const char *tag, int level, const char *format, ...);
 void usb_dprintf_enable(const char *tag, int level);
 
+void usb_dump_standard_descriptor(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+
+/** Logging level. */
+typedef enum {
+	USB_LOG_LEVEL_FATAL,
+	USB_LOG_LEVEL_ERROR,
+	USB_LOG_LEVEL_WARNING,
+	USB_LOG_LEVEL_INFO,
+	USB_LOG_LEVEL_DEBUG,
+	USB_LOG_LEVEL_DEBUG2,
+	USB_LOG_LEVEL_MAX
+} usb_log_level_t;
+
+
+void usb_log_enable(usb_log_level_t, const char *);
+
+void usb_log_printf(usb_log_level_t, const char *, ...);
+
+#define usb_log_fatal(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_FATAL, format, ##__VA_ARGS__)
+
+#define usb_log_error(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_ERROR, format, ##__VA_ARGS__)
+
+#define usb_log_warning(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_WARNING, format, ##__VA_ARGS__)
+
+#define usb_log_info(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_INFO, format, ##__VA_ARGS__)
+
+#define usb_log_debug(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_DEBUG, format, ##__VA_ARGS__)
+
+#define usb_log_debug2(format, ...) \
+	usb_log_printf(USB_LOG_LEVEL_DEBUG2, format, ##__VA_ARGS__)
+
+
 
 #endif
+/**
+ * @}
+ */
+
Index: uspace/lib/usb/include/usb/descriptor.h
===================================================================
--- uspace/lib/usb/include/usb/descriptor.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/descriptor.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -36,5 +36,4 @@
 #define LIBUSB_DESCRIPTOR_H_
 
-#include <ipc/ipc.h>
 #include <async.h>
 
Index: uspace/lib/usb/include/usb/devreq.h
===================================================================
--- uspace/lib/usb/include/usb/devreq.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,113 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Standard USB device requests.
- */
-#ifndef LIBUSB_DEVREQ_H_
-#define LIBUSB_DEVREQ_H_
-
-#include <ipc/ipc.h>
-#include <async.h>
-#include <usb/usb.h>
-#include <usb/descriptor.h>
-
-/** Standard device request. */
-typedef enum {
-	USB_DEVREQ_GET_STATUS = 0,
-	USB_DEVREQ_CLEAR_FEATURE = 1,
-	USB_DEVREQ_SET_FEATURE = 3,
-	USB_DEVREQ_SET_ADDRESS = 5,
-	USB_DEVREQ_GET_DESCRIPTOR = 6,
-	USB_DEVREQ_SET_DESCRIPTOR = 7,
-	USB_DEVREQ_GET_CONFIGURATION = 8,
-	USB_DEVREQ_SET_CONFIGURATION = 9,
-	USB_DEVREQ_GET_INTERFACE = 10,
-	USB_DEVREQ_SET_INTERFACE = 11,
-	USB_DEVREQ_SYNCH_FRAME = 12,
-	USB_DEVREQ_LAST_STD
-} usb_stddevreq_t;
-
-/** Device request setup packet.
- * The setup packet describes the request.
- */
-typedef struct {
-	/** Request type.
-	 * The type combines transfer direction, request type and
-	 * intended recipient.
-	 */
-	uint8_t request_type;
-	/** Request identification. */
-	uint8_t request;
-	/** Main parameter to the request. */
-	union {
-		/* FIXME: add #ifdefs according to host endianess */
-		struct {
-			uint8_t value_low;
-			uint8_t value_high;
-		};
-		uint16_t value;
-	};
-	/** Auxiliary parameter to the request.
-	 * Typically, it is offset to something.
-	 */
-	uint16_t index;
-	/** Length of extra data. */
-	uint16_t length;
-} __attribute__ ((packed)) usb_device_request_setup_packet_t;
-
-
-int usb_drv_req_get_status(int, usb_address_t, usb_request_recipient_t,
-    uint16_t, uint16_t *);
-int usb_drv_req_clear_feature(int, usb_address_t, usb_request_recipient_t,
-    uint16_t, uint16_t);
-int usb_drv_req_set_feature(int, usb_address_t, usb_request_recipient_t,
-    uint16_t, uint16_t);
-int usb_drv_req_set_address(int, usb_address_t, usb_address_t);
-int usb_drv_req_get_descriptor(int, usb_address_t, usb_request_type_t,
-    uint8_t, uint8_t, uint16_t, void *, size_t, size_t *);
-int usb_drv_req_get_device_descriptor(int, usb_address_t,
-    usb_standard_device_descriptor_t *);
-int usb_drv_req_get_bare_configuration_descriptor(int, usb_address_t, int,
-    usb_standard_configuration_descriptor_t *);
-int usb_drv_req_get_full_configuration_descriptor(int, usb_address_t, int,
-    void *, size_t, size_t *);
-int usb_drv_req_set_descriptor(int, usb_address_t, uint8_t, uint8_t, uint16_t,
-    void *, size_t);
-int usb_drv_req_get_configuration(int, usb_address_t, uint8_t *);
-int usb_drv_req_set_configuration(int, usb_address_t, uint8_t);
-int usb_drv_req_get_interface(int, usb_address_t, uint16_t, uint8_t *);
-int usb_drv_req_set_interface(int, usb_address_t, uint16_t, uint8_t);
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/include/usb/dp.h
===================================================================
--- uspace/lib/usb/include/usb/dp.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/dp.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -45,4 +45,6 @@
 } usb_dp_descriptor_nesting_t;
 
+extern usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[];
+
 typedef struct {
 	usb_dp_descriptor_nesting_t *nesting;
Index: uspace/lib/usb/include/usb/hcd.h
===================================================================
--- uspace/lib/usb/include/usb/hcd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,84 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief HC driver.
- */
-#ifndef LIBUSB_HCD_H_
-#define LIBUSB_HCD_H_
-
-#include <usb/usb.h>
-#include <fibril_synch.h>
-#include <devman.h>
-
-/** Info about used address. */
-typedef struct {
-	/** Linked list member. */
-	link_t link;
-	/** Address. */
-	usb_address_t address;
-	/** Corresponding devman handle. */
-	devman_handle_t devman_handle;
-} usb_address_keeping_used_t;
-
-/** Structure for keeping track of free and used USB addresses. */
-typedef struct {
-	/** Head of list of used addresses. */
-	link_t used_addresses;
-	/** Upper bound for USB addresses. */
-	usb_address_t max_address;
-	/** Mutex protecting used address. */
-	fibril_mutex_t used_addresses_guard;
-	/** Condition variable for used addresses. */
-	fibril_condvar_t used_addresses_condvar;
-
-	/** Condition variable mutex for default address. */
-	fibril_mutex_t default_condvar_guard;
-	/** Condition variable for default address. */
-	fibril_condvar_t default_condvar;
-	/** Whether is default address available. */
-	bool default_available;
-} usb_address_keeping_t;
-
-void usb_address_keeping_init(usb_address_keeping_t *, usb_address_t);
-
-void usb_address_keeping_reserve_default(usb_address_keeping_t *);
-void usb_address_keeping_release_default(usb_address_keeping_t *);
-
-usb_address_t usb_address_keeping_request(usb_address_keeping_t *);
-int usb_address_keeping_release(usb_address_keeping_t *, usb_address_t);
-void usb_address_keeping_devman_bind(usb_address_keeping_t *, usb_address_t,
-    devman_handle_t);
-usb_address_t usb_address_keeping_find(usb_address_keeping_t *,
-    devman_handle_t);
-
-
-#endif
Index: uspace/lib/usb/include/usb/hcdhubd.h
===================================================================
--- uspace/lib/usb/include/usb/hcdhubd.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,214 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief HC driver and hub driver.
- */
-#ifndef LIBUSB_HCDHUBD_H_
-#define LIBUSB_HCDHUBD_H_
-
-#include <adt/list.h>
-#include <bool.h>
-#include <driver.h>
-#include <usb/usb.h>
-
-/** Endpoint properties. */
-typedef struct {
-	/** Endpoint number. */
-	usb_endpoint_t endpoint;
-	/** Transfer type. */
-	usb_transfer_type_t transfer_type;
-	/** Endpoint direction. */
-	usb_direction_t direction;
-	/** Data toggle bit. */
-	int data_toggle;
-} usb_hc_endpoint_info_t;
-
-/** Information about attached USB device. */
-typedef struct {
-	/** Assigned address. */
-	usb_address_t address;
-	/** Number of endpoints. */
-	size_t endpoint_count;
-	/** Endpoint properties. */
-	usb_hc_endpoint_info_t *endpoints;
-	/** Link to other attached devices of the same HC. */
-	link_t link;
-} usb_hcd_attached_device_info_t;
-
-
-/** Host controller device. */
-typedef struct usb_hc_device usb_hc_device_t;
-
-/** Callback for OUT transfers. */
-typedef void (*usb_hcd_transfer_callback_out_t)
-    (usb_hc_device_t *, usb_transaction_outcome_t, void *);
-
-/** Callback for IN transfers. */
-typedef void (*usb_hcd_transfer_callback_in_t)
-    (usb_hc_device_t *, size_t, usb_transaction_outcome_t, void *);
-
-
-/** Transfer functions provided by each USB host controller driver. */
-typedef struct {
-	/** OUT transfer.
-	 * @param hc Host controller that shall enqueue the transfer.
-	 * @param dev Target device.
-	 * @param ep Target endpoint.
-	 * @param buffer Buffer to be sent.
-	 * @param size Buffer size.
-	 * @param callback Callback after transfer was processed by hardware.
-	 * @param arg Callback argument.
-	 */
-	int (*transfer_out)(usb_hc_device_t *hc,
-	    usb_hcd_attached_device_info_t *dev, usb_hc_endpoint_info_t *ep,
-	    void *buffer, size_t size,
-	    usb_hcd_transfer_callback_out_t callback, void *arg);
-
-	/** SETUP transfer. */
-	int (*transfer_setup)(usb_hc_device_t *,
-	    usb_hcd_attached_device_info_t *, usb_hc_endpoint_info_t *,
-	    void *, size_t,
-	    usb_hcd_transfer_callback_out_t, void *);
-
-	/** IN transfer. */
-	int (*transfer_in)(usb_hc_device_t *,
-	    usb_hcd_attached_device_info_t *, usb_hc_endpoint_info_t *,
-	    void *, size_t,
-	    usb_hcd_transfer_callback_in_t, void *);
-} usb_hcd_transfer_ops_t;
-
-/**
- * @brief structure holding information about free and used addresses
- *
- * This structure should not be used outside usb hcd driver.
- * You better consider it to be 'private'.
- */
-typedef struct {
-	/** lower bound included in the interval */
-	usb_address_t lower_bound;
-
-	/** upper bound, excluded from the interval */
-	usb_address_t upper_bound;
-
-	/** */
-	link_t link;
-}usb_address_list_t;
-
-struct usb_hc_device {
-	/** Transfer operations. */
-	usb_hcd_transfer_ops_t *transfer_ops;
-
-	/** Custom HC data. */
-	void *data;
-
-	/** Generic device entry (read-only). */
-	device_t *generic;
-
-	/** List of attached devices. */
-	link_t attached_devices;
-
-	/** List of hubs operating from this HC. */
-	link_t hubs;
-
-	/** Structure with free and used addresses */
-	link_t addresses;
-
-	/** Link to other driven HCs. */
-	link_t link;
-};
-
-/** Host controller driver. */
-typedef struct {
-	/** Driver name. */
-	const char *name;
-	/** Callback when device (host controller) is added. */
-	int (*add_hc)(usb_hc_device_t *device);
-} usb_hc_driver_t;
-
-
-int usb_hcd_main(usb_hc_driver_t *);
-int usb_hcd_add_root_hub(device_t *dev);
-
-/**
- * find first not yet used address on this host controller and use it
- * @param this_hcd
- * @return number in the range of allowed usb addresses or
- *     a negative number if not succesful
- */
-usb_address_t usb_use_free_address(usb_hc_device_t * this_hcd);
-
-/**
- * @brief free the address in the address space of this hcd.
- *
- * if address is not used, nothing happens
- * @param this_hcd
- * @param addr
- */
-void usb_free_used_address(usb_hc_device_t * this_hcd, usb_address_t addr );
-
-
-/*
- * Functions to be used by drivers within same task as the HC driver.
- * This will probably include only hub drivers.
- */
-
-device_t *usb_hc_connect(device_t *);
-
-int usb_hc_async_interrupt_out(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_interrupt_in(usb_hc_device_t *, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-
-int usb_hc_async_control_write_setup(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_write_data(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_write_status(usb_hc_device_t *, usb_target_t,
-    usb_handle_t *);
-
-int usb_hc_async_control_read_setup(usb_hc_device_t *, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_hc_async_control_read_data(usb_hc_device_t *, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-int usb_hc_async_control_read_status(usb_hc_device_t *, usb_target_t,
-    usb_handle_t *);
-
-int usb_hc_async_wait_for(usb_handle_t);
-
-int usb_hc_add_child_device(device_t *, const char *, const char *, bool);
-
-
-/**
- * @}
- */
-
-#endif
Index: uspace/lib/usb/include/usb/hub.h
===================================================================
--- uspace/lib/usb/include/usb/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/hub.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Functions needed by hub drivers.
+ */
+#ifndef LIBUSB_HUB_H_
+#define LIBUSB_HUB_H_
+
+#include <sys/types.h>
+#include <usb/usbdevice.h>
+
+int usb_hc_new_device_wrapper(ddf_dev_t *, usb_hc_connection_t *, usb_speed_t,
+    int (*)(int, void *), int, void *,
+    usb_address_t *, devman_handle_t *,
+    ddf_dev_ops_t *, void *, ddf_fun_t **);
+
+/** Info about device attached to host controller.
+ *
+ * This structure exists only to keep the same signature of
+ * usb_hc_register_device() when more properties of the device
+ * would have to be passed to the host controller.
+ */
+typedef struct {
+	/** Device address. */
+	usb_address_t address;
+	/** Devman handle of the device. */
+	devman_handle_t handle;
+} usb_hc_attached_device_t;
+
+int usb_hc_reserve_default_address(usb_hc_connection_t *, usb_speed_t);
+int usb_hc_release_default_address(usb_hc_connection_t *);
+
+usb_address_t usb_hc_request_address(usb_hc_connection_t *, usb_speed_t);
+int usb_hc_register_device(usb_hc_connection_t *,
+    const usb_hc_attached_device_t *);
+int usb_hc_unregister_device(usb_hc_connection_t *, usb_address_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/pipes.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB pipes representation.
+ */
+#ifndef LIBUSB_PIPES_H_
+#define LIBUSB_PIPES_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/usbdevice.h>
+#include <usb/descriptor.h>
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+
+/**
+ * Abstraction of a physical connection to the device.
+ * This type is an abstraction of the USB wire that connects the host and
+ * the function (device).
+ */
+typedef struct {
+	/** Handle of the host controller device is connected to. */
+	devman_handle_t hc_handle;
+	/** Address of the device. */
+	usb_address_t address;
+} usb_device_connection_t;
+
+/**
+ * Abstraction of a logical connection to USB device endpoint.
+ * It encapsulates endpoint attributes (transfer type etc.) as well
+ * as information about currently running sessions.
+ * This endpoint must be bound with existing usb_device_connection_t
+ * (i.e. the wire to send data over).
+ */
+typedef struct {
+	/** The connection used for sending the data. */
+	usb_device_connection_t *wire;
+
+	/** Endpoint number. */
+	usb_endpoint_t endpoint_no;
+
+	/** Endpoint transfer type. */
+	usb_transfer_type_t transfer_type;
+
+	/** Endpoint direction. */
+	usb_direction_t direction;
+
+	/** Maximum packet size for the endpoint. */
+	size_t max_packet_size;
+
+	/** Phone to the host controller.
+	 * Negative when no session is active.
+	 */
+	int hc_phone;
+} usb_endpoint_pipe_t;
+
+
+/** Description of endpoint characteristics. */
+typedef struct {
+	/** Transfer type (e.g. control or interrupt). */
+	usb_transfer_type_t transfer_type;
+	/** Transfer direction (to or from a device). */
+	usb_direction_t direction;
+	/** Interface class this endpoint belongs to (-1 for any). */
+	int interface_class;
+	/** Interface subclass this endpoint belongs to (-1 for any). */
+	int interface_subclass;
+	/** Interface protocol this endpoint belongs to (-1 for any). */
+	int interface_protocol;
+	/** Extra endpoint flags. */
+	unsigned int flags;
+} usb_endpoint_description_t;
+
+/** Mapping of endpoint pipes and endpoint descriptions. */
+typedef struct {
+	/** Endpoint pipe. */
+	usb_endpoint_pipe_t *pipe;
+	/** Endpoint description. */
+	const usb_endpoint_description_t *description;
+	/** Interface number the endpoint must belong to (-1 for any). */
+	const int interface_no;
+	/** Found descriptor fitting the description. */
+	usb_standard_endpoint_descriptor_t *descriptor;
+	/** Interface the endpoint belongs to. */
+	usb_standard_interface_descriptor_t *interface;
+	/** Whether the endpoint was actually found. */
+	bool present;
+} usb_endpoint_mapping_t;
+
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *, usb_hc_connection_t *);
+int usb_device_connection_initialize_from_device(usb_device_connection_t *,
+    ddf_dev_t *);
+int usb_device_connection_initialize(usb_device_connection_t *,
+    devman_handle_t, usb_address_t);
+
+int usb_device_get_assigned_interface(ddf_dev_t *);
+
+int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *,
+    usb_device_connection_t *,
+    usb_endpoint_t, usb_transfer_type_t, size_t, usb_direction_t);
+int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *,
+    usb_device_connection_t *);
+int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
+    size_t, uint8_t *, size_t, usb_device_connection_t *);
+
+
+int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
+int usb_endpoint_pipe_end_session(usb_endpoint_pipe_t *);
+bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *);
+
+int usb_endpoint_pipe_read(usb_endpoint_pipe_t *, void *, size_t, size_t *);
+int usb_endpoint_pipe_write(usb_endpoint_pipe_t *, void *, size_t);
+
+int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *, void *, size_t,
+    void *, size_t, size_t *);
+int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *, void *, size_t,
+    void *, size_t);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/recognise.h
===================================================================
--- uspace/lib/usb/include/usb/recognise.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/recognise.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB device recognition.
+ */
+#ifndef LIBUSB_RECOGNISE_H_
+#define LIBUSB_RECOGNISE_H_
+
+#include <sys/types.h>
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <ipc/devman.h>
+
+int usb_device_create_match_ids_from_device_descriptor(
+    const usb_standard_device_descriptor_t *, match_id_list_t *);
+
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *,
+    const usb_standard_interface_descriptor_t *, match_id_list_t *);
+
+int usb_device_create_match_ids(usb_endpoint_pipe_t *, match_id_list_t *);
+
+int usb_device_register_child_in_devman(usb_address_t, devman_handle_t,
+    ddf_dev_t *, devman_handle_t *, ddf_dev_ops_t *, void *, ddf_fun_t **);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/request.h
===================================================================
--- uspace/lib/usb/include/usb/request.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/request.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Standard USB requests.
+ */
+#ifndef LIBUSB_REQUEST_H_
+#define LIBUSB_REQUEST_H_
+
+#include <sys/types.h>
+#include <l18n/langs.h>
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/descriptor.h>
+
+/** Standard device request. */
+typedef enum {
+	USB_DEVREQ_GET_STATUS = 0,
+	USB_DEVREQ_CLEAR_FEATURE = 1,
+	USB_DEVREQ_SET_FEATURE = 3,
+	USB_DEVREQ_SET_ADDRESS = 5,
+	USB_DEVREQ_GET_DESCRIPTOR = 6,
+	USB_DEVREQ_SET_DESCRIPTOR = 7,
+	USB_DEVREQ_GET_CONFIGURATION = 8,
+	USB_DEVREQ_SET_CONFIGURATION = 9,
+	USB_DEVREQ_GET_INTERFACE = 10,
+	USB_DEVREQ_SET_INTERFACE = 11,
+	USB_DEVREQ_SYNCH_FRAME = 12,
+	USB_DEVREQ_LAST_STD
+} usb_stddevreq_t;
+
+/** Device request setup packet.
+ * The setup packet describes the request.
+ */
+typedef struct {
+	/** Request type.
+	 * The type combines transfer direction, request type and
+	 * intended recipient.
+	 */
+	uint8_t request_type;
+	/** Request identification. */
+	uint8_t request;
+	/** Main parameter to the request. */
+	union {
+		uint16_t value;
+		/* FIXME: add #ifdefs according to host endianess */
+		struct {
+			uint8_t value_low;
+			uint8_t value_high;
+		};
+	};
+	/** Auxiliary parameter to the request.
+	 * Typically, it is offset to something.
+	 */
+	uint16_t index;
+	/** Length of extra data. */
+	uint16_t length;
+} __attribute__ ((packed)) usb_device_request_setup_packet_t;
+
+int usb_control_request_set(usb_endpoint_pipe_t *,
+    usb_request_type_t, usb_request_recipient_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t);
+
+int usb_control_request_get(usb_endpoint_pipe_t *,
+    usb_request_type_t, usb_request_recipient_t, uint8_t,
+    uint16_t, uint16_t, void *, size_t, size_t *);
+
+int usb_request_set_address(usb_endpoint_pipe_t *, usb_address_t);
+int usb_request_get_descriptor(usb_endpoint_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void *, size_t, 
+    size_t *);
+int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t *, usb_request_type_t,
+    usb_request_recipient_t, uint8_t, uint8_t, uint16_t, void **, size_t *);
+int usb_request_get_device_descriptor(usb_endpoint_pipe_t *,
+    usb_standard_device_descriptor_t *);
+int usb_request_get_bare_configuration_descriptor(usb_endpoint_pipe_t *, int,
+    usb_standard_configuration_descriptor_t *);
+int usb_request_get_full_configuration_descriptor(usb_endpoint_pipe_t *, int,
+    void *, size_t, size_t *);
+int usb_request_set_configuration(usb_endpoint_pipe_t *, uint8_t);
+
+int usb_request_get_supported_languages(usb_endpoint_pipe_t *,
+    l18_win_locales_t **, size_t *);
+int usb_request_get_string(usb_endpoint_pipe_t *, size_t, l18_win_locales_t,
+    char **);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/usb.h
===================================================================
--- uspace/lib/usb/include/usb/usb.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/include/usb/usb.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -37,5 +37,18 @@
 
 #include <sys/types.h>
-#include <ipc/ipc.h>
+#include <byteorder.h>
+
+/** Convert 16bit value from native (host) endianness to USB endianness. */
+#define uint16_host2usb(n) host2uint16_t_le((n))
+
+/** Convert 32bit value from native (host) endianness to USB endianness. */
+#define uint32_host2usb(n) host2uint32_t_le((n))
+
+/** Convert 16bit value from USB endianness into native (host) one. */
+#define uint16_usb2host(n) uint16_t_le2host((n))
+
+/** Convert 32bit value from USB endianness into native (host) one. */
+#define uint32_usb2host(n) uint32_t_le2host((n))
+
 
 /** USB transfer type. */
@@ -52,6 +65,17 @@
 typedef enum {
 	USB_DIRECTION_IN,
-	USB_DIRECTION_OUT
+	USB_DIRECTION_OUT,
+	USB_DIRECTION_BOTH
 } usb_direction_t;
+
+/** USB speeds. */
+typedef enum {
+	/** USB 1.1 low speed (1.5Mbits/s). */
+	USB_SPEED_LOW,
+	/** USB 1.1 full speed (12Mbits/s). */
+	USB_SPEED_FULL,
+	/** USB 2.0 high speed (480Mbits/s). */
+	USB_SPEED_HIGH
+} usb_speed_t;
 
 /** USB request type target. */
@@ -68,13 +92,4 @@
 	USB_REQUEST_RECIPIENT_ENDPOINT = 2
 } usb_request_recipient_t;
-
-/** USB transaction outcome. */
-typedef enum {
-	USB_OUTCOME_OK,
-	USB_OUTCOME_CRCERROR,
-	USB_OUTCOME_BABBLE
-} usb_transaction_outcome_t;
-
-const char * usb_str_transaction_outcome(usb_transaction_outcome_t o);
 
 /** USB address type.
Index: uspace/lib/usb/include/usb/usbdevice.h
===================================================================
--- uspace/lib/usb/include/usb/usbdevice.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/usbdevice.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * General communication between device drivers and host controller driver.
+ */
+#ifndef LIBUSB_USBDEVICE_H_
+#define LIBUSB_USBDEVICE_H_
+
+#include <sys/types.h>
+#include <ipc/devman.h>
+#include <ddf/driver.h>
+#include <bool.h>
+#include <usb/usb.h>
+
+/** Connection to the host controller driver. */
+typedef struct {
+	/** Devman handle of the host controller. */
+	devman_handle_t hc_handle;
+	/** Phone to the host controller. */
+	int hc_phone;
+} usb_hc_connection_t;
+
+int usb_hc_find(devman_handle_t, devman_handle_t *);
+
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *,
+    ddf_dev_t *);
+int usb_hc_connection_initialize(usb_hc_connection_t *, devman_handle_t);
+
+int usb_hc_connection_open(usb_hc_connection_t *);
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *);
+int usb_hc_connection_close(usb_hc_connection_t *);
+
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/usbdrv.h
===================================================================
--- uspace/lib/usb/include/usb/usbdrv.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief USB driver.
- */
-#ifndef LIBUSB_USBDRV_H_
-#define LIBUSB_USBDRV_H_
-
-#include <usb/usb.h>
-#include <driver.h>
-#include <usb/devreq.h>
-#include <usb/descriptor.h>
-
-int usb_drv_find_hc(device_t *, devman_handle_t *);
-int usb_drv_hc_connect(device_t *, devman_handle_t, unsigned int);
-int usb_drv_hc_connect_auto(device_t *, unsigned int);
-
-int usb_drv_reserve_default_address(int);
-int usb_drv_release_default_address(int);
-usb_address_t usb_drv_request_address(int);
-int usb_drv_bind_address(int, usb_address_t, devman_handle_t);
-int usb_drv_release_address(int, usb_address_t);
-
-usb_address_t usb_drv_get_my_address(int, device_t *);
-
-int usb_drv_async_interrupt_out(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_interrupt_in(int, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-
-int usb_drv_psync_interrupt_out(int, usb_target_t, void *, size_t);
-int usb_drv_psync_interrupt_in(int, usb_target_t, void *, size_t, size_t *);
-
-
-
-int usb_drv_async_control_write_setup(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_control_write_data(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_control_write_status(int, usb_target_t,
-    usb_handle_t *);
-
-int usb_drv_psync_control_write_setup(int, usb_target_t, void *, size_t);
-int usb_drv_psync_control_write_data(int, usb_target_t, void *, size_t);
-int usb_drv_psync_control_write_status(int, usb_target_t);
-
-int usb_drv_psync_control_write(int, usb_target_t,
-    void *, size_t, void *, size_t);
-
-
-int usb_drv_async_control_read_setup(int, usb_target_t,
-    void *, size_t, usb_handle_t *);
-int usb_drv_async_control_read_data(int, usb_target_t,
-    void *, size_t, size_t *, usb_handle_t *);
-int usb_drv_async_control_read_status(int, usb_target_t,
-    usb_handle_t *);
-
-int usb_drv_psync_control_read_setup(int, usb_target_t, void *, size_t);
-int usb_drv_psync_control_read_data(int, usb_target_t, void *, size_t, size_t *);
-int usb_drv_psync_control_read_status(int, usb_target_t);
-
-int usb_drv_psync_control_read(int, usb_target_t,
-    void *, size_t, void *, size_t, size_t *);
-
-
-
-int usb_drv_async_wait_for(usb_handle_t);
-
-int usb_drv_create_match_ids_from_device_descriptor(match_id_list_t *,
-    const usb_standard_device_descriptor_t *);
-int usb_drv_create_match_ids_from_configuration_descriptor(match_id_list_t *,
-    const void *, size_t);
-
-int usb_drv_create_device_match_ids(int, match_id_list_t *, usb_address_t);
-int usb_drv_register_child_in_devman(int, device_t *, usb_address_t,
-    devman_handle_t *);
-
-
-#endif
-/**
- * @}
- */
Index: uspace/lib/usb/include/usb/usbmem.h
===================================================================
--- uspace/lib/usb/include/usb/usbmem.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/include/usb/usbmem.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2011 Matus Dekanek
+ * 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.
+ */
+
+#ifndef USBMEM_H
+#define	USBMEM_H
+
+
+// group should be changed - this is not usb specific
+/** @addtogroup usb
+ * @{
+ */
+/** @file definitions of memory management with address translation, used mostly in usb stack
+ *
+ * USB HCD needs traslation between physical and virtual addresses. These
+ * functions implement such functionality. For each allocated virtual address
+ * the memory manager gets also it`s physical translation and remembers it.
+ * Addresses allocated byt this manager can be therefore translated from and to
+ * physical addresses.
+ * Typical use:
+ * void * address = mman_malloc(some_size);
+ * void * physical_address = mman_getPA(address);
+ * void * the_same_address = mman_getVA(physical_address);
+ * void * null_address = mman_getPA(non_existing_address);
+ * mman_free(address);
+ * // physical_address, adress and the_same_address are no longer valid here
+ *
+ *
+ * @note Addresses allocated by this memory manager should be as well
+ * deallocated byt it.
+ *
+ */
+
+#include <sys/types.h>
+
+extern void * mman_malloc(
+    size_t size,
+    size_t alignment,
+    unsigned long max_physical_address);
+
+extern void * mman_getVA(void * addr);
+
+extern void * mman_getPA(void * addr);
+
+extern void mman_free(void * addr);
+
+
+
+
+
+
+/** @}
+ */
+
+
+#endif	/* USBMEM_H */
+
Index: uspace/lib/usb/src/addrkeep.c
===================================================================
--- uspace/lib/usb/src/addrkeep.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/addrkeep.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -33,5 +33,5 @@
  * @brief Address keeping.
  */
-#include <usb/hcd.h>
+#include <usb/addrkeep.h>
 #include <errno.h>
 #include <assert.h>
@@ -149,4 +149,5 @@
 			&addresses->default_condvar_guard);
 	}
+	addresses->default_available = false;
 	fibril_mutex_unlock(&addresses->default_condvar_guard);
 }
Index: uspace/lib/usb/src/class.c
===================================================================
--- uspace/lib/usb/src/class.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/class.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/src/ddfiface.c
===================================================================
--- uspace/lib/usb/src/ddfiface.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/ddfiface.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Implementations of DDF interfaces functions (actual implementation).
+ */
+#include <ipc/devman.h>
+#include <devman.h>
+#include <async.h>
+#include <usb/ddfiface.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+
+/** DDF interface for USB device, implementation for typical hub. */
+usb_iface_t  usb_iface_hub_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_impl,
+	.get_address = usb_iface_get_address_hub_impl
+};
+
+/** DDF interface for USB device, implementation for child of a typical hub. */
+usb_iface_t  usb_iface_hub_child_impl = {
+	.get_hc_handle = usb_iface_get_hc_handle_hub_child_impl,
+	.get_address = usb_iface_get_address_hub_child_impl
+};
+
+
+/** Get host controller handle, interface implementation for hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_impl(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+	return usb_hc_find(fun->handle, handle);
+}
+
+/** Get host controller handle, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Error code.
+ */
+int usb_iface_get_hc_handle_hub_child_impl(ddf_fun_t *fun,
+    devman_handle_t *handle)
+{
+	assert(fun != NULL);
+
+	int parent_phone = devman_parent_device_connect(fun->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	sysarg_t hc_handle;
+	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &hc_handle);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	*handle = hc_handle;
+
+	return EOK;
+}
+
+/** Get host controller handle, interface implementation for HC driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[out] handle Storage for the host controller handle.
+ * @return Always EOK.
+ */
+int usb_iface_get_hc_handle_hc_impl(ddf_fun_t *fun, devman_handle_t *handle)
+{
+	assert(fun);
+
+	if (handle != NULL) {
+		*handle = fun->handle;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_impl(ddf_fun_t *fun, devman_handle_t handle,
+    usb_address_t *address)
+{
+	assert(fun);
+	int parent_phone = devman_parent_device_connect(fun->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	sysarg_t addr;
+	int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS, handle, &addr);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (address != NULL) {
+		*address = (usb_address_t) addr;
+	}
+
+	return EOK;
+}
+
+/** Get USB device address, interface implementation for child of
+ * a hub driver.
+ *
+ * @param[in] device Device the operation is running on.
+ * @param[in] handle Devman handle of USB device we want address of.
+ * @param[out] address Storage for USB address of device with handle @p handle.
+ * @return Error code.
+ */
+int usb_iface_get_address_hub_child_impl(ddf_fun_t *fun,
+    devman_handle_t handle, usb_address_t *address)
+{
+	if (handle == 0) {
+		handle = fun->handle;
+	}
+	return usb_iface_get_address_hub_impl(fun, handle, address);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/debug.c
===================================================================
--- uspace/lib/usb/src/debug.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/debug.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2010-2011 Vojtech Horky
  * All rights reserved.
  *
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -60,4 +60,12 @@
 /** Mutex guard for the list of all tags. */
 static FIBRIL_MUTEX_INITIALIZE(tag_list_guard);
+
+/** Level of logging messages. */
+static usb_log_level_t log_level = USB_LOG_LEVEL_WARNING;
+/** Prefix for logging messages. */
+static const char *log_prefix = "usb";
+/** Serialization mutex for logging functions. */
+static FIBRIL_MUTEX_INITIALIZE(log_serializer);
+static FILE *log_stream = NULL;
 
 /** Find or create new tag with given name.
@@ -155,4 +163,92 @@
 }
 
+/** Enable logging.
+ *
+ * @param level Maximal enabled level (including this one).
+ * @param message_prefix Prefix for each printed message.
+ */
+void usb_log_enable(usb_log_level_t level, const char *message_prefix)
+{
+	log_prefix = message_prefix;
+	log_level = level;
+	if (log_stream == NULL) {
+		char *fname;
+		int rc = asprintf(&fname, "/log/%s", message_prefix);
+		if (rc > 0) {
+			log_stream = fopen(fname, "w");
+			free(fname);
+		}
+	}
+}
+
+
+static const char *log_level_name(usb_log_level_t level)
+{
+	switch (level) {
+		case USB_LOG_LEVEL_FATAL:
+			return " FATAL";
+		case USB_LOG_LEVEL_ERROR:
+			return " ERROR";
+		case USB_LOG_LEVEL_WARNING:
+			return " WARN";
+		case USB_LOG_LEVEL_INFO:
+			return " info";
+		default:
+			return "";
+	}
+}
+
+/** Print logging message.
+ *
+ * @param level Verbosity level of the message.
+ * @param format Formatting directive.
+ */
+void usb_log_printf(usb_log_level_t level, const char *format, ...)
+{
+	FILE *screen_stream = NULL;
+	switch (level) {
+		case USB_LOG_LEVEL_FATAL:
+		case USB_LOG_LEVEL_ERROR:
+			screen_stream = stderr;
+			break;
+		default:
+			screen_stream = stdout;
+			break;
+	}
+	assert(screen_stream != NULL);
+
+	va_list args;
+
+	/*
+	 * Serialize access to log files.
+	 * Always print to log file, to screen print only when the enabled
+	 * log level is high enough.
+	 */
+	fibril_mutex_lock(&log_serializer);
+
+	const char *level_name = log_level_name(level);
+
+	if (log_stream != NULL) {
+		va_start(args, format);
+
+		fprintf(log_stream, "[%s]%s: ", log_prefix, level_name);
+		vfprintf(log_stream, format, args);
+		fflush(log_stream);
+
+		va_end(args);
+	}
+
+	if (level <= log_level) {
+		va_start(args, format);
+
+		fprintf(screen_stream, "[%s]%s: ", log_prefix, level_name);
+		vfprintf(screen_stream, format, args);
+		fflush(screen_stream);
+
+		va_end(args);
+	}
+
+	fibril_mutex_unlock(&log_serializer);
+}
 
 /**
Index: uspace/lib/usb/src/dp.c
===================================================================
--- uspace/lib/usb/src/dp.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/dp.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -37,7 +37,28 @@
 #include <str_error.h>
 #include <errno.h>
-#include <usb/usbdrv.h>
+#include <assert.h>
 #include <bool.h>
 #include <usb/dp.h>
+#include <usb/descriptor.h>
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting of standard USB descriptors. */
+usb_dp_descriptor_nesting_t usb_dp_standard_descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+#undef NESTING
+#undef LAST_NESTING
 
 /** Tells whether pointer points inside descriptor data.
@@ -45,5 +66,5 @@
  * @param data Parser data.
  * @param ptr Pointer to be verified.
- * @return Whether @ptr points inside <code>data->data</code> field.
+ * @return Whether @p ptr points inside <code>data->data</code> field.
  */
 static bool is_valid_descriptor_pointer(usb_dp_parser_data_t *data,
Index: uspace/lib/usb/src/drvpsync.c
===================================================================
--- uspace/lib/usb/src/drvpsync.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,218 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Implementation of pseudo-synchronous transfers.
- */
-#include <usb/usbdrv.h>
-#include <usbhc_iface.h>
-#include <errno.h>
-
-int usb_drv_psync_interrupt_out(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_interrupt_out(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_interrupt_in(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_interrupt_in(phone, target, buffer, size,
-	    actual_size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-
-
-int usb_drv_psync_control_write_setup(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_write_setup(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_write_data(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_write_data(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_write_status(int phone, usb_target_t target)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_write_status(phone, target, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-
-/** Perform complete control write transaction over USB.
- *
- * The DATA stage is performed only when @p data is not NULL and
- * @p data_size is greater than zero.
- *
- * @param phone Open phone to host controller.
- * @param target Target device and endpoint.
- * @param setup_packet Setup packet data.
- * @param setup_packet_size Size of the setup packet.
- * @param data Data to be sent.
- * @param data_size Size of the @p data buffer.
- * @return Error code.
- */
-int usb_drv_psync_control_write(int phone, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data, size_t data_size)
-{
-	int rc;
-	
-	rc = usb_drv_psync_control_write_setup(phone, target,
-	    setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if ((data != NULL) && (data_size > 0)) {
-		rc = usb_drv_psync_control_write_data(phone, target,
-		    data, data_size);
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-
-	rc = usb_drv_psync_control_write_status(phone, target);
-
-	return rc;
-}
-
-
-int usb_drv_psync_control_read_setup(int phone, usb_target_t target,
-    void *buffer, size_t size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_read_setup(phone, target, buffer, size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_read_data(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_read_data(phone, target, buffer, size,
-	    actual_size, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-int usb_drv_psync_control_read_status(int phone, usb_target_t target)
-{
-	usb_handle_t h;
-	int rc;
-	rc = usb_drv_async_control_read_status(phone, target, &h);
-	if (rc != EOK) {
-		return rc;
-	}
-	return usb_drv_async_wait_for(h);
-}
-
-
-/** Perform complete control read transaction over USB.
- *
- * @param phone Open phone to host controller.
- * @param target Target device and endpoint.
- * @param setup_packet Setup packet data.
- * @param setup_packet_size Size of the setup packet.
- * @param data Storage for read data.
- * @param data_size Size of the @p data buffer.
- * @param actual_data_size Storage for number of actually transferred data from
- *        device.
- * @return Error code.
- */
-int usb_drv_psync_control_read(int phone, usb_target_t target,
-    void *setup_packet, size_t setup_packet_size,
-    void *data, size_t data_size, size_t *actual_data_size)
-{
-	int rc;
-	
-	rc = usb_drv_psync_control_read_setup(phone, target,
-	    setup_packet, setup_packet_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_drv_psync_control_read_data(phone, target,
-	    data, data_size, actual_data_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	rc = usb_drv_psync_control_read_status(phone, target);
-
-	return rc;
-}
-
-
-
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/dump.c
===================================================================
--- uspace/lib/usb/src/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/dump.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * @brief Descriptor dumping.
+ */
+#include <adt/list.h>
+#include <fibril_synch.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <usb/debug.h>
+#include <usb/descriptor.h>
+#include <usb/classes/classes.h>
+#include <usb/classes/hid.h>
+
+typedef struct {
+	int id;
+	void (*dump)(FILE *, const char *, const char *,
+	    const uint8_t *, size_t);
+} descriptor_dump_t;
+
+static void usb_dump_descriptor_device(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_configuration(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_interface(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_string(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_endpoint(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_hid(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_hub(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+static void usb_dump_descriptor_generic(FILE *, const char *, const char *,
+    const uint8_t *, size_t);
+
+static descriptor_dump_t descriptor_dumpers[] = {
+	{ USB_DESCTYPE_DEVICE, usb_dump_descriptor_device },
+	{ USB_DESCTYPE_CONFIGURATION, usb_dump_descriptor_configuration },
+	{ USB_DESCTYPE_STRING, usb_dump_descriptor_string },
+	{ USB_DESCTYPE_INTERFACE, usb_dump_descriptor_interface },
+	{ USB_DESCTYPE_ENDPOINT, usb_dump_descriptor_endpoint },
+	{ USB_DESCTYPE_HID, usb_dump_descriptor_hid },
+	{ USB_DESCTYPE_HUB, usb_dump_descriptor_hub },
+	{ -1, usb_dump_descriptor_generic },
+	{ -1, NULL }
+};
+
+/** Dumps standard USB descriptor.
+ * The @p line_suffix must contain the newline <code>\\n</code> character.
+ * When @p line_suffix or @p line_prefix is NULL, they are substitued with
+ * default values
+ * (<code> - </code> for prefix and line termination for suffix).
+ *
+ * @param output Output file stream to dump descriptor to.
+ * @param line_prefix Prefix for each line of output.
+ * @param line_suffix Suffix of each line of output.
+ * @param descriptor Actual descriptor.
+ * @param descriptor_length Descriptor size.
+ */
+void usb_dump_standard_descriptor(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	if (descriptor_length < 2) {
+		return;
+	}
+	int type = descriptor[1];
+
+	descriptor_dump_t *dumper = descriptor_dumpers;
+	while (dumper->dump != NULL) {
+		if ((dumper->id == type) || (dumper->id < 0)) {
+			dumper->dump(output, line_prefix, line_suffix,
+			    descriptor, descriptor_length);
+			return;
+		}
+		dumper++;
+	}
+}
+
+/** Prints single line of USB descriptor dump.
+ * @warning This macro abuses heavily the naming conventions used
+ * by all dumping functions (i.e. names for output file stream (@c output) and
+ * line prefix and suffix (@c line_prefix and @c line_suffix respectively))-
+ *
+ * @param fmt Formatting string.
+ */
+#define PRINTLINE(fmt, ...) \
+	fprintf(output, "%s" fmt "%s", \
+	    line_prefix ? line_prefix : " - ", \
+	    __VA_ARGS__, \
+	    line_suffix ? line_suffix : "\n")
+
+#define BCD_INT(a) (((unsigned int)(a)) / 256)
+#define BCD_FRAC(a) (((unsigned int)(a)) % 256)
+
+#define BCD_FMT "%x.%x"
+#define BCD_ARGS(a) BCD_INT((a)), BCD_FRAC((a))
+
+static void usb_dump_descriptor_device(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_device_descriptor_t *d
+	    = (usb_standard_device_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bcdUSB = %d (" BCD_FMT ")", d->usb_spec_version,
+	    BCD_ARGS(d->usb_spec_version));
+	PRINTLINE("bDeviceClass = 0x%02x", d->device_class);
+	PRINTLINE("bDeviceSubClass = 0x%02x", d->device_subclass);
+	PRINTLINE("bDeviceProtocol = 0x%02x", d->device_protocol);
+	PRINTLINE("bMaxPacketSize0 = %d", d->max_packet_size);
+	PRINTLINE("idVendor = 0x%04x", d->vendor_id);
+	PRINTLINE("idProduct = 0x%04x", d->product_id);
+	PRINTLINE("bcdDevice = %d", d->device_version);
+	PRINTLINE("iManufacturer = %d", d->str_manufacturer);
+	PRINTLINE("iProduct = %d", d->str_product);
+	PRINTLINE("iSerialNumber = %d", d->str_serial_number);
+	PRINTLINE("bNumConfigurations = %d", d->configuration_count);
+}
+
+static void usb_dump_descriptor_configuration(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_configuration_descriptor_t *d
+	    = (usb_standard_configuration_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	bool self_powered = d->attributes & 64;
+	bool remote_wakeup = d->attributes & 32;
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("wTotalLength = %d", d->total_length);
+	PRINTLINE("bNumInterfaces = %d", d->interface_count);
+	PRINTLINE("bConfigurationValue = %d", d->configuration_number);
+	PRINTLINE("iConfiguration = %d", d->str_configuration);
+	PRINTLINE("bmAttributes = %d [%s%s%s]", d->attributes,
+	    self_powered ? "self-powered" : "",
+	    (self_powered & remote_wakeup) ? ", " : "",
+	    remote_wakeup ? "remote-wakeup" : "");
+	PRINTLINE("MaxPower = %d (%dmA)", d->max_power,
+	    2 * d->max_power);
+}
+
+static void usb_dump_descriptor_interface(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_interface_descriptor_t *d
+	    = (usb_standard_interface_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bInterfaceNumber = %d", d->interface_number);
+	PRINTLINE("bAlternateSetting = %d", d->alternate_setting);
+	PRINTLINE("bNumEndpoints = %d", d->endpoint_count);
+	PRINTLINE("bInterfaceClass = %s", d->interface_class == 0
+	    ? "reserved (0)" : usb_str_class(d->interface_class));
+	PRINTLINE("bInterfaceSubClass = %d", d->interface_subclass);
+	PRINTLINE("bInterfaceProtocol = %d", d->interface_protocol);
+	PRINTLINE("iInterface = %d", d->str_interface);
+}
+
+static void usb_dump_descriptor_string(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+static void usb_dump_descriptor_endpoint(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_endpoint_descriptor_t *d
+	   = (usb_standard_endpoint_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	int endpoint = d->endpoint_address & 15;
+	usb_direction_t direction = d->endpoint_address & 128
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	usb_transfer_type_t transfer_type = d->attributes & 3;
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02X", d->descriptor_type);
+	PRINTLINE("bEndpointAddress = 0x%02X [%d, %s]",
+	    d->endpoint_address, endpoint,
+	    direction == USB_DIRECTION_IN ? "in" : "out");
+	PRINTLINE("bmAttributes = %d [%s]", d->attributes,
+	    usb_str_transfer_type(transfer_type));
+	PRINTLINE("wMaxPacketSize = %d", d->max_packet_size);
+	PRINTLINE("bInterval = %dms", d->poll_interval);
+}
+
+static void usb_dump_descriptor_hid(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+	usb_standard_hid_descriptor_t *d
+	    = (usb_standard_hid_descriptor_t *) descriptor;
+	if (descriptor_length < sizeof(*d)) {
+		return;
+	}
+
+	PRINTLINE("bLength = %d", d->length);
+	PRINTLINE("bDescriptorType = 0x%02x", d->descriptor_type);
+	PRINTLINE("bcdHID = %d (" BCD_FMT ")", d->spec_release,
+	    BCD_ARGS(d->spec_release));
+	PRINTLINE("bCountryCode = %d", d->country_code);
+	PRINTLINE("bNumDescriptors = %d", d->class_desc_count);
+	PRINTLINE("bDescriptorType = %d", d->report_desc_info.type);
+	PRINTLINE("wDescriptorLength = %d", d->report_desc_info.length);
+
+	/* Print info about report descriptors. */
+	size_t i;
+	size_t count = (descriptor_length - sizeof(*d))
+	    / sizeof(usb_standard_hid_class_descriptor_info_t);
+	usb_standard_hid_class_descriptor_info_t *d2
+	    = (usb_standard_hid_class_descriptor_info_t *)
+	    (descriptor + sizeof(*d));
+	for (i = 0; i < count; i++, d2++) {
+		PRINTLINE("bDescriptorType = %d", d2->type);
+		PRINTLINE("wDescriptorLength = %d", d2->length);
+	}
+}
+
+static void usb_dump_descriptor_hub(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+static void usb_dump_descriptor_generic(FILE *output,
+    const char *line_prefix, const char *line_suffix,
+    const uint8_t *descriptor, size_t descriptor_length)
+{
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/hcdhubd.c
===================================================================
--- uspace/lib/usb/src/hcdhubd.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,341 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Common stuff for both HC driver and hub driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <usb/classes/hub.h>
-
-#include "hcdhubd_private.h"
-
-
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	assert(dev);
-	assert(dev->parent != NULL);
-
-	device_t *parent = dev->parent;
-
-	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-		usb_iface_t *usb_iface
-		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-		assert(usb_iface != NULL);
-		if (usb_iface->get_hc_handle) {
-			int rc = usb_iface->get_hc_handle(parent, handle);
-			return rc;
-		}
-	}
-
-	return ENOTSUP;
-}
-
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t child_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
-};
-
-/** Callback when new device is detected and must be handled by this driver.
- *
- * @param dev New device.
- * @return Error code.
- */
-static int add_device(device_t *dev) {
-	return ENOTSUP;
-}
-
-/** Operations for combined HC and HUB driver. */
-static driver_ops_t hc_driver_generic_ops = {
-	.add_device = add_device
-};
-
-/** Combined HC and HUB driver. */
-static driver_t hc_driver_generic = {
-	.driver_ops = &hc_driver_generic_ops
-};
-
-/** Main USB host controller driver routine.
- *
- * @see driver_main
- *
- * @param hc Host controller driver.
- * @return Error code.
- */
-int usb_hcd_main(usb_hc_driver_t *hc) {
-	hc_driver = hc;
-	hc_driver_generic.name = hc->name;
-
-	/*
-	 * Run the device driver framework.
-	 */
-	return driver_main(&hc_driver_generic);
-}
-
-/** Add a root hub for given host controller.
- * This function shall be called only once for each host controller driven
- * by this driver.
- * It takes care of creating child device - hub - that will be driven by
- * this task.
- *
- * @param dev Host controller device.
- * @return Error code.
- */
-int usb_hcd_add_root_hub(device_t *dev)
-{
-	char *id;
-	int rc = asprintf(&id, "usb&hub");
-	if (rc <= 0) {
-		return rc;
-	}
-
-	rc = usb_hc_add_child_device(dev, USB_HUB_DEVICE_NAME, id, true);
-	if (rc != EOK) {
-		free(id);
-	}
-
-	return rc;
-}
-
-/** Info about child device. */
-struct child_device_info {
-	device_t *parent;
-	const char *name;
-	const char *match_id;
-};
-
-/** Adds a child device fibril worker. */
-static int fibril_add_child_device(void *arg) {
-	struct child_device_info *child_info
-			= (struct child_device_info *) arg;
-	int rc;
-
-	async_usleep(1000);
-
-	device_t *child = create_device();
-	match_id_t *match_id = NULL;
-
-	if (child == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	child->name = child_info->name;
-	child->parent = child_info->parent;
-	child->ops = &child_ops;
-
-	match_id = create_match_id();
-	if (match_id == NULL) {
-		rc = ENOMEM;
-		goto failure;
-	}
-	match_id->id = child_info->match_id;
-	match_id->score = 10;
-	add_match_id(&child->match_ids, match_id);
-
-	printf("%s: adding child device `%s' with match \"%s\"\n",
-			hc_driver->name, child->name, match_id->id);
-	rc = child_device_register(child, child_info->parent);
-	printf("%s: child device `%s' registration: %s\n",
-			hc_driver->name, child->name, str_error(rc));
-
-	if (rc != EOK) {
-		goto failure;
-	}
-
-	goto leave;
-
-failure:
-	if (child != NULL) {
-		child->name = NULL;
-		delete_device(child);
-	}
-
-	if (match_id != NULL) {
-		match_id->id = NULL;
-		delete_match_id(match_id);
-	}
-
-leave:
-	free(arg);
-	return EOK;
-}
-
-/** Adds a child.
- * Due to deadlock in devman when parent registers child that oughts to be
- * driven by the same task, the child adding is done in separate fibril.
- * Not optimal, but it works.
- * Update: not under all circumstances the new fibril is successful either.
- * Thus the last parameter to let the caller choose.
- *
- * @param parent Parent device.
- * @param name Device name.
- * @param match_id Match id.
- * @param create_fibril Whether to run the addition in new fibril.
- * @return Error code.
- */
-int usb_hc_add_child_device(device_t *parent, const char *name,
-		const char *match_id, bool create_fibril) {
-	printf("%s: about to add child device `%s' (%s)\n", hc_driver->name,
-			name, match_id);
-
-	/*
-	 * Seems that creating fibril which postpones the action
-	 * is the best solution.
-	 */
-	create_fibril = true;
-
-	struct child_device_info *child_info
-			= malloc(sizeof (struct child_device_info));
-
-	child_info->parent = parent;
-	child_info->name = name;
-	child_info->match_id = match_id;
-
-	if (create_fibril) {
-		fid_t fibril = fibril_create(fibril_add_child_device, child_info);
-		if (!fibril) {
-			return ENOMEM;
-		}
-		fibril_add_ready(fibril);
-	} else {
-		fibril_add_child_device(child_info);
-	}
-
-	return EOK;
-}
-
-/** Tell USB address of given device.
- *
- * @param handle Devman handle of the device.
- * @return USB device address or error code.
- */
-usb_address_t usb_get_address_by_handle(devman_handle_t handle) {
-	/* TODO: search list of attached devices. */
-	return ENOENT;
-}
-
-usb_address_t usb_use_free_address(usb_hc_device_t * this_hcd) {
-	//is there free address?
-	link_t * addresses = &this_hcd->addresses;
-	if (list_empty(addresses)) return -1;
-	link_t * link_addr = addresses;
-	bool found = false;
-	usb_address_list_t * range = NULL;
-	while (!found) {
-		link_addr = link_addr->next;
-		if (link_addr == addresses) return -2;
-		range = list_get_instance(link_addr,
-				usb_address_list_t, link);
-		if (range->upper_bound - range->lower_bound > 0) {
-			found = true;
-		}
-	}
-	//now we have interval
-	int result = range->lower_bound;
-	++(range->lower_bound);
-	if (range->upper_bound - range->lower_bound == 0) {
-		list_remove(&range->link);
-		free(range);
-	}
-	return result;
-}
-
-void usb_free_used_address(usb_hc_device_t * this_hcd, usb_address_t addr) {
-	//check range
-	if (addr < usb_lowest_address || addr > usb_highest_address)
-		return;
-	link_t * addresses = &this_hcd->addresses;
-	link_t * link_addr = addresses;
-	//find 'good' interval
-	usb_address_list_t * found_range = NULL;
-	bool found = false;
-	while (!found) {
-		link_addr = link_addr->next;
-		if (link_addr == addresses) {
-			found = true;
-		} else {
-			usb_address_list_t * range = list_get_instance(link_addr,
-					usb_address_list_t, link);
-			if (	(range->lower_bound - 1 == addr) ||
-					(range->upper_bound == addr)) {
-				found = true;
-				found_range = range;
-			}
-			if (range->lower_bound - 1 > addr) {
-				found = true;
-			}
-
-		}
-	}
-	if (found_range == NULL) {
-		//no suitable range found
-		usb_address_list_t * result_range =
-				(usb_address_list_t*) malloc(sizeof (usb_address_list_t));
-		result_range->lower_bound = addr;
-		result_range->upper_bound = addr + 1;
-		list_insert_before(&result_range->link, link_addr);
-	} else {
-		//we have good range
-		if (found_range->lower_bound - 1 == addr) {
-			--found_range->lower_bound;
-		} else {
-			//only one possible case
-			++found_range->upper_bound;
-			if (found_range->link.next != addresses) {
-				usb_address_list_t * next_range =
-						list_get_instance( &found_range->link.next,
-						usb_address_list_t, link);
-				//check neighbour range
-				if (next_range->lower_bound == addr + 1) {
-					//join ranges
-					found_range->upper_bound = next_range->upper_bound;
-					list_remove(&next_range->link);
-					free(next_range);
-				}
-			}
-		}
-	}
-
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hcdhubd_private.h
===================================================================
--- uspace/lib/usb/src/hcdhubd_private.h	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/hcdhubd_private.h	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
Index: uspace/lib/usb/src/hcdrv.c
===================================================================
--- uspace/lib/usb/src/hcdrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,127 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief HC driver.
- */
-#include <usb/hcdhubd.h>
-#include <usb/devreq.h>
-#include <usbhc_iface.h>
-#include <usb/descriptor.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-#include <usb/classes/hub.h>
-
-#include "hcdhubd_private.h"
-
-/** List of handled host controllers. */
-LIST_INITIALIZE(hc_list);
-
-/* Fake driver to have the name item initialized. */
-static usb_hc_driver_t hc_driver_fake = {
-	.name = "HCD",
-};
-
-/** Our HC driver. */
-usb_hc_driver_t *hc_driver = &hc_driver_fake;
-
-int usb_lowest_address = 1;
-
-int usb_highest_address = 255;
-
-static device_ops_t usb_device_ops = {
-	.interfaces[USBHC_DEV_IFACE] = &usbhc_interface
-};
-
-
-void usb_create_address_list(usb_hc_device_t * hcd){
-	list_initialize(&hcd->addresses);
-	usb_address_list_t * range =
-			(usb_address_list_t*)malloc(sizeof(usb_address_list_t));
-	range->lower_bound = usb_lowest_address;
-	range->upper_bound = usb_highest_address + 1;
-	list_append(&range->link, &hcd->addresses);
-}
-
-static usb_hc_device_t *usb_hc_device_create(device_t *dev) {
-	usb_hc_device_t *hc_dev = malloc(sizeof (usb_hc_device_t));
-
-	list_initialize(&hc_dev->link);
-	list_initialize(&hc_dev->hubs);
-	usb_create_address_list(hc_dev);
-	list_initialize(&hc_dev->attached_devices);
-	hc_dev->transfer_ops = NULL;
-
-	hc_dev->generic = dev;
-	dev->ops = &usb_device_ops;
-	hc_dev->generic->driver_data = hc_dev;
-
-	return hc_dev;
-}
-
-int usb_add_hc_device(device_t *dev)
-{
-	return ENOTSUP;
-	usb_hc_device_t *hc_dev = usb_hc_device_create(dev);
-
-	int rc = hc_driver->add_hc(hc_dev);
-	if (rc != EOK) {
-		free(hc_dev);
-		return rc;
-	}
-
-	/*
-	 * FIXME: The following line causes devman to hang.
-	 * Will investigate later why.
-	 */
-	// add_device_to_class(dev, "usbhc");
-
-	list_append(&hc_dev->link, &hc_list);
-
-	/*
-	 * FIXME: the following is a workaround to force loading of USB
-	 * keyboard driver.
-	 * Will be removed as soon as the hub driver is completed and
-	 * can detect connected devices.
-	 */
-	printf("%s: trying to add USB HID child device...\n", hc_driver->name);
-	rc = usb_hc_add_child_device(dev, USB_KBD_DEVICE_NAME, "usb&hid", false);
-	if (rc != EOK) {
-		printf("%s: adding USB HID child failed...\n", hc_driver->name);
-	}
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/hidparser.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -196,15 +196,4 @@
 }
 
-/** Free the HID report parser structure 
- *
- * @param parser Opaque HID report parser structure
- * @return Error code
- */
-int usb_hid_free_report_parser(usb_hid_report_parser_t *parser)
-{
-
-	return EOK;
-}
-
 
 /**
@@ -237,5 +226,5 @@
 
 	if (size != 8) {
-		return -1;//ERANGE;
+		return ERANGE;
 	}
 
@@ -540,8 +529,7 @@
 }
 
-/**
- * Frees complete structure of report parser
- * 
- * @param Parser to free
+/** Free the HID report parser structure 
+ *
+ * @param parser Opaque HID report parser structure
  * @return Error code
  */
@@ -561,7 +549,2 @@
  * @}
  */
-
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/hub.c
===================================================================
--- uspace/lib/usb/src/hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/hub.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Functions needed by hub drivers.
+ */
+#include <usb/hub.h>
+#include <usb/pipes.h>
+#include <usb/request.h>
+#include <usb/recognise.h>
+#include <usbhc_iface.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Check that HC connection is alright.
+ *
+ * @param conn Connection to be checked.
+ */
+#define CHECK_CONNECTION(conn) \
+	do { \
+		assert((conn)); \
+		if (!usb_hc_connection_is_opened((conn))) { \
+			return ENOENT; \
+		} \
+	} while (false)
+
+
+/** Tell host controller to reserve default address.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Error code.
+ */
+int usb_hc_reserve_default_address(usb_hc_connection_t *connection,
+    usb_speed_t speed)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_2_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS, speed);
+}
+
+/** Tell host controller to release default address.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Error code.
+ */
+int usb_hc_release_default_address(usb_hc_connection_t *connection)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_1_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
+}
+
+/** Ask host controller for free address assignment.
+ *
+ * @param connection Opened connection to host controller.
+ * @return Assigned USB address or negative error code.
+ */
+usb_address_t usb_hc_request_address(usb_hc_connection_t *connection,
+    usb_speed_t speed)
+{
+	CHECK_CONNECTION(connection);
+
+	sysarg_t address;
+	int rc = async_req_2_1(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_REQUEST_ADDRESS, speed,
+	    &address);
+	if (rc != EOK) {
+		return (usb_address_t) rc;
+	} else {
+		return (usb_address_t) address;
+	}
+}
+
+/** Inform host controller about new device.
+ *
+ * @param connection Opened connection to host controller.
+ * @param attached_device Information about the new device.
+ * @return Error code.
+ */
+int usb_hc_register_device(usb_hc_connection_t * connection,
+    const usb_hc_attached_device_t *attached_device)
+{
+	CHECK_CONNECTION(connection);
+	if (attached_device == NULL) {
+		return EBADMEM;
+	}
+
+	return async_req_3_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_BIND_ADDRESS,
+	    attached_device->address, attached_device->handle);
+}
+
+/** Inform host controller about device removal.
+ *
+ * @param connection Opened connection to host controller.
+ * @param address Address of the device that is being removed.
+ * @return Error code.
+ */
+int usb_hc_unregister_device(usb_hc_connection_t *connection,
+    usb_address_t address)
+{
+	CHECK_CONNECTION(connection);
+
+	return async_req_2_0(connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE),
+	    IPC_M_USBHC_RELEASE_ADDRESS, address);
+}
+
+
+/** Wrapper for registering attached device to the hub.
+ *
+ * The @p enable_port function is expected to enable singalling on given
+ * port.
+ * The two arguments to it can have arbitrary meaning
+ * (the @p port_no is only a suggestion)
+ * and are not touched at all by this function
+ * (they are passed as is to the @p enable_port function).
+ *
+ * If the @p enable_port fails (i.e. does not return EOK), the device
+ * addition is cancelled.
+ * The return value is then returned (it is good idea to use different
+ * error codes than those listed as return codes by this function itself).
+ *
+ * @param parent Parent device (i.e. the hub device).
+ * @param connection Opened connection to host controller.
+ * @param dev_speed New device speed.
+ * @param enable_port Function for enabling signalling through the port the
+ *	device is attached to.
+ * @param port_no Port number (passed through to @p enable_port).
+ * @param arg Any data argument to @p enable_port.
+ * @param[out] assigned_address USB address of the device.
+ * @param[out] assigned_handle Devman handle of the new device.
+ * @return Error code.
+ * @retval ENOENT Connection to HC not opened.
+ * @retval EADDRNOTAVAIL Failed retrieving free address from host controller.
+ * @retval EBUSY Failed reserving default USB address.
+ * @retval ENOTCONN Problem connecting to the host controller via USB pipe.
+ * @retval ESTALL Problem communication with device (either SET_ADDRESS
+ *	request or requests for descriptors when creating match ids).
+ */
+int usb_hc_new_device_wrapper(ddf_dev_t *parent, usb_hc_connection_t *connection,
+    usb_speed_t dev_speed,
+    int (*enable_port)(int port_no, void *arg), int port_no, void *arg,
+    usb_address_t *assigned_address, devman_handle_t *assigned_handle,
+    ddf_dev_ops_t *dev_ops, void *new_dev_data, ddf_fun_t **new_fun)
+{
+	CHECK_CONNECTION(connection);
+
+	/*
+	 * Request new address.
+	 */
+	usb_address_t dev_addr = usb_hc_request_address(connection, dev_speed);
+	if (dev_addr < 0) {
+		return EADDRNOTAVAIL;
+	}
+
+	int rc;
+
+	/*
+	 * Reserve the default address.
+	 */
+	rc = usb_hc_reserve_default_address(connection, dev_speed);
+	if (rc != EOK) {
+		rc = EBUSY;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * Enable the port (i.e. allow signalling through this port).
+	 */
+	rc = enable_port(port_no, arg);
+	if (rc != EOK) {
+		goto leave_release_default_address;
+	}
+
+	/*
+	 * Change the address from default to the free one.
+	 * We need to create a new control pipe for that.
+	 */
+	usb_device_connection_t dev_conn;
+	rc = usb_device_connection_initialize_on_default_address(&dev_conn,
+	    connection);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	usb_endpoint_pipe_t ctrl_pipe;
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_conn);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		rc = ENOTCONN;
+		goto leave_release_default_address;
+	}
+
+	rc = usb_request_set_address(&ctrl_pipe, dev_addr);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_stop_session;
+	}
+
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+	/*
+	 * Once the address is changed, we can return the default address.
+	 */
+	usb_hc_release_default_address(connection);
+
+	/*
+	 * It is time to register the device with devman.
+	 */
+	/* FIXME: create device_register that will get opened ctrl pipe. */
+	devman_handle_t child_handle;
+	rc = usb_device_register_child_in_devman(dev_addr, dev_conn.hc_handle,
+	    parent, &child_handle,
+	    dev_ops, new_dev_data, new_fun);
+	if (rc != EOK) {
+		rc = ESTALL;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And now inform the host controller about the handle.
+	 */
+	usb_hc_attached_device_t new_device = {
+		.address = dev_addr,
+		.handle = child_handle
+	};
+	rc = usb_hc_register_device(connection, &new_device);
+	if (rc != EOK) {
+		rc = EDESTADDRREQ;
+		goto leave_release_free_address;
+	}
+
+	/*
+	 * And we are done.
+	 */
+	if (assigned_address != NULL) {
+		*assigned_address = dev_addr;
+	}
+	if (assigned_handle != NULL) {
+		*assigned_handle = child_handle;
+	}
+
+	return EOK;
+
+
+
+	/*
+	 * Error handling (like nested exceptions) starts here.
+	 * Completely ignoring errors here.
+	 */
+
+leave_stop_session:
+	usb_endpoint_pipe_end_session(&ctrl_pipe);
+
+leave_release_default_address:
+	usb_hc_release_default_address(connection);
+
+leave_release_free_address:
+	usb_hc_unregister_device(connection, dev_addr);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/localdrv.c
===================================================================
--- uspace/lib/usb/src/localdrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,414 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Driver communication for local drivers (hubs).
- */
-#include <usb/hcdhubd.h>
-#include <usbhc_iface.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-
-/** Find host controller when handled by current task.
- *
- * @param dev Device asking for connection.
- * @return Device structure corresponding to parent host controller.
- * @retval NULL Corresponding host controller not found.
- */
-device_t *usb_hc_connect(device_t *dev)
-{
-	/*
-	 * FIXME: this will not work when some hub on the path is
-	 * not driven by the same task.
-	 */
-	device_t *parent = dev;
-	while (parent->parent != NULL) {
-		parent = parent->parent;
-	}
-	
-	if (dev == parent) {
-		printf("FIXME in %s:%d encountered!\n", __FILE__, __LINE__);
-		parent = NULL;
-	}
-
-	return parent;
-}
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Storage for actual number of bytes transferred. */
-	size_t *size_transferred;
-
-	/** Target device. */
-	usb_hcd_attached_device_info_t *device;
-	/** Target endpoint. */
-	usb_hc_endpoint_info_t *endpoint;
-
-	/** Guard for the condition variable. */
-	fibril_mutex_t condvar_guard;
-	/** Condition variable for waiting for done. */
-	fibril_condvar_t condvar;
-
-	/** Flag whether the transfer is done. */
-	bool done;
-} transfer_info_t;
-
-/** Create new transfer info.
- *
- * @param device Attached device.
- * @param endpoint Endpoint.
- * @return Transfer info with pre-filled values.
- */
-static transfer_info_t *transfer_info_create(
-    usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint)
-{
-	transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
-
-	transfer->size_transferred = NULL;
-	fibril_condvar_initialize(&transfer->condvar);
-	fibril_mutex_initialize(&transfer->condvar_guard);
-	transfer->done = false;
-
-	transfer->device = device;
-	transfer->endpoint = endpoint;
-
-	return transfer;
-}
-
-/** Destroy transfer info.
- *
- * @param transfer Transfer to be destroyed.
- */
-static void transfer_info_destroy(transfer_info_t *transfer)
-{
-	free(transfer->device);
-	free(transfer->endpoint);
-	free(transfer);
-}
-
-/** Create info about attached device.
- *
- * @param address Device address.
- * @return Device info structure.
- */
-static usb_hcd_attached_device_info_t *create_attached_device_info(
-    usb_address_t address)
-{
-	usb_hcd_attached_device_info_t *dev
-	    = malloc(sizeof(usb_hcd_attached_device_info_t));
-
-	dev->address = address;
-	dev->endpoint_count = 0;
-	dev->endpoints = NULL;
-	list_initialize(&dev->link);
-
-	return dev;
-}
-
-/** Create info about device endpoint.
- *
- * @param endpoint Endpoint number.
- * @param direction Endpoint data direction.
- * @param transfer_type Transfer type of the endpoint.
- * @return Endpoint info structure.
- */
-static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
-    usb_direction_t direction, usb_transfer_type_t transfer_type)
-{
-	usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
-	ep->data_toggle = 0;
-	ep->direction = direction;
-	ep->transfer_type = transfer_type;
-	ep->endpoint = endpoint;
-
-	return ep;
-}
-
-/** Marks given transfer as done.
- *
- * @param transfer Transfer to be completed.
- */
-static void transfer_mark_complete(transfer_info_t *transfer)
-{
-	fibril_mutex_lock(&transfer->condvar_guard);
-	transfer->done = true;
-	fibril_condvar_signal(&transfer->condvar);
-	fibril_mutex_unlock(&transfer->condvar_guard);
-}
-
-/** Callback for OUT transfers.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void callback_out(usb_hc_device_t *hc,
-    usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-
-	/*
-	 * For out transfers, marking them complete is enough.
-	 * No other processing is necessary.
-	 */
-	transfer_mark_complete(transfer);
-}
-
-/** Callback for IN transfers.
- *
- * @param hc Host controller that processed the transfer.
- * @param actual_size Number of actually transferred bytes.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void callback_in(usb_hc_device_t *hc,
-    size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-
-	/*
-	 * Set the number of actually transferred bytes and
-	 * mark the transfer as complete.
-	 */
-	if (transfer->size_transferred != NULL) {
-		*transfer->size_transferred = actual_size;
-	}
-
-	transfer_mark_complete(transfer);
-}
-
-static int async_transfer_out(usb_hc_device_t *hc,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *data, size_t size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_out == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type));
-
-	int rc = hc->transfer_ops->transfer_out(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    callback_out, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-static int async_transfer_setup(usb_hc_device_t *hc,
-    usb_target_t target, usb_transfer_type_t transfer_type,
-    void *data, size_t size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_setup == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type));
-
-	int rc = hc->transfer_ops->transfer_setup(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    callback_out, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-static int async_transfer_in(usb_hc_device_t *hc, usb_target_t target,
-    usb_transfer_type_t transfer_type,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_in == NULL)) {
-		return ENOTSUP;
-	}
-
-	/* This creation of the device on the fly is just a workaround. */
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_IN, transfer_type));
-	transfer->size_transferred = actual_size;
-
-	int rc = hc->transfer_ops->transfer_in(hc,
-	    transfer->device, transfer->endpoint,
-	    buffer, size,
-	    callback_in, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	*handle = (usb_handle_t)transfer;
-
-	return EOK;
-}
-
-
-/** Issue interrupt OUT transfer to HC driven by current task.
- *
- * @param hc Host controller to handle the transfer.
- * @param target Target device address.
- * @param buffer Data buffer.
- * @param size Buffer size.
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_interrupt_out(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_INTERRUPT, buffer, size, handle);
-}
-
-
-/** Issue interrupt IN transfer to HC driven by current task.
- *
- * @warning The @p buffer and @p actual_size parameters shall not be
- * touched until this transfer is waited for by usb_hc_async_wait_for().
- *
- * @param hc Host controller to handle the transfer.
- * @param target Target device address.
- * @param buffer Data buffer.
- * @param size Buffer size.
- * @param actual_size Size of actually transferred data.
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_interrupt_in(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_INTERRUPT, buffer, size, actual_size, handle);
-}
-
-int usb_hc_async_control_write_setup(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_setup(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_write_data(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_write_status(usb_hc_device_t *hc, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_CONTROL, NULL, 0, NULL, handle);
-}
-
-int usb_hc_async_control_read_setup(usb_hc_device_t *hc, usb_target_t target,
-    void *data, size_t size, usb_handle_t *handle)
-{
-	return async_transfer_setup(hc, target,
-	    USB_TRANSFER_CONTROL, data, size, handle);
-}
-
-int usb_hc_async_control_read_data(usb_hc_device_t *hc, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_transfer_in(hc, target,
-	    USB_TRANSFER_CONTROL, buffer, size, actual_size, handle);
-}
-
-int usb_hc_async_control_read_status(usb_hc_device_t *hc, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_transfer_out(hc, target,
-	    USB_TRANSFER_CONTROL, NULL, 0, handle);
-}
-
-/** Wait for transfer to complete.
- *
- * @param handle Transfer handle.
- * @return Error code.
- */
-int usb_hc_async_wait_for(usb_handle_t handle)
-{
-	transfer_info_t *transfer = (transfer_info_t *) handle;
-	if (transfer == NULL) {
-		return ENOENT;
-	}
-
-	fibril_mutex_lock(&transfer->condvar_guard);
-	while (!transfer->done) {
-		fibril_condvar_wait(&transfer->condvar, &transfer->condvar_guard);
-	}
-	fibril_mutex_unlock(&transfer->condvar_guard);
-
-	transfer_info_destroy(transfer);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/pipes.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB endpoint pipes miscellaneous functions.
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/debug.h>
+#include <usbhc_iface.h>
+#include <usb_iface.h>
+#include <devman.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Tell USB address assigned to given device.
+ *
+ * @param phone Phone to parent device.
+ * @param dev Device in question.
+ * @return USB address or error code.
+ */
+static usb_address_t get_my_address(int phone, ddf_dev_t *dev)
+{
+	sysarg_t address;
+
+
+	/*
+	 * We are sending special value as a handle - zero - to get
+	 * handle of the parent function (that handle was used
+	 * when registering our device @p dev.
+	 */
+	int rc = async_req_2_1(phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_ADDRESS,
+	    0, &address);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	return (usb_address_t) address;
+}
+
+/** Tell USB interface assigned to given device.
+ *
+ * @param device Device in question.
+ * @return Interface number (negative code means any).
+ */
+int usb_device_get_assigned_interface(ddf_dev_t *device)
+{
+	int parent_phone = devman_parent_device_connect(device->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return -1;
+	}
+
+	sysarg_t iface_no;
+	int rc = async_req_2_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_INTERFACE,
+	    device->handle, &iface_no);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return -1;
+	}
+
+	return (int) iface_no;
+}
+
+/** Initialize connection to USB device.
+ *
+ * @param connection Connection structure to be initialized.
+ * @param device Generic device backing the USB device.
+ * @return Error code.
+ */
+int usb_device_connection_initialize_from_device(
+    usb_device_connection_t *connection, ddf_dev_t *dev)
+{
+	assert(connection);
+	assert(dev);
+
+	int rc;
+	devman_handle_t hc_handle;
+	usb_address_t my_address;
+
+	rc = usb_hc_find(dev->handle, &hc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	int parent_phone = devman_parent_device_connect(dev->handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	my_address = get_my_address(parent_phone, dev);
+	if (my_address < 0) {
+		rc = my_address;
+		goto leave;
+	}
+
+	rc = usb_device_connection_initialize(connection,
+	    hc_handle, my_address);
+
+leave:
+	async_hangup(parent_phone);
+	return rc;
+}
+
+/** Initialize connection to USB device.
+ *
+ * @param connection Connection structure to be initialized.
+ * @param host_controller_handle Devman handle of host controller device is
+ * 	connected to.
+ * @param device_address Device USB address.
+ * @return Error code.
+ */
+int usb_device_connection_initialize(usb_device_connection_t *connection,
+    devman_handle_t host_controller_handle, usb_address_t device_address)
+{
+	assert(connection);
+
+	if ((device_address < 0) || (device_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+
+	connection->hc_handle = host_controller_handle;
+	connection->address = device_address;
+
+	return EOK;
+}
+
+/** Initialize connection to USB device on default address.
+ *
+ * @param dev_connection Device connection structure to be initialized.
+ * @param hc_connection Initialized connection to host controller.
+ * @return Error code.
+ */
+int usb_device_connection_initialize_on_default_address(
+    usb_device_connection_t *dev_connection,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(dev_connection);
+
+	if (hc_connection == NULL) {
+		return EBADMEM;
+	}
+
+	return usb_device_connection_initialize(dev_connection,
+	    hc_connection->hc_handle, (usb_address_t) 0);
+}
+
+
+/** Start a session on the endpoint pipe.
+ *
+ * A session is something inside what any communication occurs.
+ * It is expected that sessions would be started right before the transfer
+ * and ended - see usb_endpoint_pipe_end_session() - after the last
+ * transfer.
+ * The reason for this is that session actually opens some communication
+ * channel to the host controller (or to the physical hardware if you
+ * wish) and thus it involves acquiring kernel resources.
+ * Since they are limited, sessions shall not be longer than strictly
+ * necessary.
+ *
+ * @param pipe Endpoint pipe to start the session on.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *pipe)
+{
+	assert(pipe);
+
+	if (usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBUSY;
+	}
+
+	int phone = devman_device_connect(pipe->wire->hc_handle, 0);
+	if (phone < 0) {
+		return phone;
+	}
+
+	pipe->hc_phone = phone;
+
+	return EOK;
+}
+
+
+/** Ends a session on the endpoint pipe.
+ *
+ * @see usb_endpoint_pipe_start_session
+ *
+ * @param pipe Endpoint pipe to end the session on.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_end_session(usb_endpoint_pipe_t *pipe)
+{
+	assert(pipe);
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return ENOENT;
+	}
+
+	int rc = async_hangup(pipe->hc_phone);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	pipe->hc_phone = -1;
+
+	return EOK;
+}
+
+/** Tell whether a session is started (open) on the endpoint pipe.
+ *
+ * The expected usage of this function is in assertions for some
+ * nested functions.
+ *
+ * @param pipe Endpoint pipe in question.
+ * @return Whether @p pipe has opened a session.
+ */
+bool usb_endpoint_pipe_is_session_started(usb_endpoint_pipe_t *pipe)
+{
+	return (pipe->hc_phone >= 0);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/pipesinit.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Initialization of endpoint pipes.
+ *
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <usb/dp.h>
+#include <errno.h>
+#include <assert.h>
+
+
+#define NESTING(parentname, childname) \
+	{ \
+		.child = USB_DESCTYPE_##childname, \
+		.parent = USB_DESCTYPE_##parentname, \
+	}
+#define LAST_NESTING { -1, -1 }
+
+/** Nesting pairs of standard descriptors. */
+static usb_dp_descriptor_nesting_t descriptor_nesting[] = {
+	NESTING(CONFIGURATION, INTERFACE),
+	NESTING(INTERFACE, ENDPOINT),
+	NESTING(INTERFACE, HUB),
+	NESTING(INTERFACE, HID),
+	NESTING(HID, HID_REPORT),
+	LAST_NESTING
+};
+
+/** Tells whether given descriptor is of endpoint type.
+ *
+ * @param descriptor Descriptor in question.
+ * @return Whether the given descriptor is endpoint descriptor.
+ */
+static inline bool is_endpoint_descriptor(uint8_t *descriptor)
+{
+	return descriptor[1] == USB_DESCTYPE_ENDPOINT;
+}
+
+/** Tells whether found endpoint corresponds to endpoint described by user.
+ *
+ * @param wanted Endpoint description as entered by driver author.
+ * @param found Endpoint description obtained from endpoint descriptor.
+ * @return Whether the @p found descriptor fits the @p wanted descriptor.
+ */
+static bool endpoint_fits_description(const usb_endpoint_description_t *wanted,
+    usb_endpoint_description_t *found)
+{
+#define _SAME(fieldname) ((wanted->fieldname) == (found->fieldname))
+
+	if (!_SAME(direction)) {
+		return false;
+	}
+
+	if (!_SAME(transfer_type)) {
+		return false;
+	}
+
+	if ((wanted->interface_class >= 0) && !_SAME(interface_class)) {
+		return false;
+	}
+
+	if ((wanted->interface_subclass >= 0) && !_SAME(interface_subclass)) {
+		return false;
+	}
+
+	if ((wanted->interface_protocol >= 0) && !_SAME(interface_protocol)) {
+		return false;
+	}
+
+#undef _SAME
+
+	return true;
+}
+
+/** Find endpoint mapping for a found endpoint.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param found_endpoint Description of found endpoint.
+ * @param interface_number Number of currently processed interface.
+ * @return Endpoint mapping corresponding to @p found_endpoint.
+ * @retval NULL No corresponding endpoint found.
+ */
+static usb_endpoint_mapping_t *find_endpoint_mapping(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_endpoint_description_t *found_endpoint,
+    int interface_number)
+{
+	while (mapping_count > 0) {
+		bool interface_number_fits = (mapping->interface_no < 0)
+		    || (mapping->interface_no == interface_number);
+
+		bool endpoint_descriptions_fits = endpoint_fits_description(
+		    mapping->description, found_endpoint);
+
+		if (interface_number_fits && endpoint_descriptions_fits) {
+			return mapping;
+		}
+
+		mapping++;
+		mapping_count--;
+	}
+	return NULL;
+}
+
+/** Process endpoint descriptor.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param interface Interface descriptor under which belongs the @p endpoint.
+ * @param endpoint Endpoint descriptor.
+ * @param wire Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+static int process_endpoint(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_standard_interface_descriptor_t *interface,
+    usb_standard_endpoint_descriptor_t *endpoint,
+    usb_device_connection_t *wire)
+{
+	usb_endpoint_description_t description;
+
+	/*
+	 * Get endpoint characteristics.
+	 */
+
+	/* Actual endpoint number is in bits 0..3 */
+	usb_endpoint_t ep_no = endpoint->endpoint_address & 0x0F;
+
+	/* Endpoint direction is set by bit 7 */
+	description.direction = (endpoint->endpoint_address & 128)
+	    ? USB_DIRECTION_IN : USB_DIRECTION_OUT;
+	/* Transfer type is in bits 0..2 and the enum values corresponds 1:1 */
+	description.transfer_type = endpoint->attributes & 3;
+
+	/*
+	 * Get interface characteristics.
+	 */
+	description.interface_class = interface->interface_class;
+	description.interface_subclass = interface->interface_subclass;
+	description.interface_protocol = interface->interface_protocol;
+
+	/*
+	 * Find the most fitting mapping and initialize the pipe.
+	 */
+	usb_endpoint_mapping_t *ep_mapping = find_endpoint_mapping(mapping,
+	    mapping_count, &description, interface->interface_number);
+	if (ep_mapping == NULL) {
+		return ENOENT;
+	}
+
+	if (ep_mapping->pipe == NULL) {
+		return EBADMEM;
+	}
+	if (ep_mapping->present) {
+		return EEXISTS;
+	}
+
+	int rc = usb_endpoint_pipe_initialize(ep_mapping->pipe, wire,
+	    ep_no, description.transfer_type, endpoint->max_packet_size,
+	    description.direction);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	ep_mapping->present = true;
+	ep_mapping->descriptor = endpoint;
+	ep_mapping->interface = interface;
+
+	return EOK;
+}
+
+/** Process whole USB interface.
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param parser Descriptor parser.
+ * @param parser_data Descriptor parser data.
+ * @param interface_descriptor Interface descriptor.
+ * @return Error code.
+ */
+static int process_interface(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    usb_dp_parser_t *parser, usb_dp_parser_data_t *parser_data,
+    uint8_t *interface_descriptor)
+{
+	uint8_t *descriptor = usb_dp_get_nested_descriptor(parser,
+	    parser_data, interface_descriptor);
+
+	if (descriptor == NULL) {
+		return ENOENT;
+	}
+
+	do {
+		if (is_endpoint_descriptor(descriptor)) {
+			(void) process_endpoint(mapping, mapping_count,
+			    (usb_standard_interface_descriptor_t *)
+			        interface_descriptor,
+			    (usb_standard_endpoint_descriptor_t *)
+			        descriptor,
+			    (usb_device_connection_t *) parser_data->arg);
+		}
+
+		descriptor = usb_dp_get_sibling_descriptor(parser, parser_data,
+		    interface_descriptor, descriptor);
+	} while (descriptor != NULL);
+
+	return EOK;
+}
+
+/** Initialize endpoint pipes from configuration descriptor.
+ *
+ * The mapping array is expected to conform to following rules:
+ * - @c pipe must point to already allocated structure with uninitialized pipe
+ * - @c description must point to prepared endpoint description
+ * - @c descriptor does not need to be initialized (will be overwritten)
+ * - @c interface does not need to be initialized (will be overwritten)
+ * - @c present does not need to be initialized (will be overwritten)
+ *
+ * After processing the configuration descriptor, the mapping is updated
+ * in the following fashion:
+ * - @c present will be set to @c true when the endpoint was found in the
+ *   configuration
+ * - @c descriptor will point inside the configuration descriptor to endpoint
+ *   corresponding to given description (or NULL for not found descriptor)
+ * - @c interface will point inside the configuration descriptor to interface
+ *   descriptor the endpoint @c descriptor belongs to (or NULL for not found
+ *   descriptor)
+ * - @c pipe will be initialized when found, otherwise left untouched
+ * - @c description will be untouched under all circumstances
+ *
+ * @param mapping Endpoint mapping list.
+ * @param mapping_count Number of endpoint mappings in @p mapping.
+ * @param configuration_descriptor Full configuration descriptor (is expected
+ *	to be in USB endianness: i.e. as-is after being retrieved from
+ *	the device).
+ * @param configuration_descriptor_size Size of @p configuration_descriptor
+ *	in bytes.
+ * @param connection Connection backing the endpoint pipes.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize_from_configuration(
+    usb_endpoint_mapping_t *mapping, size_t mapping_count,
+    uint8_t *configuration_descriptor, size_t configuration_descriptor_size,
+    usb_device_connection_t *connection)
+{
+	assert(connection);
+
+	if (configuration_descriptor == NULL) {
+		return EBADMEM;
+	}
+	if (configuration_descriptor_size
+	    < sizeof(usb_standard_configuration_descriptor_t)) {
+		return ERANGE;
+	}
+
+	/*
+	 * Go through the mapping and set all endpoints to not present.
+	 */
+	size_t i;
+	for (i = 0; i < mapping_count; i++) {
+		mapping[i].present = false;
+		mapping[i].descriptor = NULL;
+		mapping[i].interface = NULL;
+	}
+
+	/*
+	 * Prepare the descriptor parser.
+	 */
+	usb_dp_parser_t dp_parser = {
+		.nesting = descriptor_nesting
+	};
+	usb_dp_parser_data_t dp_data = {
+		.data = configuration_descriptor,
+		.size = configuration_descriptor_size,
+		.arg = connection
+	};
+
+	/*
+	 * Iterate through all interfaces.
+	 */
+	uint8_t *interface = usb_dp_get_nested_descriptor(&dp_parser,
+	    &dp_data, configuration_descriptor);
+	if (interface == NULL) {
+		return ENOENT;
+	}
+	do {
+		(void) process_interface(mapping, mapping_count,
+		    &dp_parser, &dp_data,
+		    interface);
+		interface = usb_dp_get_sibling_descriptor(&dp_parser, &dp_data,
+		    configuration_descriptor, interface);
+	} while (interface != NULL);
+
+	return EOK;
+}
+
+/** Initialize USB endpoint pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @param endpoint_no Endpoint number (in USB 1.1 in range 0 to 15).
+ * @param transfer_type Transfer type (e.g. interrupt or bulk).
+ * @param max_packet_size Maximum packet size in bytes.
+ * @param direction Endpoint direction (in/out).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize(usb_endpoint_pipe_t *pipe,
+    usb_device_connection_t *connection, usb_endpoint_t endpoint_no,
+    usb_transfer_type_t transfer_type, size_t max_packet_size,
+    usb_direction_t direction)
+{
+	assert(pipe);
+	assert(connection);
+
+	pipe->wire = connection;
+	pipe->hc_phone = -1;
+	pipe->endpoint_no = endpoint_no;
+	pipe->transfer_type = transfer_type;
+	pipe->max_packet_size = max_packet_size;
+	pipe->direction = direction;
+
+	return EOK;
+}
+
+
+/** Initialize USB endpoint pipe as the default zero control pipe.
+ *
+ * @param pipe Endpoint pipe to be initialized.
+ * @param connection Connection to the USB device backing this pipe (the wire).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_initialize_default_control(usb_endpoint_pipe_t *pipe,
+    usb_device_connection_t *connection)
+{
+	assert(pipe);
+	assert(connection);
+
+	int rc = usb_endpoint_pipe_initialize(pipe, connection,
+	    0, USB_TRANSFER_CONTROL, 8, USB_DIRECTION_BOTH);
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/pipesio.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Input and output functions (reads and writes) on endpoint pipes.
+ *
+ * Note on synchronousness of the operations: there is ABSOLUTELY NO
+ * guarantee that a call to particular function will not trigger a fibril
+ * switch.
+ *
+ * Note about the implementation: the transfer requests are always divided
+ * into two functions.
+ * The outer one does checking of input parameters (e.g. that session was
+ * already started, buffers are not NULL etc), while the inner one
+ * (with _no_checks suffix) does the actual IPC (it checks for IPC errors,
+ * obviously).
+ */
+#include <usb/usb.h>
+#include <usb/pipes.h>
+#include <errno.h>
+#include <assert.h>
+#include <usbhc_iface.h>
+
+/** Request an in transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_read_no_checks(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_IN;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_IN;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
+	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(pipe->hc_phone, buffer, size,
+	    &data_request_call);
+
+	if (data_request == 0) {
+		/*
+		 * FIXME:
+		 * How to let the other side know that we want to abort?
+		 */
+		async_wait_for(opening_request, NULL);
+		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) {
+		return (int) data_request_rc;
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*size_transfered = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+
+/** Request a read (in) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[out] buffer Buffer where to store the data.
+ * @param[in] size Size of the buffer (in bytes).
+ * @param[out] size_transfered Number of bytes that were actually transfered.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_read(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size, size_t *size_transfered)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+			return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if (pipe->direction != USB_DIRECTION_IN) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	size_t act_size = 0;
+	int rc;
+
+	rc = usb_endpoint_pipe_read_no_checks(pipe, buffer, size, &act_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (size_transfered != NULL) {
+		*size_transfered = act_size;
+	}
+
+	return EOK;
+}
+
+
+
+
+/** Request an out transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_write_no_check(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	/*
+	 * Get corresponding IPC method.
+	 * In future, replace with static array of mappings
+	 * transfer type -> method.
+	 */
+	usbhc_iface_funcs_t ipc_method;
+	switch (pipe->transfer_type) {
+		case USB_TRANSFER_INTERRUPT:
+			ipc_method = IPC_M_USBHC_INTERRUPT_OUT;
+			break;
+		case USB_TRANSFER_BULK:
+			ipc_method = IPC_M_USBHC_BULK_OUT;
+			break;
+		default:
+			return ENOTSUP;
+	}
+
+	/*
+	 * Make call identifying target USB device and type of transfer.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), ipc_method,
+	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the data.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone, buffer, size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a write (out) transfer on an endpoint pipe.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] buffer Buffer with data to transfer.
+ * @param[in] size Size of the buffer (in bytes).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_write(usb_endpoint_pipe_t *pipe,
+    void *buffer, size_t size)
+{
+	assert(pipe);
+
+	if (buffer == NULL) {
+		return EINVAL;
+	}
+
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if (pipe->direction != USB_DIRECTION_OUT) {
+		return EBADF;
+	}
+
+	if (pipe->transfer_type == USB_TRANSFER_CONTROL) {
+		return EBADF;
+	}
+
+	int rc = usb_endpoint_pipe_write_no_check(pipe, buffer, size);
+
+	return rc;
+}
+
+
+/** Request a control read transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_control_read_no_check(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	aid_t opening_request = async_send_4(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_READ,
+	    pipe->wire->address, pipe->endpoint_no,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Retrieve the data.
+	 */
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(pipe->hc_phone,
+	    data_buffer, data_buffer_size,
+	    &data_request_call);
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		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) {
+		return (int) data_request_rc;
+	}
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	*data_transfered_size = IPC_GET_ARG2(data_request_call);
+
+	return EOK;
+}
+
+/** Request a control read transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[out] data_buffer Buffer for incoming data.
+ * @param[in] data_buffer_size Size of the buffer for incoming data (in bytes).
+ * @param[out] data_transfered_size Number of bytes that were actually
+ *                                  transfered during the DATA stage.
+ * @return Error code.
+ */
+int usb_endpoint_pipe_control_read(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) || (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	size_t act_size = 0;
+	int rc = usb_endpoint_pipe_control_read_no_check(pipe,
+	    setup_buffer, setup_buffer_size,
+	    data_buffer, data_buffer_size, &act_size);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (data_transfered_size != NULL) {
+		*data_transfered_size = act_size;
+	}
+
+	return EOK;
+}
+
+
+/** Request a control write transfer, no checking of input parameters.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+static int usb_endpoint_pipe_control_write_no_check(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	/*
+	 * Make call identifying target USB device and control transfer type.
+	 */
+	aid_t opening_request = async_send_5(pipe->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_CONTROL_WRITE,
+	    pipe->wire->address, pipe->endpoint_no,
+	    data_buffer_size,
+	    pipe->max_packet_size,
+	    NULL);
+	if (opening_request == 0) {
+		return ENOMEM;
+	}
+
+	/*
+	 * Send the setup packet.
+	 */
+	int rc = async_data_write_start(pipe->hc_phone,
+	    setup_buffer, setup_buffer_size);
+	if (rc != EOK) {
+		async_wait_for(opening_request, NULL);
+		return rc;
+	}
+
+	/*
+	 * Send the data (if any).
+	 */
+	if (data_buffer_size > 0) {
+		rc = async_data_write_start(pipe->hc_phone,
+		    data_buffer, data_buffer_size);
+		if (rc != EOK) {
+			async_wait_for(opening_request, NULL);
+			return rc;
+		}
+	}
+
+	/*
+	 * Wait for the answer.
+	 */
+	sysarg_t opening_request_rc;
+	async_wait_for(opening_request, &opening_request_rc);
+
+	return (int) opening_request_rc;
+}
+
+/** Request a control write transfer on an endpoint pipe.
+ *
+ * This function encapsulates all three stages of a control transfer.
+ *
+ * @param[in] pipe Pipe used for the transfer.
+ * @param[in] setup_buffer Buffer with the setup packet.
+ * @param[in] setup_buffer_size Size of the setup packet (in bytes).
+ * @param[in] data_buffer Buffer with data to be sent.
+ * @param[in] data_buffer_size Size of the buffer with outgoing data (in bytes).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_control_write(usb_endpoint_pipe_t *pipe,
+    void *setup_buffer, size_t setup_buffer_size,
+    void *data_buffer, size_t data_buffer_size)
+{
+	assert(pipe);
+
+	if ((setup_buffer == NULL) || (setup_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer == NULL) && (data_buffer_size > 0)) {
+		return EINVAL;
+	}
+
+	if ((data_buffer != NULL) && (data_buffer_size == 0)) {
+		return EINVAL;
+	}
+
+	if (!usb_endpoint_pipe_is_session_started(pipe)) {
+		return EBADF;
+	}
+
+	if ((pipe->direction != USB_DIRECTION_BOTH)
+	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
+		return EBADF;
+	}
+
+	int rc = usb_endpoint_pipe_control_write_no_check(pipe,
+	    setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
+
+	return rc;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/recognise.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -33,36 +33,20 @@
  * @brief Functions for recognising kind of attached devices.
  */
-#include <usb_iface.h>
-#include <usb/usbdrv.h>
+#include <sys/types.h>
+#include <fibril_synch.h>
+#include <usb/pipes.h>
+#include <usb/recognise.h>
+#include <usb/ddfiface.h>
+#include <usb/request.h>
 #include <usb/classes/classes.h>
 #include <stdio.h>
 #include <errno.h>
-
-static int usb_iface_get_hc_handle(device_t *dev, devman_handle_t *handle)
-{
-	assert(dev);
-	assert(dev->parent != NULL);
-
-	device_t *parent = dev->parent;
-
-	if (parent->ops && parent->ops->interfaces[USB_DEV_IFACE]) {
-		usb_iface_t *usb_iface
-		    = (usb_iface_t *) parent->ops->interfaces[USB_DEV_IFACE];
-		assert(usb_iface != NULL);
-		if (usb_iface->get_hc_handle) {
-			int rc = usb_iface->get_hc_handle(parent, handle);
-			return rc;
-		}
-	}
-
-	return ENOTSUP;
-}
-
-static usb_iface_t usb_iface = {
-	.get_hc_handle = usb_iface_get_hc_handle
-};
-
-static device_ops_t child_ops = {
-	.interfaces[USB_DEV_IFACE] = &usb_iface
+#include <assert.h>
+
+static size_t device_name_index = 0;
+static FIBRIL_MUTEX_INITIALIZE(device_name_index_mutex);
+
+ddf_dev_ops_t child_ops = {
+	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_child_impl
 };
 
@@ -129,4 +113,127 @@
 }
 
+#define ADD_MATCHID_OR_RETURN(match_ids, score, format, ...) \
+	do { \
+		int __rc = usb_add_match_id((match_ids), (score), \
+		    format, ##__VA_ARGS__); \
+		if (__rc != EOK) { \
+			return __rc; \
+		} \
+	} while (0)
+
+/** Create device match ids based on its interface.
+ *
+ * @param[in] descriptor Interface descriptor.
+ * @param[out] matches Initialized list of match ids.
+ * @return Error code (the two mentioned are not the only ones).
+ * @retval EINVAL Invalid input parameters (expects non NULL pointers).
+ * @retval ENOENT Interface does not specify class.
+ */
+int usb_device_create_match_ids_from_interface(
+    const usb_standard_device_descriptor_t *desc_device,
+    const usb_standard_interface_descriptor_t *desc_interface,
+    match_id_list_t *matches)
+{
+	if (desc_interface == NULL) {
+		return EINVAL;
+	}
+	if (matches == NULL) {
+		return EINVAL;
+	}
+
+	if (desc_interface->interface_class == USB_CLASS_USE_INTERFACE) {
+		return ENOENT;
+	}
+
+	const char *classname = usb_str_class(desc_interface->interface_class);
+	assert(classname != NULL);
+
+#define IFACE_PROTOCOL_FMT "interface&class=%s&subclass=0x%02x&protocol=0x%02x"
+#define IFACE_PROTOCOL_ARGS classname, desc_interface->interface_subclass, \
+    desc_interface->interface_protocol
+
+#define IFACE_SUBCLASS_FMT "interface&class=%s&subclass=0x%02x"
+#define IFACE_SUBCLASS_ARGS classname, desc_interface->interface_subclass
+
+#define IFACE_CLASS_FMT "interface&class=%s"
+#define IFACE_CLASS_ARGS classname
+
+#define VENDOR_RELEASE_FMT "vendor=0x%04x&product=0x%04x&release=" BCD_FMT
+#define VENDOR_RELEASE_ARGS desc_device->vendor_id, desc_device->product_id, \
+    BCD_ARGS(desc_device->device_version)
+
+#define VENDOR_PRODUCT_FMT "vendor=0x%04x&product=0x%04x"
+#define VENDOR_PRODUCT_ARGS desc_device->vendor_id, desc_device->product_id
+
+#define VENDOR_ONLY_FMT "vendor=0x%04x"
+#define VENDOR_ONLY_ARGS desc_device->vendor_id
+
+	/*
+	 * If the vendor is specified, create match ids with vendor with
+	 * higher score.
+	 * Then the same ones without the vendor part.
+	 */
+	if ((desc_device != NULL) && (desc_device->vendor_id != 0)) {
+		/* First, interface matches with device release number. */
+		ADD_MATCHID_OR_RETURN(matches, 250,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 240,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 230,
+		    "usb&" VENDOR_RELEASE_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_RELEASE_ARGS, IFACE_CLASS_ARGS);
+
+		/* Next, interface matches without release number. */
+		ADD_MATCHID_OR_RETURN(matches, 220,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 210,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 200,
+		    "usb&" VENDOR_PRODUCT_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_PRODUCT_ARGS, IFACE_CLASS_ARGS);
+
+		/* Finally, interface matches with only vendor. */
+		ADD_MATCHID_OR_RETURN(matches, 190,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_PROTOCOL_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_PROTOCOL_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 180,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_SUBCLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_SUBCLASS_ARGS);
+		ADD_MATCHID_OR_RETURN(matches, 170,
+		    "usb&" VENDOR_ONLY_FMT "&" IFACE_CLASS_FMT,
+		    VENDOR_ONLY_ARGS, IFACE_CLASS_ARGS);
+	}
+
+	/* Now, the same but without any vendor specification. */
+	ADD_MATCHID_OR_RETURN(matches, 160,
+	    "usb&" IFACE_PROTOCOL_FMT,
+	    IFACE_PROTOCOL_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 150,
+	    "usb&" IFACE_SUBCLASS_FMT,
+	    IFACE_SUBCLASS_ARGS);
+	ADD_MATCHID_OR_RETURN(matches, 140,
+	    "usb&" IFACE_CLASS_FMT,
+	    IFACE_CLASS_ARGS);
+
+#undef IFACE_PROTOCOL_FMT
+#undef IFACE_PROTOCOL_ARGS
+#undef IFACE_SUBCLASS_FMT
+#undef IFACE_SUBCLASS_ARGS
+#undef IFACE_CLASS_FMT
+#undef IFACE_CLASS_ARGS
+#undef VENDOR_RELEASE_FMT
+#undef VENDOR_RELEASE_ARGS
+#undef VENDOR_PRODUCT_FMT
+#undef VENDOR_PRODUCT_ARGS
+#undef VENDOR_ONLY_FMT
+#undef VENDOR_ONLY_ARGS
+
+	return EOK;
+}
+
 /** Create DDF match ids from USB device descriptor.
  *
@@ -135,10 +242,8 @@
  * @return Error code.
  */
-int usb_drv_create_match_ids_from_device_descriptor(
-    match_id_list_t *matches,
-    const usb_standard_device_descriptor_t *device_descriptor)
+int usb_device_create_match_ids_from_device_descriptor(
+    const usb_standard_device_descriptor_t *device_descriptor,
+    match_id_list_t *matches)
 {
-	int rc;
-	
 	/*
 	 * Unless the vendor id is 0, the pair idVendor-idProduct
@@ -147,32 +252,26 @@
 	if (device_descriptor->vendor_id != 0) {
 		/* First, with release number. */
-		rc = usb_add_match_id(matches, 100,
-		    "usb&vendor=%d&product=%d&release=" BCD_FMT,
+		ADD_MATCHID_OR_RETURN(matches, 100,
+		    "usb&vendor=0x%04x&product=0x%04x&release=" BCD_FMT,
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id,
 		    BCD_ARGS(device_descriptor->device_version));
-		if (rc != EOK) {
-			return rc;
-		}
 		
 		/* Next, without release number. */
-		rc = usb_add_match_id(matches, 90, "usb&vendor=%d&product=%d",
+		ADD_MATCHID_OR_RETURN(matches, 90,
+		    "usb&vendor=0x%04x&product=0x%04x",
 		    (int) device_descriptor->vendor_id,
 		    (int) device_descriptor->product_id);
-		if (rc != EOK) {
-			return rc;
-		}
 	}	
 
 	/*
 	 * If the device class points to interface we skip adding
-	 * class directly.
+	 * class directly but we add a multi interface device.
 	 */
 	if (device_descriptor->device_class != USB_CLASS_USE_INTERFACE) {
-		rc = usb_add_match_id(matches, 50, "usb&class=%s",
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&class=%s",
 		    usb_str_class(device_descriptor->device_class));
-		if (rc != EOK) {
-			return rc;
-		}
+	} else {
+		ADD_MATCHID_OR_RETURN(matches, 50, "usb&mid");
 	}
 	
@@ -180,177 +279,85 @@
 }
 
-/** Create DDF match ids from USB configuration descriptor.
- * The configuration descriptor is expected to be in the complete form,
- * i.e. including interface, endpoint etc. descriptors.
- *
- * @param matches List of match ids to extend.
- * @param config_descriptor Configuration descriptor returned by given device.
- * @param total_size Size of the @p config_descriptor.
+
+/** Create match ids describing attached device.
+ *
+ * @warning The list of match ids @p matches may change even when
+ * function exits with error.
+ *
+ * @param ctrl_pipe Control pipe to given device (session must be already
+ *	started).
+ * @param matches Initialized list of match ids.
  * @return Error code.
  */
-int usb_drv_create_match_ids_from_configuration_descriptor(
-    match_id_list_t *matches,
-    const void *config_descriptor, size_t total_size)
+int usb_device_create_match_ids(usb_endpoint_pipe_t *ctrl_pipe,
+    match_id_list_t *matches)
 {
-	/*
-	 * Iterate through config descriptor to find the interface
-	 * descriptors.
-	 */
-	size_t position = sizeof(usb_standard_configuration_descriptor_t);
-	while (position + 1 < total_size) {
-		uint8_t *current_descriptor
-		    = ((uint8_t *) config_descriptor) + position;
-		uint8_t cur_descr_len = current_descriptor[0];
-		uint8_t cur_descr_type = current_descriptor[1];
-		
-		position += cur_descr_len;
-		
-		if (cur_descr_type != USB_DESCTYPE_INTERFACE) {
-			continue;
-		}
-		
-		/*
-		 * Finally, we found an interface descriptor.
-		 */
-		usb_standard_interface_descriptor_t *interface
-		    = (usb_standard_interface_descriptor_t *)
-		    current_descriptor;
-		
-		int rc = usb_add_match_id(matches, 50,
-		    "usb&interface&class=%s",
-		    usb_str_class(interface->interface_class));
-		if (rc != EOK) {
-			return rc;
-		}
-	}
-	
+	int rc;
+	/*
+	 * Retrieve device descriptor and add matches from it.
+	 */
+	usb_standard_device_descriptor_t device_descriptor;
+
+	rc = usb_request_get_device_descriptor(ctrl_pipe, &device_descriptor);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_device_create_match_ids_from_device_descriptor(
+	    &device_descriptor, matches);
+	if (rc != EOK) {
+		return rc;
+	}
+
 	return EOK;
 }
 
-/** Add match ids based on configuration descriptor.
- *
- * @param hc Open phone to host controller.
- * @param matches Match ids list to add matches to.
- * @param address USB address of the attached device.
+/** Probe for device kind and register it in devman.
+ *
+ * @param[in] address Address of the (unknown) attached device.
+ * @param[in] hc_handle Handle of the host controller.
+ * @param[in] parent Parent device.
+ * @param[out] child_handle Handle of the child device.
  * @return Error code.
  */
-static int usb_add_config_descriptor_match_ids(int hc,
-    match_id_list_t *matches, usb_address_t address,
-    int config_count)
+int usb_device_register_child_in_devman(usb_address_t address,
+    devman_handle_t hc_handle,
+    ddf_dev_t *parent, devman_handle_t *child_handle,
+    ddf_dev_ops_t *dev_ops, void *dev_data, ddf_fun_t **child_fun)
 {
-	int final_rc = EOK;
-	
-	int config_index;
-	for (config_index = 0; config_index < config_count; config_index++) {
-		int rc;
-		usb_standard_configuration_descriptor_t config_descriptor;
-		rc = usb_drv_req_get_bare_configuration_descriptor(hc,
-		    address,  config_index, &config_descriptor);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-
-		size_t full_config_descriptor_size;
-		void *full_config_descriptor
-		    = malloc(config_descriptor.total_length);
-		rc = usb_drv_req_get_full_configuration_descriptor(hc,
-		    address, config_index,
-		    full_config_descriptor, config_descriptor.total_length,
-		    &full_config_descriptor_size);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-		if (full_config_descriptor_size
-		    != config_descriptor.total_length) {
-			final_rc = ERANGE;
-			continue;
-		}
-		
-		rc = usb_drv_create_match_ids_from_configuration_descriptor(
-		    matches,
-		    full_config_descriptor, full_config_descriptor_size);
-		if (rc != EOK) {
-			final_rc = rc;
-			continue;
-		}
-		
-	}
-	
-	return final_rc;
-}
-
-/** Create match ids describing attached device.
- *
- * @warning The list of match ids @p matches may change even when
- * function exits with error.
- *
- * @param hc Open phone to host controller.
- * @param matches Initialized list of match ids.
- * @param address USB address of the attached device.
- * @return Error code.
- */
-int usb_drv_create_device_match_ids(int hc, match_id_list_t *matches,
-    usb_address_t address)
-{
-	int rc;
-	
-	/*
-	 * Retrieve device descriptor and add matches from it.
-	 */
-	usb_standard_device_descriptor_t device_descriptor;
-
-	rc = usb_drv_req_get_device_descriptor(hc, address,
-	    &device_descriptor);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	rc = usb_drv_create_match_ids_from_device_descriptor(matches,
-	    &device_descriptor);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	/*
-	 * Go through all configurations and add matches
-	 * based on interface class.
-	 */
-	rc = usb_add_config_descriptor_match_ids(hc, matches,
-	    address, device_descriptor.configuration_count);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/*
-	 * As a fallback, provide the simplest match id possible.
-	 */
-	rc = usb_add_match_id(matches, 1, "usb&fallback");
-	if (rc != EOK) {
-		return rc;
-	}
-
-	return EOK;
-}
-
-
-/** Probe for device kind and register it in devman.
- *
- * @param hc Open phone to the host controller.
- * @param parent Parent device.
- * @param address Address of the (unknown) attached device.
- * @return Error code.
- */
-int usb_drv_register_child_in_devman(int hc, device_t *parent,
-    usb_address_t address, devman_handle_t *child_handle)
-{
-	static size_t device_name_index = 0;
-
-	device_t *child = NULL;
+	size_t this_device_name_index;
+
+	fibril_mutex_lock(&device_name_index_mutex);
+	this_device_name_index = device_name_index;
+	device_name_index++;
+	fibril_mutex_unlock(&device_name_index_mutex);
+
+	ddf_fun_t *child = NULL;
 	char *child_name = NULL;
 	int rc;
-
-	child = create_device();
+	usb_device_connection_t dev_connection;
+	usb_endpoint_pipe_t ctrl_pipe;
+
+	rc = usb_device_connection_initialize(&dev_connection, hc_handle, address);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_endpoint_pipe_initialize_default_control(&ctrl_pipe,
+	    &dev_connection);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	/*
+	 * TODO: Once the device driver framework support persistent
+	 * naming etc., something more descriptive could be created.
+	 */
+	rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
+	if (rc < 0) {
+		goto failure;
+	}
+
+	child = ddf_fun_create(parent, fun_inner, child_name);
 	if (child == NULL) {
 		rc = ENOMEM;
@@ -358,22 +365,28 @@
 	}
 
-	/*
-	 * TODO: Once the device driver framework support persistent
-	 * naming etc., something more descriptive could be created.
-	 */
-	rc = asprintf(&child_name, "usbdev%02zu", device_name_index);
-	if (rc < 0) {
-		goto failure;
-	}
-	child->parent = parent;
-	child->name = child_name;
-	child->ops = &child_ops;
-	
-	rc = usb_drv_create_device_match_ids(hc, &child->match_ids, address);
-	if (rc != EOK) {
-		goto failure;
-	}
-
-	rc = child_device_register(child, parent);
+	if (dev_ops != NULL) {
+		child->ops = dev_ops;
+	} else {
+		child->ops = &child_ops;
+	}
+
+	child->driver_data = dev_data;
+
+	rc = usb_endpoint_pipe_start_session(&ctrl_pipe);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_device_create_match_ids(&ctrl_pipe, &child->match_ids);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = usb_endpoint_pipe_end_session(&ctrl_pipe);
+	if (rc != EOK) {
+		goto failure;
+	}
+
+	rc = ddf_fun_bind(child);
 	if (rc != EOK) {
 		goto failure;
@@ -383,6 +396,8 @@
 		*child_handle = child->handle;
 	}
-	
-	device_name_index++;
+
+	if (child_fun != NULL) {
+		*child_fun = child;
+	}
 
 	return EOK;
@@ -392,5 +407,5 @@
 		child->name = NULL;
 		/* This takes care of match_id deallocation as well. */
-		delete_device(child);
+		ddf_fun_destroy(child);
 	}
 	if (child_name != NULL) {
@@ -399,5 +414,4 @@
 
 	return rc;
-
 }
 
Index: uspace/lib/usb/src/remotedrv.c
===================================================================
--- uspace/lib/usb/src/remotedrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,437 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief Driver communication for remote drivers (interface implementation).
- */
-#include <usb/hcdhubd.h>
-#include <usbhc_iface.h>
-#include <driver.h>
-#include <bool.h>
-#include <errno.h>
-
-#include "hcdhubd_private.h"
-
-static int remote_get_address(device_t *, devman_handle_t, usb_address_t *);
-
-static int remote_interrupt_out(device_t *, usb_target_t, void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_interrupt_in(device_t *, usb_target_t, void *, size_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-
-static int remote_control_write_setup(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_write_data(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_write_status(device_t *, usb_target_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-
-static int remote_control_read_setup(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-static int remote_control_read_data(device_t *, usb_target_t,
-    void *, size_t,
-    usbhc_iface_transfer_in_callback_t, void *);
-static int remote_control_read_status(device_t *, usb_target_t,
-    usbhc_iface_transfer_out_callback_t, void *);
-
-/** Implementation of USB HC interface. */
-usbhc_iface_t usbhc_interface = {
-	.tell_address = remote_get_address,
-	.interrupt_out = remote_interrupt_out,
-	.interrupt_in = remote_interrupt_in,
-	.control_write_setup = remote_control_write_setup,
-	.control_write_data = remote_control_write_data,
-	.control_write_status = remote_control_write_status,
-	.control_read_setup = remote_control_read_setup,
-	.control_read_data = remote_control_read_data,
-	.control_read_status = remote_control_read_status
-};
-
-/** Get USB address for remote USBHC interface.
- *
- * @param dev Device asked for the information.
- * @param handle Devman handle of the USB device.
- * @param address Storage for obtained address.
- * @return Error code.
- */
-int remote_get_address(device_t *dev, devman_handle_t handle,
-    usb_address_t *address)
-{
-	usb_address_t addr = usb_get_address_by_handle(handle);
-	if (addr < 0) {
-		return addr;
-	}
-
-	*address = addr;
-
-	return EOK;
-}
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Target device. */
-	usb_hcd_attached_device_info_t *device;
-	/** Target endpoint. */
-	usb_hc_endpoint_info_t *endpoint;
-
-	/** Callbacks. */
-	union {
-		/** Callback for outgoing transfers. */
-		usbhc_iface_transfer_out_callback_t out_callback;
-		/** Callback for incoming transfers. */
-		usbhc_iface_transfer_in_callback_t in_callback;
-	};
-
-	/** Custom argument for the callback. */
-	void *arg;
-} transfer_info_t;
-
-/** Create new transfer info.
- *
- * @param device Attached device.
- * @param endpoint Endpoint.
- * @param custom_arg Custom argument.
- * @return Transfer info with pre-filled values.
- */
-static transfer_info_t *transfer_info_create(
-    usb_hcd_attached_device_info_t *device, usb_hc_endpoint_info_t *endpoint,
-    void *custom_arg)
-{
-	transfer_info_t *transfer = malloc(sizeof(transfer_info_t));
-
-	transfer->device = device;
-	transfer->endpoint = endpoint;
-	transfer->arg = custom_arg;
-	transfer->out_callback = NULL;
-	transfer->in_callback = NULL;
-
-	return transfer;
-}
-
-/** Destroy transfer info.
- *
- * @param transfer Transfer to be destroyed.
- */
-static void transfer_info_destroy(transfer_info_t *transfer)
-{
-	free(transfer->device);
-	free(transfer->endpoint);
-	free(transfer);
-}
-
-/** Create info about attached device.
- *
- * @param address Device address.
- * @return Device info structure.
- */
-static usb_hcd_attached_device_info_t *create_attached_device_info(
-    usb_address_t address)
-{
-	usb_hcd_attached_device_info_t *dev
-	    = malloc(sizeof(usb_hcd_attached_device_info_t));
-
-	dev->address = address;
-	dev->endpoint_count = 0;
-	dev->endpoints = NULL;
-	list_initialize(&dev->link);
-
-	return dev;
-}
-
-/** Create info about device endpoint.
- *
- * @param endpoint Endpoint number.
- * @param direction Endpoint data direction.
- * @param transfer_type Transfer type of the endpoint.
- * @return Endpoint info structure.
- */
-static usb_hc_endpoint_info_t *create_endpoint_info(usb_endpoint_t endpoint,
-    usb_direction_t direction, usb_transfer_type_t transfer_type)
-{
-	usb_hc_endpoint_info_t *ep = malloc(sizeof(usb_hc_endpoint_info_t));
-	ep->data_toggle = 0;
-	ep->direction = direction;
-	ep->transfer_type = transfer_type;
-	ep->endpoint = endpoint;
-
-	return ep;
-}
-
-
-
-/** Callback for OUT transfers.
- * This callback is called by implementation of HC operations.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param arg Custom argument.
- */
-static void remote_out_callback(usb_hc_device_t *hc,
-    usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-	transfer->out_callback(hc->generic, outcome, transfer->arg);
-
-	transfer_info_destroy(transfer);
-}
-
-/** Start an OUT transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_out_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_out == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->out_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_out(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_out_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Start a SETUP transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_setup_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_setup == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->out_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_setup(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_out_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Callback for IN transfers.
- * This callback is called by implementation of HC operations.
- *
- * @param hc Host controller that processed the transfer.
- * @param outcome Transfer outcome.
- * @param actual_size Size of actually received data.
- * @param arg Custom argument.
- */
-static void remote_in_callback(usb_hc_device_t *hc,
-    size_t actual_size, usb_transaction_outcome_t outcome, void *arg)
-{
-	transfer_info_t *transfer = (transfer_info_t *) arg;
-	transfer->in_callback(hc->generic, outcome, actual_size, transfer->arg);
-
-	transfer_info_destroy(transfer);
-}
-
-/** Start an IN transfer.
- *
- * @param dev Device that shall process the transfer.
- * @param target Target device for the data.
- * @param transfer_type Transfer type.
- * @param data Data buffer.
- * @param size Size of data buffer.
- * @param callback Callback after transfer is complete.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-static int remote_in_transfer(device_t *dev, usb_target_t target,
-    usb_transfer_type_t transfer_type, void *data, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	usb_hc_device_t *hc = (usb_hc_device_t *) dev->driver_data;
-
-	if ((hc->transfer_ops == NULL)
-	    || (hc->transfer_ops->transfer_in == NULL)) {
-		return ENOTSUP;
-	}
-
-	transfer_info_t *transfer = transfer_info_create(
-	    create_attached_device_info(target.address),
-	    create_endpoint_info(target.endpoint,
-		USB_DIRECTION_OUT, transfer_type),
-	    arg);
-	transfer->in_callback = callback;
-
-	int rc = hc->transfer_ops->transfer_in(hc,
-	    transfer->device, transfer->endpoint,
-	    data, size,
-	    remote_in_callback, transfer);
-
-	if (rc != EOK) {
-		transfer_info_destroy(transfer);
-		return rc;
-	}
-
-	return EOK;
-}
-
-/** Start outgoing interrupt transfer (USBHC remote interface).
- *
- * @param dev Host controller device processing the transfer.
- * @param target Target USB device.
- * @param buffer Data buffer.
- * @param size Data buffer size.
- * @param callback Callback after the transfer is completed.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-int remote_interrupt_out(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(dev, target, USB_TRANSFER_INTERRUPT,
-	    buffer, size, callback, arg);
-}
-
-/** Start incoming interrupt transfer (USBHC remote interface).
- *
- * @param dev Host controller device processing the transfer.
- * @param target Target USB device.
- * @param buffer Data buffer.
- * @param size Data buffer size.
- * @param callback Callback after the transfer is completed.
- * @param arg Custom argument to the callback.
- * @return Error code.
- */
-int remote_interrupt_in(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(dev, target, USB_TRANSFER_INTERRUPT,
-	    buffer, size, callback, arg);
-}
-
-
-int remote_control_write_setup(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_setup_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_write_data(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_write_status(device_t *device, usb_target_t target,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(device, target, USB_TRANSFER_CONTROL,
-	    NULL, 0, callback, arg);
-}
-
-int remote_control_read_setup(device_t *device, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_setup_transfer(device, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_read_data(device_t *dev, usb_target_t target,
-    void *buffer, size_t size,
-    usbhc_iface_transfer_in_callback_t callback, void *arg)
-{
-	return remote_in_transfer(dev, target, USB_TRANSFER_CONTROL,
-	    buffer, size, callback, arg);
-}
-
-int remote_control_read_status(device_t *device, usb_target_t target,
-    usbhc_iface_transfer_out_callback_t callback, void *arg)
-{
-	return remote_out_transfer(device, target, USB_TRANSFER_CONTROL,
-	    NULL, 0, callback, arg);
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/request.c
===================================================================
--- uspace/lib/usb/src/request.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/request.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,600 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * Standard USB requests (implementation).
+ */
+#include <usb/request.h>
+#include <errno.h>
+#include <assert.h>
+#include <usb/debug.h>
+
+#define MAX_DATA_LENGTH ((size_t)(0xFFFF))
+
+/** Generic wrapper for SET requests using standard control request format.
+ *
+ * @see usb_endpoint_pipe_control_write
+ *
+ * @param pipe Pipe used for the communication.
+ * @param request_type Request type (standard/class/vendor).
+ * @param recipient Request recipient (e.g. device or endpoint).
+ * @param request Actual request (e.g. GET_DESCRIPTOR).
+ * @param value Value of @c wValue field of setup packet
+ * 	(must be in USB endianness).
+ * @param index Value of @c wIndex field of setup packet
+ * 	(must be in USB endianness).
+ * @param data Data to be sent during DATA stage
+ * 	(expected to be in USB endianness).
+ * @param data_size Size of the @p data buffer (in native endianness).
+ * @return Error code.
+ * @retval EBADMEM @p pipe is NULL.
+ * @retval EBADMEM @p data is NULL and @p data_size is not zero.
+ * @retval ERANGE Data buffer too large.
+ */
+int usb_control_request_set(usb_endpoint_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t request,
+    uint16_t value, uint16_t index,
+    void *data, size_t data_size)
+{
+	if (pipe == NULL) {
+		return EBADMEM;
+	}
+
+	if (data_size > MAX_DATA_LENGTH) {
+		return ERANGE;
+	}
+
+	if ((data_size > 0) && (data == NULL)) {
+		return EBADMEM;
+	}
+
+	/*
+	 * TODO: check that @p request_type and @p recipient are
+	 * within ranges.
+	 */
+
+	usb_device_request_setup_packet_t setup_packet;
+	setup_packet.request_type = (request_type << 5) | recipient;
+	setup_packet.request = request;
+	setup_packet.value = value;
+	setup_packet.index = index;
+	setup_packet.length = (uint16_t) data_size;
+
+	int rc = usb_endpoint_pipe_control_write(pipe,
+	    &setup_packet, sizeof(setup_packet),
+	    data, data_size);
+
+	return rc;
+}
+
+ /** Generic wrapper for GET requests using standard control request format.
+  *
+  * @see usb_endpoint_pipe_control_read
+  *
+  * @param pipe Pipe used for the communication.
+  * @param request_type Request type (standard/class/vendor).
+  * @param recipient Request recipient (e.g. device or endpoint).
+  * @param request Actual request (e.g. GET_DESCRIPTOR).
+  * @param value Value of @c wValue field of setup packet
+  * 	(must be in USB endianness).
+  * @param index Value of @c wIndex field of setup packet
+  *	(must be in USB endianness).
+  * @param data Buffer where to store data accepted during the DATA stage.
+  *	(they will come in USB endianess).
+  * @param data_size Size of the @p data buffer
+  * 	(in native endianness).
+  * @param actual_data_size Actual size of transfered data
+  * 	(in native endianness).
+  * @return Error code.
+  * @retval EBADMEM @p pipe is NULL.
+  * @retval EBADMEM @p data is NULL and @p data_size is not zero.
+  * @retval ERANGE Data buffer too large.
+  */
+int usb_control_request_get(usb_endpoint_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t request,
+    uint16_t value, uint16_t index,
+    void *data, size_t data_size, size_t *actual_data_size)
+{
+	if (pipe == NULL) {
+		return EBADMEM;
+	}
+
+	if (data_size > MAX_DATA_LENGTH) {
+		return ERANGE;
+	}
+
+	if ((data_size > 0) && (data == NULL)) {
+		return EBADMEM;
+	}
+
+	/*
+	 * TODO: check that @p request_type and @p recipient are
+	 * within ranges.
+	 */
+
+	usb_device_request_setup_packet_t setup_packet;
+	setup_packet.request_type = 128 | (request_type << 5) | recipient;
+	setup_packet.request = request;
+	setup_packet.value = value;
+	setup_packet.index = index;
+	setup_packet.length = (uint16_t) data_size;
+
+	int rc = usb_endpoint_pipe_control_read(pipe,
+	    &setup_packet, sizeof(setup_packet),
+	    data, data_size, actual_data_size);
+
+	return rc;
+}
+
+/** Change address of connected device.
+ * This function automatically updates the backing connection to point to
+ * the new address.
+ *
+ * @see usb_drv_reserve_default_address
+ * @see usb_drv_release_default_address
+ * @see usb_drv_request_address
+ * @see usb_drv_release_address
+ * @see usb_drv_bind_address
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param new_address New USB address to be set (in native endianness).
+ * @return Error code.
+ */
+int usb_request_set_address(usb_endpoint_pipe_t *pipe,
+    usb_address_t new_address)
+{
+	if ((new_address < 0) || (new_address >= USB11_ADDRESS_MAX)) {
+		return EINVAL;
+	}
+
+	uint16_t addr = uint16_host2usb((uint16_t)new_address);
+
+	int rc = usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_ADDRESS,
+	    addr, 0,
+	    NULL, 0);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	assert(pipe->wire != NULL);
+	/* TODO: prevent other from accessing wire now. */
+	pipe->wire->address = new_address;
+
+	return EOK;
+}
+
+/** Retrieve USB descriptor of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer Buffer where to store the retrieved descriptor.
+ * @param[in] size Size of the @p buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_request_get_descriptor(usb_endpoint_pipe_t *pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void *buffer, size_t size, size_t *actual_size)
+{
+	if (buffer == NULL) {
+		return EBADMEM;
+	}
+	if (size == 0) {
+		return EINVAL;
+	}
+
+	uint16_t wValue = descriptor_index | (descriptor_type << 8);
+
+	return usb_control_request_get(pipe,
+	    request_type, recipient,
+	    USB_DEVREQ_GET_DESCRIPTOR,
+	    wValue, language,
+	    buffer, size, actual_size);
+}
+
+/** Retrieve USB descriptor, allocate space for it.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] request_type Request type (standard/class/vendor).
+ * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
+ * @param[in] descriptor_index Descriptor index.
+ * @param[in] language Language index.
+ * @param[out] buffer_ptr Where to store pointer to allocated buffer.
+ * @param[out] buffer_size Where to store the size of the descriptor.
+ * @return
+ */
+int usb_request_get_descriptor_alloc(usb_endpoint_pipe_t * pipe,
+    usb_request_type_t request_type, usb_request_recipient_t recipient,
+    uint8_t descriptor_type, uint8_t descriptor_index,
+    uint16_t language,
+    void **buffer_ptr, size_t *buffer_size)
+{
+	if (buffer_ptr == NULL) {
+		return EBADMEM;
+	}
+
+	int rc;
+
+	/*
+	 * Get only first byte to retrieve descriptor length.
+	 */
+	uint8_t tmp_buffer[1];
+	size_t bytes_transfered;
+	rc = usb_request_get_descriptor(pipe, request_type, recipient,
+	    descriptor_type, descriptor_index, language,
+	    &tmp_buffer, 1, &bytes_transfered);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (bytes_transfered != 1) {
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	size_t size = tmp_buffer[0];
+	if (size == 0) {
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	/*
+	 * Allocate buffer and get the descriptor again.
+	 */
+	void *buffer = malloc(size);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+
+	rc = usb_request_get_descriptor(pipe, request_type, recipient,
+	    descriptor_type, descriptor_index, language,
+	    buffer, size, &bytes_transfered);
+	if (rc != EOK) {
+		free(buffer);
+		return rc;
+	}
+	if (bytes_transfered != size) {
+		free(buffer);
+		/* FIXME: some better error code? */
+		return ESTALL;
+	}
+
+	*buffer_ptr = buffer;
+	if (buffer_size != NULL) {
+		*buffer_size = size;
+	}
+
+	return EOK;
+}
+
+/** Retrieve standard device descriptor of a USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ */
+int usb_request_get_device_descriptor(usb_endpoint_pipe_t *pipe,
+    usb_standard_device_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	size_t actually_transferred = 0;
+	usb_standard_device_descriptor_t descriptor_tmp;
+	int rc = usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE, 
+	    USB_DESCTYPE_DEVICE, 0, 0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Verify that all data has been transferred. */
+	if (actually_transferred < sizeof(descriptor_tmp)) {
+		return ELIMIT;
+	}
+
+	/* Everything is okay, copy the descriptor. */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(descriptor_tmp));
+
+	return EOK;
+}
+
+/** Retrieve configuration descriptor of a USB device.
+ *
+ * The function does not retrieve additional data binded with configuration
+ * descriptor (such as its interface and endpoint descriptors) - use
+ * usb_request_get_full_configuration_descriptor() instead.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Descriptor index.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @return Error code.
+ */
+int usb_request_get_bare_configuration_descriptor(usb_endpoint_pipe_t *pipe,
+    int index, usb_standard_configuration_descriptor_t *descriptor)
+{
+	if (descriptor == NULL) {
+		return EBADMEM;
+	}
+
+	if ((index < 0) || (index > 0xFF)) {
+		return ERANGE;
+	}
+
+	size_t actually_transferred = 0;
+	usb_standard_configuration_descriptor_t descriptor_tmp;
+	int rc = usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_CONFIGURATION, index, 0,
+	    &descriptor_tmp, sizeof(descriptor_tmp),
+	    &actually_transferred);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	/* Verify that all data has been transferred. */
+	if (actually_transferred < sizeof(descriptor_tmp)) {
+		return ELIMIT;
+	}
+
+	/* Everything is okay, copy the descriptor. */
+	memcpy(descriptor, &descriptor_tmp,
+	    sizeof(descriptor_tmp));
+
+	return EOK;
+}
+
+/** Retrieve full configuration descriptor of a USB device.
+ *
+ * @warning The @p buffer might be touched (i.e. its contents changed)
+ * even when error occurs.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index Descriptor index.
+ * @param[out] descriptor Storage for the device descriptor.
+ * @param[in] descriptor_size Size of @p descriptor buffer.
+ * @param[out] actual_size Number of bytes actually transferred.
+ * @return Error code.
+ */
+int usb_request_get_full_configuration_descriptor(usb_endpoint_pipe_t *pipe,
+    int index, void *descriptor, size_t descriptor_size, size_t *actual_size)
+{
+	if ((index < 0) || (index > 0xFF)) {
+		return ERANGE;
+	}
+
+	return usb_request_get_descriptor(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_CONFIGURATION, index, 0,
+	    descriptor, descriptor_size, actual_size);
+}
+
+/** Set configuration of USB device.
+ *
+ * @param pipe Control endpoint pipe (session must be already started).
+ * @param configuration_value New configuration value.
+ * @return Error code.
+ */
+int usb_request_set_configuration(usb_endpoint_pipe_t *pipe,
+    uint8_t configuration_value)
+{
+	uint16_t config_value
+	    = uint16_host2usb((uint16_t) configuration_value);
+
+	return usb_control_request_set(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DEVREQ_SET_CONFIGURATION, config_value, 0,
+	    NULL, 0);
+}
+
+/** Get list of supported languages by USB device.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[out] languages_ptr Where to store pointer to allocated array of
+ *	supported languages.
+ * @param[out] languages_count Number of supported languages.
+ * @return Error code.
+ */
+int usb_request_get_supported_languages(usb_endpoint_pipe_t *pipe,
+    l18_win_locales_t **languages_ptr, size_t *languages_count)
+{
+	int rc;
+
+	if (languages_ptr == NULL) {
+		return EBADMEM;
+	}
+	if (languages_count == NULL) {
+		return EBADMEM;
+	}
+
+	uint8_t *string_descriptor = NULL;
+	size_t string_descriptor_size = 0;
+	rc = usb_request_get_descriptor_alloc(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_STRING, 0, 0,
+	    (void **) &string_descriptor, &string_descriptor_size);
+	if (rc != EOK) {
+		return rc;
+	}
+	if (string_descriptor_size <= 2) {
+		free(string_descriptor);
+		return EEMPTY;
+	}
+	/* Substract first 2 bytes (length and descriptor type). */
+	string_descriptor_size -= 2;
+
+	/* Odd number of bytes - descriptor is broken? */
+	if ((string_descriptor_size % 2) != 0) {
+		/* FIXME: shall we return with error or silently ignore? */
+		free(string_descriptor);
+		return ESTALL;
+	}
+
+	size_t langs_count = string_descriptor_size / 2;
+	l18_win_locales_t *langs
+	    = malloc(sizeof(l18_win_locales_t) * langs_count);
+	if (langs == NULL) {
+		free(string_descriptor);
+		return ENOMEM;
+	}
+
+	size_t i;
+	for (i = 0; i < langs_count; i++) {
+		/* Language code from the descriptor is in USB endianess. */
+		/* FIXME: is this really correct? */
+		uint16_t lang_code = (string_descriptor[2 + 2 * i + 1] << 8)
+		    + string_descriptor[2 + 2 * i];
+		langs[i] = uint16_usb2host(lang_code);
+	}
+
+	free(string_descriptor);
+
+	*languages_ptr = langs;
+	*languages_count =langs_count;
+
+	return EOK;
+}
+
+/** Get string (descriptor) from USB device.
+ *
+ * The string is returned in native encoding of the operating system.
+ * For HelenOS, that is UTF-8.
+ *
+ * @param[in] pipe Control endpoint pipe (session must be already started).
+ * @param[in] index String index (in native endianess).
+ * @param[in] lang String language (in native endianess).
+ * @param[out] string_ptr Where to store allocated string in native encoding.
+ * @return Error code.
+ */
+int usb_request_get_string(usb_endpoint_pipe_t *pipe,
+    size_t index, l18_win_locales_t lang, char **string_ptr)
+{
+	if (string_ptr == NULL) {
+		return EBADMEM;
+	}
+	/* Index is actually one byte value. */
+	if (index > 0xFF) {
+		return ERANGE;
+	}
+	/* Language is actually two byte value. */
+	if (lang > 0xFFFF) {
+		return ERANGE;
+	}
+
+	int rc;
+
+	/* Prepare dynamically allocated variables. */
+	uint8_t *string = NULL;
+	wchar_t *string_chars = NULL;
+
+	/* Get the actual descriptor. */
+	size_t string_size;
+	rc = usb_request_get_descriptor_alloc(pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_DESCTYPE_STRING, index, uint16_host2usb(lang),
+	    (void **) &string, &string_size);
+	if (rc != EOK) {
+		goto leave;
+	}
+
+	if (string_size <= 2) {
+		rc =  EEMPTY;
+		goto leave;
+	}
+	/* Substract first 2 bytes (length and descriptor type). */
+	string_size -= 2;
+
+	/* Odd number of bytes - descriptor is broken? */
+	if ((string_size % 2) != 0) {
+		/* FIXME: shall we return with error or silently ignore? */
+		rc = ESTALL;
+		goto leave;
+	}
+
+	size_t string_char_count = string_size / 2;
+	string_chars = malloc(sizeof(wchar_t) * (string_char_count + 1));
+	if (string_chars == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	/*
+	 * Build a wide string.
+	 * And do not forget to set NULL terminator (string descriptors
+	 * do not have them).
+	 */
+	size_t i;
+	for (i = 0; i < string_char_count; i++) {
+		uint16_t uni_char = (string[2 + 2 * i + 1] << 8)
+		    + string[2 + 2 * i];
+		string_chars[i] = uni_char;
+	}
+	string_chars[string_char_count] = 0;
+
+
+	/* Convert to normal string. */
+	char *str = wstr_to_astr(string_chars);
+	if (str == NULL) {
+		rc = ENOMEM;
+		goto leave;
+	}
+
+	*string_ptr = str;
+	rc = EOK;
+
+leave:
+	if (string != NULL) {
+		free(string);
+	}
+	if (string_chars != NULL) {
+		free(string_chars);
+	}
+
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/usb.c
===================================================================
--- uspace/lib/usb/src/usb.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ uspace/lib/usb/src/usb.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup libusb usb
+/** @addtogroup libusb
  * @{
  */
@@ -54,20 +54,4 @@
 }
 
-/** String representation of USB transaction outcome. */
-const char * usb_str_transaction_outcome(usb_transaction_outcome_t o)
-{
-	switch (o) {
-		case USB_OUTCOME_OK:
-			return "ok";
-		case USB_OUTCOME_CRCERROR:
-			return "CRC error";
-		case USB_OUTCOME_BABBLE:
-			return "babble";
-		default:
-			return "unknown";
-	}
-}
-
-
 /**
  * @}
Index: uspace/lib/usb/src/usbdevice.c
===================================================================
--- uspace/lib/usb/src/usbdevice.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/usbdevice.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * General communication between device drivers and host controller driver.
+ */
+#include <devman.h>
+#include <async.h>
+#include <usb_iface.h>
+#include <usb/usbdevice.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Find host controller handle that is ancestor of given device.
+ *
+ * @param[in] device_handle Device devman handle.
+ * @param[out] hc_handle Where to store handle of host controller
+ *	controlling device with @p device_handle handle.
+ * @return Error code.
+ */
+int usb_hc_find(devman_handle_t device_handle, devman_handle_t *hc_handle)
+{
+	int parent_phone = devman_parent_device_connect(device_handle,
+	    IPC_FLAG_BLOCKING);
+	if (parent_phone < 0) {
+		return parent_phone;
+	}
+
+	devman_handle_t h;
+	usb_log_debug("asking for HC handle (my handle is %zu).\n", device_handle);
+	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
+	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
+
+	async_hangup(parent_phone);
+
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (hc_handle != NULL) {
+		*hc_handle = h;
+	}
+
+	return EOK;
+}
+
+/** Initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param device Device connecting to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize_from_device(usb_hc_connection_t *connection,
+    ddf_dev_t *device)
+{
+	assert(connection);
+
+	if (device == NULL) {
+		return EBADMEM;
+	}
+
+	devman_handle_t hc_handle;
+	int rc = usb_hc_find(device->handle, &hc_handle);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_hc_connection_initialize(connection, hc_handle);
+
+	return rc;
+}
+
+/** Manually initialize connection to USB host controller.
+ *
+ * @param connection Connection to be initialized.
+ * @param hc_handle Devman handle of the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_initialize(usb_hc_connection_t *connection,
+    devman_handle_t hc_handle)
+{
+	assert(connection);
+
+	connection->hc_handle = hc_handle;
+	connection->hc_phone = -1;
+
+	return EOK;
+}
+
+/** Open connection to host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_open(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (usb_hc_connection_is_opened(connection)) {
+		return EBUSY;
+	}
+
+	int phone = devman_device_connect(connection->hc_handle, 0);
+	if (phone < 0) {
+		return phone;
+	}
+
+	connection->hc_phone = phone;
+
+	return EOK;
+}
+
+/** Tells whether connection to host controller is opened.
+ *
+ * @param connection Connection to the host controller.
+ * @return Whether connection is opened.
+ */
+bool usb_hc_connection_is_opened(const usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	return (connection->hc_phone >= 0);
+}
+
+/** Close connection to the host controller.
+ *
+ * @param connection Connection to the host controller.
+ * @return Error code.
+ */
+int usb_hc_connection_close(usb_hc_connection_t *connection)
+{
+	assert(connection);
+
+	if (!usb_hc_connection_is_opened(connection)) {
+		return ENOENT;
+	}
+
+	int rc = async_hangup(connection->hc_phone);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	connection->hc_phone = -1;
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/usbdrv.c
===================================================================
--- uspace/lib/usb/src/usbdrv.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,534 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief USB driver (implementation).
- */
-#include <usb/usbdrv.h>
-#include <usbhc_iface.h>
-#include <usb_iface.h>
-#include <errno.h>
-#include <str_error.h>
-
-/** Information about pending transaction on HC. */
-typedef struct {
-	/** Phone to host controller driver. */
-	int phone;
-	/** Data buffer. */
-	void *buffer;
-	/** Buffer size. */
-	size_t size;
-	/** Storage for actual number of bytes transferred. */
-	size_t *size_transferred;
-	/** Initial call replay data. */
-	ipc_call_t reply;
-	/** Initial call identifier. */
-	aid_t request;
-} transfer_info_t;
-
-/** Find handle of host controller the device is physically attached to.
- *
- * @param[in] dev Device looking for its host controller.
- * @param[out] handle Host controller devman handle.
- * @return Error code.
- */
-int usb_drv_find_hc(device_t *dev, devman_handle_t *handle)
-{
-	if (dev == NULL) {
-		return EBADMEM;
-	}
-	if (handle == NULL) {
-		return EBADMEM;
-	}
-
-	int parent_phone = devman_parent_device_connect(dev->handle,
-	    IPC_FLAG_BLOCKING);
-	if (parent_phone < 0) {
-		return parent_phone;
-	}
-
-	devman_handle_t h;
-	int rc = async_req_1_1(parent_phone, DEV_IFACE_ID(USB_DEV_IFACE),
-	    IPC_M_USB_GET_HOST_CONTROLLER_HANDLE, &h);
-
-	ipc_hangup(parent_phone);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	*handle = h;
-
-	return EOK;
-}
-
-/** Connect to host controller the device is physically attached to.
- *
- * @param dev Device asking for connection.
- * @param hc_handle Devman handle of the host controller.
- * @param flags Connection flags (blocking connection).
- * @return Phone to the HC or error code.
- */
-int usb_drv_hc_connect(device_t *dev, devman_handle_t hc_handle,
-    unsigned int flags)
-{
-	return devman_device_connect(hc_handle, flags);
-}
-
-/** Connect to host controller the device is physically attached to.
- *
- * @param dev Device asking for connection.
- * @param flags Connection flags (blocking connection).
- * @return Phone to corresponding HC or error code.
- */
-int usb_drv_hc_connect_auto(device_t *dev, unsigned int flags)
-{
-	int rc;
-	devman_handle_t hc_handle;
-
-	/*
-	 * Call parent hub to obtain device handle of respective HC.
-	 */
-	rc = usb_drv_find_hc(dev, &hc_handle);
-	if (rc != EOK) {
-		return rc;
-	}
-	
-	return usb_drv_hc_connect(dev, hc_handle, flags);
-}
-
-/** Tell USB address assigned to given device.
- *
- * @param phone Phone to my HC.
- * @param dev Device in question.
- * @return USB address or error code.
- */
-usb_address_t usb_drv_get_my_address(int phone, device_t *dev)
-{
-	sysarg_t address;
-	int rc = async_req_2_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_ADDRESS,
-	    dev->handle, &address);
-
-	if (rc != EOK) {
-		printf("usb_drv_get_my_address over %d failed: %s\n", phone, str_error(rc));
-		return rc;
-	}
-
-	return (usb_address_t) address;
-}
-
-/** Tell HC to reserve default address.
- *
- * @param phone Open phone to host controller driver.
- * @return Error code.
- */
-int usb_drv_reserve_default_address(int phone)
-{
-	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RESERVE_DEFAULT_ADDRESS);
-}
-
-/** Tell HC to release default address.
- *
- * @param phone Open phone to host controller driver.
- * @return Error code.
- */
-int usb_drv_release_default_address(int phone)
-{
-	return async_req_1_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_DEFAULT_ADDRESS);
-}
-
-/** Ask HC for free address assignment.
- *
- * @param phone Open phone to host controller driver.
- * @return Assigned USB address or negative error code.
- */
-usb_address_t usb_drv_request_address(int phone)
-{
-	sysarg_t address;
-	int rc = async_req_1_1(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_REQUEST_ADDRESS, &address);
-	if (rc != EOK) {
-		return rc;
-	} else {
-		return (usb_address_t) address;
-	}
-}
-
-/** Inform HC about binding address with devman handle.
- *
- * @param phone Open phone to host controller driver.
- * @param address Address to be binded.
- * @param handle Devman handle of the device.
- * @return Error code.
- */
-int usb_drv_bind_address(int phone, usb_address_t address,
-    devman_handle_t handle)
-{
-	int rc = async_req_3_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_BIND_ADDRESS,
-	    address, handle);
-
-	return rc;
-}
-
-/** Inform HC about address release.
- *
- * @param phone Open phone to host controller driver.
- * @param address Address to be released.
- * @return Error code.
- */
-int usb_drv_release_address(int phone, usb_address_t address)
-{
-	return async_req_2_0(phone, DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_RELEASE_ADDRESS, address);
-}
-
-/** Send data to HCD.
- *
- * @param phone Phone to HC.
- * @param method Method used for calling.
- * @param target Targeted device.
- * @param buffer Data buffer (NULL to skip data transfer phase).
- * @param size Buffer size (must be zero when @p buffer is NULL).
- * @param handle Storage for transaction handle (cannot be NULL).
- * @return Error status.
- * @retval EINVAL Invalid parameter.
- * @retval ENOMEM Not enough memory to complete the operation.
- */
-static int async_send_buffer(int phone, int method,
-    usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-
-	if ((buffer == NULL) && (size > 0)) {
-		return EINVAL;
-	}
-
-	if (handle == NULL) {
-		return EINVAL;
-	}
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->size_transferred = NULL;
-	transfer->buffer = NULL;
-	transfer->size = 0;
-	transfer->phone = phone;
-
-	int rc;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    method,
-	    target.address, target.endpoint,
-	    size,
-	    &transfer->reply);
-
-	if (size > 0) {
-		rc = async_data_write_start(phone, buffer, size);
-		if (rc != EOK) {
-			async_wait_for(transfer->request, NULL);
-			return rc;
-		}
-	}
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
-/** Prepare data retrieval.
- *
- * @param phone Opened phone to HCD.
- * @param method Method used for calling.
- * @param target Targeted device.
- * @param buffer Buffer where to store retrieved data
- * 	(NULL to skip data transfer phase).
- * @param size Buffer size (must be zero when @p buffer is NULL).
- * @param actual_size Storage where actual number of bytes transferred will
- * 	be stored.
- * @param handle Storage for transaction handle (cannot be NULL).
- * @return Error status.
- * @retval EINVAL Invalid parameter.
- * @retval ENOMEM Not enough memory to complete the operation.
- */
-static int async_recv_buffer(int phone, int method,
-    usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	if (phone < 0) {
-		return EINVAL;
-	}
-
-	if ((buffer == NULL) && (size > 0)) {
-		return EINVAL;
-	}
-
-	if (handle == NULL) {
-		return EINVAL;
-	}
-
-	transfer_info_t *transfer
-	    = (transfer_info_t *) malloc(sizeof(transfer_info_t));
-	if (transfer == NULL) {
-		return ENOMEM;
-	}
-
-	transfer->size_transferred = actual_size;
-	transfer->buffer = buffer;
-	transfer->size = size;
-	transfer->phone = phone;
-
-	transfer->request = async_send_4(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    method,
-	    target.address, target.endpoint,
-	    size,
-	    &transfer->reply);
-
-	*handle = (usb_handle_t) transfer;
-
-	return EOK;
-}
-
-/** Read buffer from HCD.
- *
- * @param phone Opened phone to HCD.
- * @param hash Buffer hash (obtained after completing IN transaction).
- * @param buffer Buffer where to store data data.
- * @param size Buffer size.
- * @param actual_size Storage where actual number of bytes transferred will
- * 	be stored.
- * @return Error status.
- */
-static int read_buffer_in(int phone, sysarg_t hash,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	ipc_call_t answer_data;
-	sysarg_t answer_rc;
-	aid_t req;
-	int rc;
-
-	req = async_send_2(phone,
-	    DEV_IFACE_ID(USBHC_DEV_IFACE),
-	    IPC_M_USBHC_GET_BUFFER,
-	    hash,
-	    &answer_data);
-
-	rc = async_data_read_start(phone, buffer, size);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return EINVAL;
-	}
-
-	async_wait_for(req, &answer_rc);
-	rc = (int)answer_rc;
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	*actual_size = IPC_GET_ARG1(answer_data);
-
-	return EOK;
-}
-
-/** Blocks caller until given USB transaction is finished.
- * After the transaction is finished, the user can access all output data
- * given to initial call function.
- *
- * @param handle Transaction handle.
- * @return Error status.
- * @retval EOK No error.
- * @retval EBADMEM Invalid handle.
- * @retval ENOENT Data buffer associated with transaction does not exist.
- */
-int usb_drv_async_wait_for(usb_handle_t handle)
-{
-	if (handle == 0) {
-		return EBADMEM;
-	}
-
-	int rc = EOK;
-
-	transfer_info_t *transfer = (transfer_info_t *) handle;
-
-	sysarg_t answer_rc;
-	async_wait_for(transfer->request, &answer_rc);
-
-	if (answer_rc != EOK) {
-		rc = (int) answer_rc;
-		goto leave;
-	}
-
-	/*
-	 * If the buffer is not NULL, we must accept some data.
-	 */
-	if ((transfer->buffer != NULL) && (transfer->size > 0)) {
-		/*
-		 * The buffer hash identifies the data on the server
-		 * side.
-		 * We will use it when actually reading-in the data.
-		 */
-		sysarg_t buffer_hash = IPC_GET_ARG1(transfer->reply);
-		if (buffer_hash == 0) {
-			rc = ENOENT;
-			goto leave;
-		}
-
-		size_t actual_size;
-		rc = read_buffer_in(transfer->phone, buffer_hash,
-		    transfer->buffer, transfer->size, &actual_size);
-
-		if (rc != EOK) {
-			goto leave;
-		}
-
-		if (transfer->size_transferred) {
-			*(transfer->size_transferred) = actual_size;
-		}
-	}
-
-leave:
-	free(transfer);
-
-	return rc;
-}
-
-/** Send interrupt data to device. */
-int usb_drv_async_interrupt_out(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_INTERRUPT_OUT,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Request interrupt data from device. */
-int usb_drv_async_interrupt_in(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_INTERRUPT_IN,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
-}
-
-/** Start control write transfer. */
-int usb_drv_async_control_write_setup(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Send data during control write transfer. */
-int usb_drv_async_control_write_data(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_DATA,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Finalize control write transfer. */
-int usb_drv_async_control_write_status(int phone, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_WRITE_STATUS,
-	    target,
-	    NULL, 0, NULL,
-	    handle);
-}
-
-/** Start control read transfer. */
-int usb_drv_async_control_read_setup(int phone, usb_target_t target,
-    void *buffer, size_t size,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_SETUP,
-	    target,
-	    buffer, size,
-	    handle);
-}
-
-/** Read data during control read transfer. */
-int usb_drv_async_control_read_data(int phone, usb_target_t target,
-    void *buffer, size_t size, size_t *actual_size,
-    usb_handle_t *handle)
-{
-	return async_recv_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_DATA,
-	    target,
-	    buffer, size, actual_size,
-	    handle);
-}
-
-/** Finalize control read transfer. */
-int usb_drv_async_control_read_status(int phone, usb_target_t target,
-    usb_handle_t *handle)
-{
-	return async_send_buffer(phone,
-	    IPC_M_USBHC_CONTROL_READ_STATUS,
-	    target,
-	    NULL, 0,
-	    handle);
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/usbdrvreq.c
===================================================================
--- uspace/lib/usb/src/usbdrvreq.c	(revision 976f5467374c4083883e264c4bac5dc6e98c2a1c)
+++ 	(revision )
@@ -1,523 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * 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 libusb usb
- * @{
- */
-/** @file
- * @brief USB driver - standard USB requests (implementation).
- */
-#include <usb/usbdrv.h>
-#include <errno.h>
-
-/**  Prepare USB target for control endpoint.
- *
- * @param name Variable name with the USB target.
- * @param target_address Target USB address.
- */
-#define PREPARE_TARGET(name, target_address) \
-	usb_target_t name = { \
-		.address = target_address, \
-		.endpoint = 0 \
-	}
-
-/** Prepare setup packet.
- *
- * @param name Variable name with the setup packet.
- * @param p_direction Data transfer direction.
- * @param p_type Request type (standard/class/vendor)
- * @param p_recipient Recipient of the request.
- * @param p_request Request.
- * @param p_value wValue field of setup packet.
- * @param p_index wIndex field of setup packet.
- * @param p_length Length of extra data.
- */
-#define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
-    p_request, p_value, p_index, p_length) \
-	usb_device_request_setup_packet_t name = { \
-		.request_type = \
-			((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
-			| ((p_type) << 5) \
-			| (p_recipient), \
-		.request = (p_request), \
-		{ .value = (p_value) }, \
-		.index = (p_index), \
-		.length = (p_length) \
-	}
-
-/** Prepare setup packet.
- *
- * @param name Variable name with the setup packet.
- * @param p_direction Data transfer direction.
- * @param p_type Request type (standard/class/vendor)
- * @param p_recipient Recipient of the request.
- * @param p_request Request.
- * @param p_value_low wValue field of setup packet (low byte).
- * @param p_value_high wValue field of setup packet (high byte).
- * @param p_index wIndex field of setup packet.
- * @param p_length Length of extra data.
- */
-#define PREPARE_SETUP_PACKET_LOHI(name, p_direction, p_type, p_recipient, \
-    p_request, p_value_low, p_value_high, p_index, p_length) \
-	PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
-	    p_request, (p_value_low) | ((p_value_high) << 8), \
-	    p_index, p_length)
-
-/** Retrieve status of a USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] recipient Recipient of the request.
- * @param[in] recipient_index Index of @p recipient.
- * @param[out] status Status (see figure 9-4 in USB 1.1 specification).
- * @return Error code.
- */
-int usb_drv_req_get_status(int hc_phone, usb_address_t address,
-    usb_request_recipient_t recipient, uint16_t recipient_index,
-    uint16_t *status)
-{
-	if (status == NULL) {
-		return EBADMEM;
-	}
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet,
-	    USB_DIRECTION_IN, USB_REQUEST_TYPE_STANDARD,
-	    recipient, USB_DEVREQ_GET_STATUS, 0, recipient_index, 2);
-
-	size_t transfered;
-	uint16_t tmp_status;
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), &tmp_status, 2, &transfered);
-	if (rc != EOK) {
-		return rc;
-	}
-	if (transfered != 2) {
-		return ERANGE;
-	}
-
-	*status = tmp_status;
-
-	return EOK;
-}
-
-/** Clear or disable USB device feature.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] recipient Recipient of the request.
- * @param[in] selector Feature selector.
- * @param[in] index Index of @p recipient.
- * @return Error code.
- */
-int usb_drv_req_clear_feature(int hc_phone, usb_address_t address,
-    usb_request_recipient_t recipient,
-    uint16_t selector, uint16_t index)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet,
-	    USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
-	    recipient, USB_DEVREQ_CLEAR_FEATURE, selector, index, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Set or enable USB device feature.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] recipient Recipient of the request.
- * @param[in] selector Feature selector.
- * @param[in] index Index of @p recipient.
- * @return Error code.
- */
-int usb_drv_req_set_feature(int hc_phone, usb_address_t address,
-    usb_request_recipient_t recipient,
-    uint16_t selector, uint16_t index)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet,
-	    USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
-	    recipient, USB_DEVREQ_SET_FEATURE, selector, index, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Change address of connected device.
- *
- * @see usb_drv_reserve_default_address
- * @see usb_drv_release_default_address
- * @see usb_drv_request_address
- * @see usb_drv_release_address
- * @see usb_drv_bind_address
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] old_address Current address.
- * @param[in] address Address to be set.
- * @return Error code.
- */
-int usb_drv_req_set_address(int phone, usb_address_t old_address,
-    usb_address_t new_address)
-{
-	PREPARE_TARGET(target, old_address);
-
-	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_ADDRESS, new_address, 0, 0);
-
-	int rc = usb_drv_psync_control_write(phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Retrieve USB descriptor of connected USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] request_type Request type (standard/class/vendor).
- * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
- * @param[in] descriptor_index Descriptor index.
- * @param[in] language Language index.
- * @param[out] buffer Buffer where to store the retrieved descriptor.
- * @param[in] size Size of the @p buffer.
- * @param[out] actual_size Number of bytes actually transferred.
- * @return Error code.
- */
-int usb_drv_req_get_descriptor(int hc_phone, usb_address_t address,
-    usb_request_type_t request_type,
-    uint8_t descriptor_type, uint8_t descriptor_index,
-    uint16_t language,
-    void *buffer, size_t size, size_t *actual_size)
-{
-	if (buffer == NULL) {
-		return EBADMEM;
-	}
-	if (size == 0) {
-		return EINVAL;
-	}
-
-	// FIXME: check that size is not too big
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_IN,
-	    request_type, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_GET_DESCRIPTOR, descriptor_index, descriptor_type,
-	    language, size);
-
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    buffer, size, actual_size);
-	
-	return rc;
-}
-
-/** Retrieve device descriptor of connected USB device.
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[out] descriptor Storage for the device descriptor.
- * @return Error code.
- * @retval EBADMEM @p descriptor is NULL.
- */
-int usb_drv_req_get_device_descriptor(int phone, usb_address_t address,
-    usb_standard_device_descriptor_t *descriptor)
-{
-	if (descriptor == NULL) {
-		return EBADMEM;
-	}
-	
-	size_t actually_transferred = 0;
-	usb_standard_device_descriptor_t descriptor_tmp;
-	int rc = usb_drv_req_get_descriptor(phone, address,
-	    USB_REQUEST_TYPE_STANDARD,
-	    USB_DESCTYPE_DEVICE, 0,
-	    0,
-	    &descriptor_tmp, sizeof(descriptor_tmp),
-	    &actually_transferred);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Verify that all data has been transferred. */
-	if (actually_transferred < sizeof(descriptor_tmp)) {
-		return ELIMIT;
-	}
-
-	/* Everything is okay, copy the descriptor. */
-	memcpy(descriptor, &descriptor_tmp,
-	    sizeof(descriptor_tmp));
-
-	return EOK;
-}
-
-
-/** Retrieve configuration descriptor of connected USB device.
- *
- * The function does not retrieve additional data binded with configuration
- * descriptor (such as its interface and endpoint descriptors) - use
- * usb_drv_req_get_full_configuration_descriptor() instead.
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] index Configuration descriptor index.
- * @param[out] descriptor Storage for the configuration descriptor.
- * @return Error code.
- * @retval EBADMEM @p descriptor is NULL.
- */
-int usb_drv_req_get_bare_configuration_descriptor(int phone,
-    usb_address_t address, int index,
-    usb_standard_configuration_descriptor_t *descriptor)
-{
-	if (descriptor == NULL) {
-		return EBADMEM;
-	}
-	
-	size_t actually_transferred = 0;
-	usb_standard_configuration_descriptor_t descriptor_tmp;
-	int rc = usb_drv_req_get_descriptor(phone, address,
-	    USB_REQUEST_TYPE_STANDARD,
-	    USB_DESCTYPE_CONFIGURATION, 0,
-	    0,
-	    &descriptor_tmp, sizeof(descriptor_tmp),
-	    &actually_transferred);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	/* Verify that all data has been transferred. */
-	if (actually_transferred < sizeof(descriptor_tmp)) {
-		return ELIMIT;
-	}
-
-	/* Everything is okay, copy the descriptor. */
-	memcpy(descriptor, &descriptor_tmp,
-	    sizeof(descriptor_tmp));
-
-	return EOK;
-}
-
-/** Retrieve full configuration descriptor of connected USB device.
- *
- * @warning The @p buffer might be touched (i.e. its contents changed)
- * even when error occurs.
- *
- * @param[in] phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] index Configuration descriptor index.
- * @param[out] buffer Buffer for the whole configuration descriptor.
- * @param[in] buffer_size Size of the prepared @p buffer.
- * @param[out] actual_buffer_size Bytes actually transfered.
- * @return Error code.
- * @retval EBADMEM @p descriptor is NULL.
- */
-int usb_drv_req_get_full_configuration_descriptor(int phone,
-    usb_address_t address, int index,
-    void *buffer, size_t buffer_size, size_t *actual_buffer_size)
-{
-	int rc = usb_drv_req_get_descriptor(phone, address,
-	    USB_REQUEST_TYPE_STANDARD,
-	    USB_DESCTYPE_CONFIGURATION, 0,
-	    0,
-	    buffer, buffer_size,
-	    actual_buffer_size);
-
-	return rc;
-}
-
-/** Update existing descriptor of a USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] descriptor_type Descriptor type (device/configuration/...).
- * @param[in] descriptor_index Descriptor index.
- * @param[in] language Language index.
- * @param[in] descriptor Actual descriptor data.
- * @param[in] descriptor_size Descriptor size.
- * @return Error code.
- */
-int usb_drv_req_set_descriptor(int hc_phone, usb_address_t address,
-    uint8_t descriptor_type, uint8_t descriptor_index,
-    uint16_t language,
-    void *descriptor, size_t descriptor_size)
-{
-	// FIXME: check that descriptor is not too big
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_DESCRIPTOR, descriptor_index, descriptor_type,
-	    language, descriptor_size);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet),
-	    descriptor, descriptor_size);
-
-	return rc;
-}
-
-/** Determine current configuration value of USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[out] configuration_value Current configuration value.
- * @return Error code.
- */
-int usb_drv_req_get_configuration(int hc_phone, usb_address_t address,
-    uint8_t *configuration_value)
-{
-	if (configuration_value == NULL) {
-		return EBADMEM;
-	}
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_GET_CONFIGURATION, 0, 0, 1);
-
-	uint8_t value;
-	size_t transfered;
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), &value, 1, &transfered);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (transfered != 1) {
-		return ERANGE;
-	}
-
-	*configuration_value = value;
-
-	return EOK;
-}
-
-/** Set configuration of USB device.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] configuration_value New configuration value.
- * @return Error code.
- */
-int usb_drv_req_set_configuration(int hc_phone, usb_address_t address,
-    uint8_t configuration_value)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DEVREQ_SET_CONFIGURATION, configuration_value, 0,
-	    0, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/** Determine alternate setting of USB device interface.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] interface_index Interface index.
- * @param[out] alternate_setting Value of alternate setting.
- * @return Error code.
- */
-int usb_drv_req_get_interface(int hc_phone, usb_address_t address,
-    uint16_t interface_index, uint8_t *alternate_setting)
-{
-	if (alternate_setting == NULL) {
-		return EBADMEM;
-	}
-
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
-	    USB_DEVREQ_GET_INTERFACE, 0, interface_index, 1);
-
-	uint8_t alternate;
-	size_t transfered;
-	int rc = usb_drv_psync_control_read(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), &alternate, 1, &transfered);
-
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (transfered != 1) {
-		return ERANGE;
-	}
-
-	*alternate_setting = alternate;
-
-	return EOK;
-}
-
-/** Select an alternate setting of USB device interface.
- *
- * @param[in] hc_phone Open phone to HC driver.
- * @param[in] address Device address.
- * @param[in] interface_index Interface index.
- * @param[in] alternate_setting Value of alternate setting.
- * @return Error code.
- */
-int usb_drv_req_set_interface(int hc_phone, usb_address_t address,
-    uint16_t interface_index, uint8_t alternate_setting)
-{
-	PREPARE_TARGET(target, address);
-
-	PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
-	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
-	    USB_DEVREQ_SET_INTERFACE, alternate_setting, 0,
-	    0, 0);
-
-	int rc = usb_drv_psync_control_write(hc_phone, target,
-	    &setup_packet, sizeof(setup_packet), NULL, 0);
-
-	return rc;
-}
-
-/**
- * @}
- */
Index: uspace/lib/usb/src/usbmem.c
===================================================================
--- uspace/lib/usb/src/usbmem.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
+++ uspace/lib/usb/src/usbmem.c	(revision 19a18004a56ed89f716b2310c889ca6b22618bbd)
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2011 Matus Dekanek
+ * 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 libc
+ * @{
+ */
+/** @file implementation of special memory management, used mostly in usb stack
+ */
+
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include <as.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include "usb/usbmem.h"
+
+#define ADDR_BUCKETS 1537
+
+//address translation tables
+static hash_table_t * pa2va_table = NULL;
+static hash_table_t * va2pa_table = NULL;
+
+/**
+ * address translation hashtable item
+ */
+typedef struct{
+	unsigned long addr;
+	unsigned long translation;
+	link_t link;
+
+}addr_node_t;
+
+static hash_index_t addr_hash(unsigned long key[])
+{
+	return (3*key[0]<<4) % ADDR_BUCKETS;
+}
+
+static int addr_compare(unsigned long key[], hash_count_t keys,
+    link_t *item)
+{
+	addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
+	return (addr_node->addr == key[0]);
+}
+
+static void addr_remove_callback(link_t * item)
+{
+	//delete item
+	addr_node_t *addr_node = hash_table_get_instance(item, addr_node_t, link);
+	free(addr_node);
+}
+
+
+static hash_table_operations_t addr_devices_ops = {
+	.hash = addr_hash,
+	.compare = addr_compare,
+	.remove_callback = addr_remove_callback
+};
+
+/**
+ * create node for address translation hashtable
+ * @param addr
+ * @param translation
+ * @return
+ */
+static addr_node_t * create_addr_node(void * addr, void * translation){
+	addr_node_t * node = (addr_node_t*)malloc(sizeof(addr_node_t));
+	node->addr = (unsigned long)addr;
+	node->translation = (unsigned long)translation;
+	return node;
+}
+
+/**
+ * allocate size on heap and register it`s pa<->va translation
+ *
+ * If physical address + size is 2GB or higher, nothing is allocated and NULL
+ * is returned.
+ * @param size
+ * @param alignment
+ * @return
+ */
+void * mman_malloc(
+	size_t size,
+	size_t alignment,
+	unsigned long max_physical_address)
+{
+	if (size == 0)
+		return NULL;
+	if (alignment == 0)
+		return NULL;
+	//check if tables were initialized
+	if(!pa2va_table){
+		pa2va_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
+		va2pa_table = (hash_table_t*)malloc(sizeof(hash_table_t*));
+		hash_table_create(pa2va_table, ADDR_BUCKETS, 1,
+		    &addr_devices_ops);
+		hash_table_create(va2pa_table, ADDR_BUCKETS, 1,
+		    &addr_devices_ops);
+	}
+	//allocate
+	void * vaddr = memalign(alignment, size);
+	
+	//get translation
+	void * paddr = NULL;
+	int opResult = as_get_physical_mapping(vaddr,(uintptr_t*)&paddr);
+	if(opResult != EOK){
+		//something went wrong
+		free(vaddr);
+		return NULL;
+	}
+	if((unsigned long)paddr + size > max_physical_address){
+		//unusable address for usb
+		free(vaddr);
+		return NULL;
+	}
+	//store translation
+	addr_node_t * pa2vaNode = create_addr_node(paddr,vaddr);
+	addr_node_t * va2paNode = create_addr_node(vaddr,paddr);
+
+	unsigned long keypaddr = (unsigned long)paddr;
+	unsigned long keyvaddr = (unsigned long)vaddr;
+	hash_table_insert(pa2va_table, (&keypaddr), &pa2vaNode->link);
+	hash_table_insert(va2pa_table, (&keyvaddr), &va2paNode->link);
+	//return
+	return vaddr;
+
+}
+
+/**
+ * get virtual address from physical
+ * @param addr
+ * @return translated virtual address or null
+ */
+void * mman_getVA(void * addr){
+	unsigned long keypaddr = (unsigned long)addr;
+	link_t * link = hash_table_find(pa2va_table, &keypaddr);
+	if(!link) return NULL;
+	addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
+	return (void*)node->translation;
+}
+
+/**
+ * get physical address from virtual
+ * @param addr
+ * @return physical address or null
+ */
+void * mman_getPA(void * addr){
+	unsigned long keyvaddr = (unsigned long)addr;
+	link_t * link = hash_table_find(va2pa_table, &keyvaddr);
+	if(!link) return NULL;
+	addr_node_t * node = hash_table_get_instance(link, addr_node_t, link);
+	return (void*)node->translation;
+}
+
+/**
+ * free the address and deregister it from pa<->va translation
+ * @param vaddr if NULL, nothing happens
+ */
+void mman_free(void * vaddr){
+	if(!vaddr)
+		return;
+	//get paddress
+	void * paddr = mman_getPA(vaddr);
+	unsigned long keypaddr = (unsigned long)paddr;
+	unsigned long keyvaddr = (unsigned long)vaddr;
+	//remove mapping
+	hash_table_remove(pa2va_table,&keypaddr, 1);
+	hash_table_remove(va2pa_table,&keyvaddr, 1);
+	//free address
+	free(vaddr);
+}
+
+
+
+/** @}
+ */
