Index: .bzrignore
===================================================================
--- .bzrignore	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ .bzrignore	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -109,5 +109,6 @@
 ./uspace/srv/hw/irc/apic/apic
 ./uspace/srv/hw/irc/i8259/i8259
-./uspace/srv/hw/netif/dp8390/dp8390
+./uspace/srv/hw/netif/ne2000/dp8390
+./uspace/srv/hw/netif/ne2000/ne2000
 ./uspace/srv/loader/loader
 ./uspace/srv/net/cfg/lo
Index: uspace/app/usbinfo/dump.c
===================================================================
--- uspace/app/usbinfo/dump.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/app/usbinfo/dump.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -43,4 +43,6 @@
 #include <usb/usb.h>
 #include <usb/descriptor.h>
+#include <usb/debug.h>
+#include <usb/classes/classes.h>
 
 #include "usbinfo.h"
@@ -50,22 +52,50 @@
 #define BYTES_PER_LINE 12
 
-#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 const char *get_indent(size_t level)
+{
+	static const char *indents[] = {
+		INDENT,
+		INDENT INDENT,
+		INDENT INDENT INDENT,
+		INDENT INDENT INDENT INDENT,
+		INDENT INDENT INDENT INDENT INDENT
+	};
+	static size_t indents_count = sizeof(indents)/sizeof(indents[0]);
+	if (level >= indents_count) {
+		return indents[indents_count - 1];
+	}
+	return indents[level];
+}
 
-void dump_buffer(const char *msg, const uint8_t *buffer, size_t length)
+void dump_buffer(const char *msg, size_t indent,
+    const uint8_t *buffer, size_t length)
 {
-	printf("%s\n", msg);
+	if (msg != NULL) {
+		printf("%s\n", msg);
+	}
 
 	size_t i;
+	if (length > 0) {
+		printf("%s", get_indent(indent));
+	}
 	for (i = 0; i < length; i++) {
-		printf("  0x%02X", buffer[i]);
+		printf("0x%02X", buffer[i]);
 		if (((i > 0) && (((i+1) % BYTES_PER_LINE) == 0))
 		    || (i + 1 == length)) {
 			printf("\n");
+			if (i + 1 < length) {
+				printf("%s", get_indent(indent));
+			}
+		} else {
+			printf("  ");
 		}
 	}
+}
+
+void dump_usb_descriptor(uint8_t *descriptor, size_t size)
+{
+	usb_dump_standard_descriptor(stdout, get_indent(0), "\n",
+	    descriptor, size);
 }
 
@@ -83,55 +113,8 @@
 }
 
-void dump_standard_device_descriptor(usb_standard_device_descriptor_t *d)
-{
-	printf("Standard device descriptor:\n");
-
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "bcdUSB = %d (" BCD_FMT ")\n", d->usb_spec_version,
-	    BCD_ARGS(d->usb_spec_version));
-	printf(INDENT "bDeviceClass = 0x%02x\n", d->device_class);
-	printf(INDENT "bDeviceSubClass = 0x%02x\n", d->device_subclass);
-	printf(INDENT "bDeviceProtocol = 0x%02x\n", d->device_protocol);
-	printf(INDENT "bMaxPacketSize0 = %d\n", d->max_packet_size);
-	printf(INDENT "idVendor = %d\n", d->vendor_id);
-	printf(INDENT "idProduct = %d\n", d->product_id);
-	printf(INDENT "bcdDevice = %d\n", d->device_version);
-	printf(INDENT "iManufacturer = %d\n", d->str_manufacturer);
-	printf(INDENT "iProduct = %d\n", d->str_product);
-	printf(INDENT "iSerialNumber = %d\n", d->str_serial_number);
-	printf(INDENT "bNumConfigurations = %d\n", d->configuration_count);
-}
-
-void dump_standard_configuration_descriptor(
-    int index, usb_standard_configuration_descriptor_t *d)
-{
-	bool self_powered = d->attributes & 64;
-	bool remote_wakeup = d->attributes & 32;
-	
-	printf("Standard configuration descriptor #%d\n", index);
-	printf(INDENT "bLength = %d\n", d->length);
-	printf(INDENT "bDescriptorType = 0x%02x\n", d->descriptor_type);
-	printf(INDENT "wTotalLength = %d\n", d->total_length);
-	printf(INDENT "bNumInterfaces = %d\n", d->interface_count);
-	printf(INDENT "bConfigurationValue = %d\n", d->configuration_number);
-	printf(INDENT "iConfiguration = %d\n", d->str_configuration);
-	printf(INDENT "bmAttributes = %d [%s%s%s]\n", d->attributes,
-	    self_powered ? "self-powered" : "",
-	    (self_powered & remote_wakeup) ? ", " : "",
-	    remote_wakeup ? "remote-wakeup" : "");
-	printf(INDENT "MaxPower = %d (%dmA)\n", d->max_power,
-	    2 * d->max_power);
-	// printf(INDENT " = %d\n", d->);
-}
-
 static void dump_tree_descriptor(uint8_t *descriptor, size_t depth)
 {
 	if (descriptor == NULL) {
 		return;
-	}
-	while (depth > 0) {
-		printf("  ");
-		depth--;
 	}
 	int type = (int) *(descriptor + 1);
@@ -151,5 +134,7 @@
 #undef _TYPE
 	}
-	printf("0x%02x (%s)\n", type, name);
+	printf("%s%s (0x%02X):\n", get_indent(depth), name, type);
+	usb_dump_standard_descriptor(stdout, get_indent(depth), "\n",
+	    descriptor, descriptor[0]);
 }
 
@@ -172,5 +157,5 @@
 	uint8_t *ptr = data->data;
 	printf("Descriptor tree:\n");
-	dump_tree_internal(parser, data, ptr, 1);
+	dump_tree_internal(parser, data, ptr, 0);
 }
 
Index: uspace/app/usbinfo/info.c
===================================================================
--- uspace/app/usbinfo/info.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/app/usbinfo/info.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -72,5 +72,5 @@
 		return rc;
 	}
-	dump_standard_device_descriptor(&device_descriptor);
+	dump_usb_descriptor((uint8_t *)&device_descriptor, sizeof(device_descriptor));
 
 	/*
@@ -91,6 +91,5 @@
 		return rc;
 	}
-	dump_standard_configuration_descriptor(config_index,
-	    &config_descriptor);
+	//dump_standard_configuration_descriptor(config_index, &config_descriptor);
 
 	void *full_config_descriptor = malloc(config_descriptor.total_length);
@@ -109,6 +108,4 @@
 		return rc;
 	}
-	dump_buffer("Full configuration descriptor:",
-	    full_config_descriptor, config_descriptor.total_length);
 
 	dump_descriptor_tree(full_config_descriptor,
Index: uspace/app/usbinfo/usbinfo.h
===================================================================
--- uspace/app/usbinfo/usbinfo.h	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/app/usbinfo/usbinfo.h	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -44,9 +44,7 @@
 #define NAME "usbinfo"
 
-void dump_buffer(const char *, const uint8_t *, size_t);
+void dump_buffer(const char *, size_t, const uint8_t *, size_t);
 void dump_match_ids(match_id_list_t *matches);
-void dump_standard_device_descriptor(usb_standard_device_descriptor_t *);
-void dump_standard_configuration_descriptor(int, 
-    usb_standard_configuration_descriptor_t *);
+void dump_usb_descriptor(uint8_t *, size_t);
 int dump_device(int, usb_address_t);
 void dump_descriptor_tree(uint8_t *, size_t);
Index: uspace/app/virtusbkbd/keys.h
===================================================================
--- uspace/app/virtusbkbd/keys.h	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/app/virtusbkbd/keys.h	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -40,5 +40,5 @@
 
 /** Maximum number of keys that can be pressed simultaneously. */
-#define KB_MAX_KEYS_AT_ONCE 4
+#define KB_MAX_KEYS_AT_ONCE 6
 
 /** Key code type. */
Index: uspace/drv/usbhub/main.c
===================================================================
--- uspace/drv/usbhub/main.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/usbhub/main.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -52,5 +52,5 @@
 	while(true){
 		usb_hub_check_hub_changes();
-		async_usleep(1000 * 1000);
+		async_usleep(1000 * 1000 );/// \TODO proper number once
 	}
 	return 0;
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/usbhub/usbhub.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -46,4 +46,5 @@
 #include "usbhub_private.h"
 #include "port_status.h"
+#include "usb/usb.h"
 
 static usb_iface_t hub_usb_iface = {
@@ -85,10 +86,4 @@
 
 	// get hub descriptor
-	usb_target_t target;
-	target.address = addr;
-	target.endpoint = 0;
-	usb_device_request_setup_packet_t request;
-	//printf("[usb_hub] creating descriptor request\n");
-	usb_hub_set_descriptor_request(&request);
 
 	//printf("[usb_hub] creating serialized descriptor\n");
@@ -98,7 +93,10 @@
 	int opResult;
 	//printf("[usb_hub] starting control transaction\n");
-	opResult = usb_drv_sync_control_read(
-			hc, target, &request, serialized_descriptor,
+	
+	opResult = usb_drv_req_get_descriptor(hc, addr,
+			USB_REQUEST_TYPE_CLASS,
+			USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
 			USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
+
 	if (opResult != EOK) {
 		dprintf(1,"[usb_hub] failed when receiving hub descriptor, badcode = %d",opResult);
@@ -155,5 +153,4 @@
 	int port;
 	int opResult;
-	usb_device_request_setup_packet_t request;
 	usb_target_t target;
 	target.address = hub_info->usb_device->address;
@@ -173,4 +170,5 @@
 	if(std_descriptor.configuration_count<1){
 		dprintf(1,"[usb_hub] THERE ARE NO CONFIGURATIONS AVAILABLE");
+		//shouldn`t I return?
 	}
 	/// \TODO check other configurations
@@ -184,15 +182,12 @@
 	}
 	//set configuration
-	request.request_type = 0;
-	request.request = USB_DEVREQ_SET_CONFIGURATION;
-	request.index=0;
-	request.length=0;
-	request.value_high=0;
-	request.value_low = config_descriptor.configuration_number;
-	opResult = usb_drv_sync_control_write(hc, target, &request, NULL, 0);
+	opResult = usb_drv_req_set_configuration(hc, target.address,
+    config_descriptor.configuration_number);
+
 	if (opResult != EOK) {
 		dprintf(1,"[usb_hub]something went wrong when setting hub`s configuration, %d", opResult);
 	}
 
+	usb_device_request_setup_packet_t request;
 	for (port = 1; port < hub_info->port_count+1; ++port) {
 		usb_hub_set_power_port_request(&request, port);
@@ -229,5 +224,4 @@
 
 
-
 //*********************************************
 //
@@ -237,6 +231,6 @@
 
 /**
- * convenience function for releasing default address and writing debug info
- * (these few lines are used too often to be written again and again)
+ * Convenience function for releasing default address and writing debug info
+ * (these few lines are used too often to be written again and again).
  * @param hc
  * @return
@@ -253,5 +247,5 @@
 
 /**
- * reset the port with new device and reserve the default address
+ * Reset the port with new device and reserve the default address.
  * @param hc
  * @param port
@@ -282,5 +276,5 @@
 
 /**
- * finalize adding new device after port reset
+ * Finalize adding new device after port reset
  * @param hc
  * @param port
@@ -345,5 +339,5 @@
 
 /**
- * unregister device address in hc
+ * Unregister device address in hc
  * @param hc
  * @param port
@@ -355,5 +349,7 @@
 	int opResult;
 	
-	/// \TODO remove device
+	/** \TODO remove device from device manager - not yet implemented in
+	 * devide manager
+	 */
 
 	hub->attached_devs[port].devman_handle=0;
@@ -376,5 +372,5 @@
 
 /**
- * process interrupts on given hub port
+ * Process interrupts on given hub port
  * @param hc
  * @param port
@@ -434,6 +430,7 @@
 	usb_port_set_reset_completed(&status, false);
 	usb_port_set_dev_connected(&status, false);
-	if (status) {
-		dprintf(1,"[usb_hub]there was some unsupported change on port %d",port);
+	if (status>>16) {
+		dprintf(1,"[usb_hub]there was some unsupported change on port %d: %X",port,status);
+
 	}
 	/// \TODO handle other changes
@@ -442,5 +439,6 @@
 }
 
-/* Check changes on all known hubs.
+/**
+ * Check changes on all known hubs.
  */
 void usb_hub_check_hub_changes(void) {
Index: uspace/drv/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/usbhub/usbhub_private.h	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/usbhub/usbhub_private.h	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -31,5 +31,5 @@
  */
 /** @file
- * @brief Hub driver.
+ * @brief Hub driver private definitions
  */
 
@@ -68,5 +68,5 @@
 
 /**
- * create hub structure instance
+ * Create hub structure instance
  *
  * Set the address and port count information most importantly.
@@ -78,21 +78,21 @@
 usb_hub_info_t * usb_create_hub_info(device_t * device, int hc);
 
-/** list of hubs maanged by this driver */
+/** List of hubs maanged by this driver */
 extern usb_general_list_t usb_hub_list;
 
-/** lock for hub list*/
+/** Lock for hub list*/
 extern futex_t usb_hub_list_lock;
 
 
 /**
- * perform complete control read transaction
+ * Perform complete control read transaction
  *
- * manages all three steps of transaction: setup, read and finalize
+ * Manages all three steps of transaction: setup, read and finalize
  * @param phone
  * @param target
- * @param request request for data
- * @param rcvd_buffer received data
+ * @param request Request packet
+ * @param rcvd_buffer Received data
  * @param rcvd_size
- * @param actual_size actual size of received data
+ * @param actual_size Actual size of received data
  * @return error code
  */
@@ -104,10 +104,10 @@
 
 /**
- * perform complete control write transaction
+ * Perform complete control write transaction
  *
- * manages all three steps of transaction: setup, write and finalize
+ * Manages all three steps of transaction: setup, write and finalize
  * @param phone
  * @param target
- * @param request request to send data
+ * @param request Request packet to send data
  * @param sent_buffer
  * @param sent_size
@@ -121,5 +121,5 @@
 
 /**
- * set the device request to be a get hub descriptor request.
+ * Set the device request to be a get hub descriptor request.
  * @warning the size is allways set to USB_HUB_MAX_DESCRIPTOR_SIZE
  * @param request
@@ -137,4 +137,13 @@
 }
 
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
 static inline int usb_hub_clear_port_feature(int hc, usb_address_t address,
     int port_index,
Index: uspace/drv/usbkbd/Makefile
===================================================================
--- uspace/drv/usbkbd/Makefile	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/usbkbd/Makefile	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -36,5 +36,6 @@
 	descparser.c \
 	descdump.c \
-	conv.c
+	conv.c \
+	us_qwerty.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/usbkbd/descparser.c
===================================================================
--- uspace/drv/usbkbd/descparser.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/usbkbd/descparser.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -187,5 +187,5 @@
 		case USB_DESCTYPE_HID:
 			if (desc_size < sizeof(usb_standard_hid_descriptor_t)) {
-				printf("Wrong size of descriptor: %d (should be %d)\n",
+				printf("Wrong size of descriptor: %d (should be %zu)\n",
 				    desc_size, sizeof(usb_standard_hid_descriptor_t));
 				ret = EINVAL;
Index: uspace/drv/usbkbd/main.c
===================================================================
--- uspace/drv/usbkbd/main.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/usbkbd/main.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -42,4 +42,5 @@
 #include "descdump.h"
 #include "conv.h"
+#include "layout.h"
 
 #define BUFFER_SIZE 32
@@ -125,6 +126,14 @@
 static unsigned lock_keys;
 
+#define NUM_LAYOUTS 3
+
+static layout_op_t *layout[NUM_LAYOUTS] = {
+	&us_qwerty_op,
+	&us_dvorak_op,
+	&cz_op
+};
+
 // TODO: put to device?
-//static int active_layout = 0;
+static int active_layout = 0;
 
 static void kbd_push_ev(int type, unsigned int key)
@@ -206,9 +215,9 @@
 	ev.mods = mods;
 
-	//ev.c = layout[active_layout]->parse_ev(&ev);
+	ev.c = layout[active_layout]->parse_ev(&ev);
 
 	printf("Sending key %d to the console\n", ev.key);
 	assert(console_callback_phone != -1);
-	async_msg_4(console_callback_phone, KBD_EVENT, ev.type, ev.key, ev.mods, 0);
+	async_msg_4(console_callback_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
 }
 /*
@@ -405,7 +414,7 @@
 	//usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 
 	//    NULL);
-//	printf("Calling usb_hid_boot_keyboard_input_report() with size %d\n",
-//	    actual_size);
-//	dump_buffer("bufffer: ", buffer, actual_size);
+	printf("Calling usb_hid_boot_keyboard_input_report() with size %d\n",
+	    actual_size);
+	//dump_buffer("bufffer: ", buffer, actual_size);
 	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, callbacks, 
 	    NULL);
@@ -457,5 +466,5 @@
 		 */
 		if (actual_size == 0) {
-			printf("Keyboar returned NAK\n");
+			printf("Keyboard returned NAK\n");
 			continue;
 		}
@@ -465,6 +474,5 @@
 		 */
 		printf("Calling usbkbd_process_interrupt_in()\n");
-		// actual_size is not set, workaround...
-		usbkbd_process_interrupt_in(kbd_dev, buffer, /*actual_size*/8);
+		usbkbd_process_interrupt_in(kbd_dev, buffer, actual_size);
 	}
 
Index: uspace/drv/vhc/devices.c
===================================================================
--- uspace/drv/vhc/devices.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/vhc/devices.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -138,4 +138,5 @@
 		} else {
 			async_wait_for(req, &answer_rc);
+			transaction->actual_len = IPC_GET_ARG1(answer_data);
 			rc = (int)answer_rc;
 		}
Index: uspace/drv/vhc/hc.c
===================================================================
--- uspace/drv/vhc/hc.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/vhc/hc.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -96,6 +96,6 @@
 	    usb_str_transaction_outcome(outcome));
 	
-	transaction->callback(transaction->buffer, transaction->len, outcome,
-	    transaction->callback_arg);
+	transaction->callback(transaction->buffer, transaction->actual_len,
+	    outcome, transaction->callback_arg);
 }
 
@@ -169,4 +169,5 @@
 	transaction->buffer = buffer;
 	transaction->len = len;
+	transaction->actual_len = len;
 	transaction->callback = callback;
 	transaction->callback_arg = arg;
Index: uspace/drv/vhc/hc.h
===================================================================
--- uspace/drv/vhc/hc.h	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/drv/vhc/hc.h	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -65,4 +65,6 @@
 	/** Transaction data length. */
 	size_t len;
+	/** Data length actually transfered. */
+	size_t actual_len;
 	/** Callback after transaction is done. */
 	hc_transaction_done_callback_t callback;
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/lib/usb/Makefile	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -38,4 +38,5 @@
 	src/dp.c \
 	src/drvpsync.c \
+	src/dump.c \
 	src/hcdhubd.c \
 	src/hcdrv.c \
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/lib/usb/include/usb/debug.h	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -35,8 +35,12 @@
 #ifndef LIBUSB_DEBUG_H_
 #define LIBUSB_DEBUG_H_
+#include <stdio.h>
+#include <usb/usb.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);
 
 #endif
Index: uspace/lib/usb/src/dump.c
===================================================================
--- uspace/lib/usb/src/dump.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
+++ uspace/lib/usb/src/dump.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -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 = %d", d->vendor_id);
+	PRINTLINE("idProduct = %d", 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/usbvirt/src/callback.c
===================================================================
--- uspace/lib/usbvirt/src/callback.c	(revision 6336b6ed30c5d3025044acbae3db2d8893acd20c)
+++ uspace/lib/usbvirt/src/callback.c	(revision 7c169cef1c068093084d1828dec3a4b96960c749)
@@ -160,8 +160,11 @@
 			return;
 		}
-		async_data_read_finalize(callid, buffer, receive_len);
-	}
-	
-	ipc_answer_0(iid, rc);
+		if (len > receive_len) {
+			len = receive_len;
+		}
+		async_data_read_finalize(callid, buffer, len);
+	}
+	
+	ipc_answer_1(iid, rc, len);
 }
 
