Index: uspace/app/usbinfo/dev.c
===================================================================
--- uspace/app/usbinfo/dev.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/app/usbinfo/dev.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -77,11 +77,5 @@
 	}
 
-	rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
-	if (rc != EOK) {
-		fprintf(stderr,
-		    NAME ": failed to start transfer on control pipe: %s.\n",
-		    str_error(rc));
-		goto leave;
-	}
+	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
 	transfer_started = true;
 
Index: uspace/drv/ehci-hcd/main.c
===================================================================
--- uspace/drv/ehci-hcd/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ehci-hcd/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -82,6 +82,7 @@
 	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
 	CHECK_RET_RETURN(ret,
-	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
-	usb_log_info("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
+	    "Failed to get memory addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n",
 	    mem_reg_base, mem_reg_size, irq);
 
@@ -102,5 +103,5 @@
 	    str_error(ret));
 
-	usb_log_info("Controlling new EHCI device `%s' (handle %llu).\n",
+	usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n",
 	    device->name, device->handle);
 
Index: uspace/drv/ehci-hcd/pci.c
===================================================================
--- uspace/drv/ehci-hcd/pci.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ehci-hcd/pci.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -117,5 +117,5 @@
 				mem_address = res->res.mem_range.address;
 				mem_size = res->res.mem_range.size;
-				usb_log_debug2("Found mem: %llx %zu.\n",
+				usb_log_debug2("Found mem: %" PRIxn" %zu.\n",
 				    mem_address, mem_size);
 				mem_found = true;
@@ -186,9 +186,9 @@
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read PCI config space.\n",
 	    ret);
-	usb_log_info("Register space BAR at %p:%x.\n", address, value);
+	usb_log_info("Register space BAR at %p:%" PRIxn ".\n", (void *) address, value);
 
 	/* clear lower byte, it's not part of the BASE address */
 	uintptr_t registers = (value & 0xffffff00);
-	usb_log_info("Memory registers BASE address:%p.\n", registers);
+	usb_log_info("Memory registers BASE address:%p.\n", (void *) registers);
 
 	/* if nothing setup the hc, we don't need to turn it off */
@@ -201,5 +201,5 @@
 	    AS_AREA_READ | AS_AREA_WRITE);
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to map registers %p:%p.\n",
-	    ret, regs, registers);
+	    ret, regs, (void *) registers);
 
 	/* calculate value of BASE */
@@ -221,5 +221,5 @@
 	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
-	usb_log_debug("USBLEGCTLSTS: %x.\n", value);
+	usb_log_debug("USBLEGCTLSTS: %" PRIxn ".\n", value);
 
 	/* Read the first EEC. i.e. Legacy Support register */
@@ -228,5 +228,5 @@
 	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
-	usb_log_debug2("USBLEGSUP: %x.\n", value);
+	usb_log_debug2("USBLEGSUP: %" PRIxn ".\n", value);
 
 	/* Request control from firmware/BIOS, by writing 1 to highest byte.
@@ -248,9 +248,9 @@
 
 	if ((value & USBLEGSUP_BIOS_CONTROL) == 0) {
-		usb_log_info("BIOS released control after %d usec.\n", wait);
+		usb_log_info("BIOS released control after %zu usec.\n", wait);
 	} else {
 		/* BIOS failed to hand over control, this should not happen. */
 		usb_log_warning( "BIOS failed to release control after "
-		    "%d usecs, force it.\n", wait);
+		    "%zu usecs, force it.\n", wait);
 		ret = async_req_3_0(parent_phone, DEV_IFACE_ID(PCI_DEV_IFACE),
 		    IPC_M_CONFIG_SPACE_WRITE_32, eecp + USBLEGSUP_OFFSET,
@@ -271,5 +271,5 @@
 	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGCTLSTS_OFFSET, &value);
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGCTLSTS.\n", ret);
-	usb_log_debug2("USBLEGCTLSTS: %x.\n", value);
+	usb_log_debug2("USBLEGCTLSTS: %" PRIxn ".\n", value);
 
 	/* Read again Legacy Support register */
@@ -277,5 +277,5 @@
 	    IPC_M_CONFIG_SPACE_READ_32, eecp + USBLEGSUP_OFFSET, &value);
 	CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) to read USBLEGSUP.\n", ret);
-	usb_log_debug2("USBLEGSUP: %x.\n", value);
+	usb_log_debug2("USBLEGSUP: %" PRIxn ".\n", value);
 
 	/*
Index: uspace/drv/ohci/batch.c
===================================================================
--- uspace/drv/ohci/batch.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/batch.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -141,5 +141,5 @@
 	assert(data);
 	size_t tds = data->td_count;
-	usb_log_debug("Batch(%p) checking %d td(s) for completion.\n",
+	usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n",
 	    instance, tds);
 	usb_log_debug("ED: %x:%x:%x:%x.\n",
@@ -147,7 +147,8 @@
 	    data->ed->next);
 	size_t i = 0;
+	instance->transfered_size = instance->buffer_size;
 	for (; i < tds; ++i) {
 		assert(data->tds[i] != NULL);
-		usb_log_debug("TD %d: %x:%x:%x:%x.\n", i,
+		usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i,
 		    data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,
 		    data->tds[i]->be);
@@ -156,8 +157,6 @@
 		}
 		instance->error = td_error(data->tds[i]);
-		/* FIXME: calculate real transfered size */
-		instance->transfered_size = instance->buffer_size;
 		if (instance->error != EOK) {
-			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
+			usb_log_debug("Batch(%p) found error TD(%zu):%x.\n",
 			    instance, i, data->tds[i]->status);
 			/* Make sure TD queue is empty (one TD),
@@ -174,4 +173,7 @@
 	assert(hcd_ep);
 	hcd_ep->td = data->tds[i];
+	if (i > 0)
+		instance->transfered_size -= td_remain_size(data->tds[i - 1]);
+
 	/* Clear possible ED HALT */
 	data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG;
@@ -238,7 +240,9 @@
 {
 	assert(instance);
-	instance->next_step = usb_transfer_batch_call_in_and_dispose;
+	/* We are data out, we are supposed to provide data */
+	memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
+	instance->next_step = usb_transfer_batch_call_out_and_dispose;
 	batch_data(instance);
-	usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
+	usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
 }
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/ohci/endpoint_list.c
===================================================================
--- uspace/drv/ohci/endpoint_list.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/endpoint_list.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -55,5 +55,5 @@
 	}
 	instance->list_head_pa = addr_to_phys(instance->list_head);
-	usb_log_debug2("Transfer list %s setup with ED: %p(%p).\n",
+	usb_log_debug2("Transfer list %s setup with ED: %p(0x%0" PRIx32 ")).\n",
 	    name, instance->list_head, instance->list_head_pa);
 
@@ -121,5 +121,5 @@
 		hcd_ep, instance->name, first, first->ed);
 	if (last_ed == instance->list_head) {
-		usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n",
+		usb_log_debug2("%s head ED(%p-0x%0" PRIx32 "): %x:%x:%x:%x.\n",
 		    instance->name, last_ed, instance->list_head_pa,
 		    last_ed->status, last_ed->td_tail, last_ed->td_head,
Index: uspace/drv/ohci/hc.c
===================================================================
--- uspace/drv/ohci/hc.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/hc.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -113,10 +113,10 @@
 	    BANDWIDTH_AVAILABLE_USB11);
 	CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
-	    ret, str_error(ret));
+	    str_error(ret));
 
 	hc_gain_control(instance);
 	ret = hc_init_memory(instance);
-	CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures:%s.\n",
-	    ret, str_error(ret));
+	CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n",
+	    str_error(ret));
 	hc_init_hw(instance);
 	fibril_mutex_initialize(&instance->guard);
@@ -294,7 +294,8 @@
 	if (status & IS_WDH) {
 		fibril_mutex_lock(&instance->guard);
-		usb_log_debug2("HCCA: %p-%p(%p).\n", instance->hcca,
-		    instance->registers->hcca, addr_to_phys(instance->hcca));
-		usb_log_debug2("Periodic current: %p.\n",
+		usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
+		    instance->registers->hcca,
+		    (void *) addr_to_phys(instance->hcca));
+		usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
 		    instance->registers->periodic_current);
 
@@ -405,5 +406,5 @@
 	instance->registers->bulk_head =
 	    instance->lists[USB_TRANSFER_BULK].list_head_pa;
-	usb_log_debug2("Bulk HEAD set to: %p(%p).\n",
+	usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_BULK].list_head,
 	    instance->lists[USB_TRANSFER_BULK].list_head_pa);
@@ -411,5 +412,5 @@
 	instance->registers->control_head =
 	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
-	usb_log_debug2("Control HEAD set to: %p(%p).\n",
+	usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_CONTROL].list_head,
 	    instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
@@ -487,5 +488,5 @@
 		    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
 	}
-	usb_log_debug2("Interrupt HEADs set to: %p(%p).\n",
+	usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
 	    instance->lists[USB_TRANSFER_INTERRUPT].list_head,
 	    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -52,4 +52,7 @@
 		instance->status |= togg[toggle] << TD_STATUS_T_SHIFT;
 	}
+	if (dir == USB_DIRECTION_IN) {
+		instance->status |= TD_STATUS_ROUND_FLAG;
+	}
 	if (buffer != NULL) {
 		assert(size != 0);
Index: uspace/drv/ohci/hw_struct/transfer_descriptor.h
===================================================================
--- uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/hw_struct/transfer_descriptor.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -59,4 +59,5 @@
 #define TD_STATUS_T_0 (0x2)
 #define TD_STATUS_T_1 (0x3)
+#define TD_STATUS_T_ED (0)
 #define TD_STATUS_EC_MASK (0x3) /* error count */
 #define TD_STATUS_EC_SHIFT (26)
@@ -102,4 +103,12 @@
 	return cc_to_rc(cc);
 }
+
+static inline size_t td_remain_size(td_t *instance)
+{
+	assert(instance);
+	if (instance->cbp == 0)
+		return 0;
+	return instance->be - instance->cbp + 1;
+}
 #endif
 /**
Index: uspace/drv/ohci/iface.c
===================================================================
--- uspace/drv/ohci/iface.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/iface.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -118,5 +118,5 @@
 	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
-	usb_log_debug("Address bind %d-%d.\n", address, handle);
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
 	usb_device_keeper_bind(&hc->manager, address, handle);
 	return EOK;
Index: uspace/drv/ohci/ohci.c
===================================================================
--- uspace/drv/ohci/ohci.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/ohci.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -148,7 +148,8 @@
 	    pci_get_my_registers(device, &mem_reg_base, &mem_reg_size, &irq);
 	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed(%d) to get memory addresses:.\n", ret, device->handle);
-	usb_log_debug("Memory mapped regs at 0x%X (size %zu), IRQ %d.\n",
-	    mem_reg_base, mem_reg_size, irq);
+	    "Failed to get memory addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
+	    (void *) mem_reg_base, mem_reg_size, irq);
 
 	ret = pci_disable_legacy(device);
Index: uspace/drv/ohci/pci.c
===================================================================
--- uspace/drv/ohci/pci.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/ohci/pci.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -117,6 +117,6 @@
 				mem_address = res->res.mem_range.address;
 				mem_size = res->res.mem_range.size;
-				usb_log_debug2("Found mem: %llx %zu.\n",
-				    mem_address, mem_size);
+				usb_log_debug2("Found mem: %p %zu.\n",
+				    (void *) mem_address, mem_size);
 				mem_found = true;
 				}
Index: uspace/drv/uhci-hcd/batch.c
===================================================================
--- uspace/drv/uhci-hcd/batch.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/batch.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -162,5 +162,5 @@
 	assert(data);
 
-	usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
+	usb_log_debug2("Batch(%p) checking %zu transfer(s) for completion.\n",
 	    instance, data->td_count);
 	instance->transfered_size = 0;
@@ -173,5 +173,5 @@
 		instance->error = td_status(&data->tds[i]);
 		if (instance->error != EOK) {
-			usb_log_debug("Batch(%p) found error TD(%d):%x.\n",
+			usb_log_debug("Batch(%p) found error TD(%zu):%" PRIx32 ".\n",
 			    instance, i, data->tds[i].status);
 			td_print_status(&data->tds[i]);
Index: uspace/drv/uhci-hcd/hc.c
===================================================================
--- uspace/drv/uhci-hcd/hc.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/hc.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -101,5 +101,5 @@
 	    ret, io, str_error(ret));
 	instance->registers = io;
-	usb_log_debug("Device registers at %p(%u) accessible.\n",
+	usb_log_debug("Device registers at %p (%zuB) accessible.\n",
 	    io, reg_size);
 
@@ -423,5 +423,6 @@
 		if (frame_list != addr_to_phys(instance->frame_list)) {
 			usb_log_debug("Framelist address: %p vs. %p.\n",
-			    frame_list, addr_to_phys(instance->frame_list));
+			    (void *) frame_list,
+			    (void *) addr_to_phys(instance->frame_list));
 		}
 
@@ -432,6 +433,6 @@
 		uintptr_t real_pa = addr_to_phys(QH(interrupt));
 		if (expected_pa != real_pa) {
-			usb_log_debug("Interrupt QH: %p(frame: %d) vs. %p.\n",
-			    expected_pa, frnum, real_pa);
+			usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.\n",
+			    (void *) expected_pa, frnum, (void *) real_pa);
 		}
 
@@ -440,5 +441,5 @@
 		if (expected_pa != real_pa) {
 			usb_log_debug("Control Slow QH: %p vs. %p.\n",
-			    expected_pa, real_pa);
+			    (void *) expected_pa, (void *) real_pa);
 		}
 
@@ -447,5 +448,5 @@
 		if (expected_pa != real_pa) {
 			usb_log_debug("Control Full QH: %p vs. %p.\n",
-			    expected_pa, real_pa);
+			    (void *) expected_pa, (void *) real_pa);
 		}
 
@@ -454,5 +455,5 @@
 		if (expected_pa != real_pa ) {
 			usb_log_debug("Bulk QH: %p vs. %p.\n",
-			    expected_pa, real_pa);
+			    (void *) expected_pa, (void *) real_pa);
 		}
 		async_usleep(UHCI_DEBUGER_TIMEOUT);
Index: uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c
===================================================================
--- uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -154,5 +154,5 @@
 	assert(instance);
 	const uint32_t s = instance->status;
-	usb_log_debug2("TD(%p) status(%#x):%s %d,%s%s%s%s%s%s%s%s%s%s%s %d.\n",
+	usb_log_debug2("TD(%p) status(%#" PRIx32 "):%s %d,%s%s%s%s%s%s%s%s%s%s%s %zu.\n",
 	    instance, instance->status,
 	    (s & TD_STATUS_SPD_FLAG) ? " SPD," : "",
Index: uspace/drv/uhci-hcd/iface.c
===================================================================
--- uspace/drv/uhci-hcd/iface.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/iface.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -118,5 +118,5 @@
 	hc_t *hc = fun_to_hc(fun);
 	assert(hc);
-	usb_log_debug("Address bind %d-%d.\n", address, handle);
+	usb_log_debug("Address bind %d-%" PRIun ".\n", address, handle);
 	usb_device_keeper_bind(&hc->manager, address, handle);
 	return EOK;
Index: uspace/drv/uhci-hcd/main.c
===================================================================
--- uspace/drv/uhci-hcd/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -72,6 +72,6 @@
 	int ret = uhci_init(uhci, device);
 	if (ret != EOK) {
-		usb_log_error("Failed(%d) to initialize UHCI driver: %s.\n",
-		    ret, str_error(ret));
+		usb_log_error("Failed to initialize UHCI driver: %s.\n",
+		    str_error(ret));
 		return ret;
 	}
Index: uspace/drv/uhci-hcd/pci.c
===================================================================
--- uspace/drv/uhci-hcd/pci.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/pci.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -90,5 +90,5 @@
 			io_address = res->res.io_range.address;
 			io_size = res->res.io_range.size;
-			usb_log_debug2("Found io: %llx %zu.\n",
+			usb_log_debug2("Found io: %" PRIx64" %zu.\n",
 			    res->res.io_range.address, res->res.io_range.size);
 			io_found = true;
Index: uspace/drv/uhci-hcd/transfer_list.c
===================================================================
--- uspace/drv/uhci-hcd/transfer_list.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/transfer_list.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -58,5 +58,5 @@
 	}
 	uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
-	usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n",
+	usb_log_debug2("Transfer list %s setup with QH: %p (%#" PRIx32" ).\n",
 	    name, instance->queue_head, queue_head_pa);
 
Index: uspace/drv/uhci-hcd/uhci.c
===================================================================
--- uspace/drv/uhci-hcd/uhci.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-hcd/uhci.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -168,7 +168,8 @@
 	    pci_get_my_registers(device, &io_reg_base, &io_reg_size, &irq);
 	CHECK_RET_DEST_FUN_RETURN(ret,
-	    "Failed(%d) to get I/O addresses:.\n", ret, device->handle);
-	usb_log_debug("I/O regs at 0x%X (size %zu), IRQ %d.\n",
-	    io_reg_base, io_reg_size, irq);
+	    "Failed to get I/O addresses for %" PRIun ": %s.\n",
+	    device->handle, str_error(ret));
+	usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n",
+	    (void *) io_reg_base, io_reg_size, irq);
 
 	ret = pci_disable_legacy(device);
Index: uspace/drv/uhci-rhd/main.c
===================================================================
--- uspace/drv/uhci-rhd/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-rhd/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2011 Vojtech Horky, Jan Vesely
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -84,5 +84,6 @@
 		return EINVAL;
 
-	usb_log_debug2("%s called device %d\n", __FUNCTION__, device->handle);
+	usb_log_debug2("uhci_rh_add_device(handle=%" PRIun ")\n",
+	    device->handle);
 
 	uintptr_t io_regs = 0;
@@ -101,6 +102,7 @@
 	ret = hc_get_my_registers(device, &io_regs, &io_size);
 	CHECK_RET_FREE_RH_RETURN(ret,
-	    "Failed(%d) to get registers from HC: %s.\n", ret, str_error(ret));
-	usb_log_debug("I/O regs at %#x (size %zu).\n", io_regs, io_size);
+	    "Failed to get registers from HC: %s.\n", str_error(ret));
+	usb_log_debug("I/O regs at %p (size %zuB).\n",
+	    (void *) io_regs, io_size);
 
 	rh = malloc(sizeof(uhci_root_hub_t));
@@ -115,5 +117,5 @@
 
 	device->driver_data = rh;
-	usb_log_info("Controlling root hub '%s' (%llu).\n",
+	usb_log_info("Controlling root hub '%s' (%" PRIun ").\n",
 	    device->name, device->handle);
 	return EOK;
Index: uspace/drv/uhci-rhd/port.c
===================================================================
--- uspace/drv/uhci-rhd/port.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/uhci-rhd/port.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -89,5 +89,5 @@
 {
 	assert(port);
-	asprintf(&port->id_string, "Port (%p - %d)", port, number);
+	asprintf(&port->id_string, "Port (%p - %u)", port, number);
 	if (port->id_string == NULL) {
 		return ENOMEM;
@@ -115,5 +115,5 @@
 
 	fibril_add_ready(port->checker);
-	usb_log_debug("%s: Started polling fibril(%x).\n",
+	usb_log_debug("%s: Started polling fibril (%" PRIun ").\n",
 	    port->id_string, port->checker);
 	return EOK;
@@ -267,5 +267,5 @@
 	}
 
-	usb_log_info("New device at port %u, address %d (handle %llu).\n",
+	usb_log_info("New device at port %u, address %d (handle %" PRIun ").\n",
 	    port->number, dev_addr, port->attached_device);
 	return EOK;
@@ -283,5 +283,5 @@
 int uhci_port_remove_device(uhci_port_t *port)
 {
-	usb_log_error("%s: Don't know how to remove device %llu.\n",
+	usb_log_error("%s: Don't know how to remove device %" PRIun ".\n",
 	    port->id_string, port->attached_device);
 	return ENOTSUP;
Index: uspace/drv/usbflbk/main.c
===================================================================
--- uspace/drv/usbflbk/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbflbk/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -65,5 +65,5 @@
 
 	usb_log_info("Pretending to control %s `%s'" \
-	    " (node `%s', handle %llu).\n",
+	    " (node `%s', handle %" PRIun ").\n",
 	    dev->interface_no < 0 ? "device" : "interface",
 	    dev->ddf_dev->name, fun_name, dev->ddf_dev->handle);
Index: uspace/drv/usbhid/Makefile
===================================================================
--- uspace/drv/usbhid/Makefile	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/Makefile	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -46,4 +46,5 @@
 	generic/hiddev.c \
 	mouse/mousedev.c \
+	lgtch-ultrax/lgtch-ultrax.c \
 	$(STOLEN_LAYOUT_SOURCES)
 
Index: uspace/drv/usbhid/kbd/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbd/kbddev.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/kbd/kbddev.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -176,4 +176,13 @@
 
 /*----------------------------------------------------------------------------*/
+
+static void usb_kbd_process_keycodes(const uint8_t *key_codes, size_t count,
+    uint8_t report_id, void *arg);
+
+static const usb_hid_report_in_callbacks_t usb_kbd_parser_callbacks = {
+	.keyboard = usb_kbd_process_keycodes
+};
+
+/*----------------------------------------------------------------------------*/
 /* Keyboard layouts                                                           */
 /*----------------------------------------------------------------------------*/
@@ -598,6 +607,6 @@
 	
 	if (count != kbd_dev->key_count) {
-		usb_log_warning("Number of received keycodes (%d) differs from"
-		    " expected number (%d).\n", count, kbd_dev->key_count);
+		usb_log_warning("Number of received keycodes (%zu) differs from"
+		    " expected (%zu).\n", count, kbd_dev->key_count);
 		return;
 	}
@@ -630,10 +639,4 @@
 {
 	assert(hid_dev->parser != NULL);
-	
-	usb_hid_report_in_callbacks_t *callbacks =
-	    (usb_hid_report_in_callbacks_t *)malloc(
-	        sizeof(usb_hid_report_in_callbacks_t));
-	
-	callbacks->keyboard = usb_kbd_process_keycodes;
 
 	usb_log_debug("Calling usb_hid_parse_report() with "
@@ -644,10 +647,10 @@
 	usb_hid_report_path_t *path = usb_hid_report_path();
 	usb_hid_report_path_append_item(path, USB_HIDUT_PAGE_KEYBOARD, 0);
-	usb_hid_report_path_set_report_id(path, 0);
+	//usb_hid_report_path_set_report_id(path, 0);
 	
 	int rc = usb_hid_parse_report(hid_dev->parser, buffer,
 	    actual_size, path, 
 	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
-	    callbacks, hid_dev);
+	    &usb_kbd_parser_callbacks, hid_dev);
 
 	usb_hid_report_path_free(path);
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak, 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 drvusbhid
+ * @{
+ */
+/**
+ * @file
+ * USB Logitech UltraX Keyboard sample driver.
+ */
+
+
+#include "lgtch-ultrax.h"
+#include "../usbhid.h"
+
+#include <usb/classes/hidparser.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+
+#define NAME "lgtch-ultrax"
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
+    uint8_t report_id, void *arg);
+
+static const usb_hid_report_in_callbacks_t usb_lgtch_parser_callbacks = {
+	.keyboard = usb_lgtch_process_keycodes
+};
+
+/*----------------------------------------------------------------------------*/
+
+static void usb_lgtch_process_keycodes(const uint8_t *key_codes, size_t count,
+    uint8_t report_id, void *arg)
+{
+	// TODO: checks
+	
+	usb_log_debug(NAME " Got keys from parser (report id: %u): %s\n", 
+	    report_id, usb_debug_str_buffer(key_codes, count, 0));
+}
+
+/*----------------------------------------------------------------------------*/
+
+bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, 
+    uint8_t *buffer, size_t buffer_size)
+{
+	// TODO: checks
+	
+	usb_log_debug(NAME " usb_lgtch_polling_callback(%p, %p, %zu)\n",
+	    hid_dev, buffer, buffer_size);
+
+	usb_log_debug(NAME " Calling usb_hid_parse_report() with "
+	    "buffer %s\n", usb_debug_str_buffer(buffer, buffer_size, 0));
+	
+	usb_hid_report_path_t *path = usb_hid_report_path();
+	usb_hid_report_path_append_item(path, 0xc, 0);
+	usb_hid_report_path_set_report_id(path, 1);
+	
+	int rc = usb_hid_parse_report(hid_dev->parser, buffer,
+	    buffer_size, path, 
+	    USB_HID_PATH_COMPARE_END | USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY, 
+	    &usb_lgtch_parser_callbacks, hid_dev);
+
+	usb_hid_report_path_free(path);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
+		    "%s\n", str_error(rc));
+	}
+	
+	return true;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h
===================================================================
--- uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/drv/usbhid/lgtch-ultrax/lgtch-ultrax.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Lubos Slovak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup drvusbhid
+ * @{
+ */
+/** @file
+ * USB Logitech UltraX Keyboard sample driver.
+ */
+
+#ifndef USB_HID_LGTCH_ULTRAX_H_
+#define USB_HID_LGTCH_ULTRAX_H_
+
+#include <usb/devdrv.h>
+
+struct usb_hid_dev;
+//struct usb_hid_subdriver_mapping;
+
+/*----------------------------------------------------------------------------*/
+
+//extern struct usb_hid_subdriver_mapping usb_lgtch_mapping;
+
+/*----------------------------------------------------------------------------*/
+
+//int usb_lgtch_init(struct usb_hid_dev *hid_dev);
+
+bool usb_lgtch_polling_callback(struct usb_hid_dev *hid_dev, uint8_t *buffer,
+    size_t buffer_size);
+
+/*----------------------------------------------------------------------------*/
+
+#endif // USB_HID_LGTCH_ULTRAX_H_
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -75,4 +75,6 @@
 static int usb_hid_try_add_device(usb_device_t *dev)
 {
+	assert(dev != NULL);
+	
 	/* 
 	 * Initialize device (get and process descriptors, get address, etc.)
@@ -178,4 +180,9 @@
 	usb_log_debug("usb_hid_add_device()\n");
 	
+	if (dev == NULL) {
+		usb_log_warning("Wrong parameter given for add_device().\n");
+		return EINVAL;
+	}
+	
 	if (dev->interface_no < 0) {
 		usb_log_warning("Device is not a supported HID device.\n");
Index: uspace/drv/usbhid/mouse/mousedev.c
===================================================================
--- uspace/drv/usbhid/mouse/mousedev.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/mouse/mousedev.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -157,10 +157,10 @@
 static void usb_mouse_free(usb_mouse_t **mouse_dev)
 {
-	if (mouse_dev == NULL || *mouse_dev == NULL) {
-		return;
-	}
+	assert(mouse_dev != NULL && *mouse_dev != NULL);
 	
 	// hangup phone to the console
-	async_hangup((*mouse_dev)->console_phone);
+	if ((*mouse_dev)->console_phone >= 0) {
+		async_hangup((*mouse_dev)->console_phone);
+	}
 	
 	free(*mouse_dev);
Index: uspace/drv/usbhid/subdrivers.c
===================================================================
--- uspace/drv/usbhid/subdrivers.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/subdrivers.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -37,23 +37,47 @@
 #include "usb/classes/hidut.h"
 
-static usb_hid_subdriver_usage_t path_kbd[] = {{USB_HIDUT_PAGE_KEYBOARD, 0}};
+#include "lgtch-ultrax/lgtch-ultrax.h"
+
+static usb_hid_subdriver_usage_t path_kbd[] = {
+	{USB_HIDUT_PAGE_KEYBOARD, 0}, 
+	{0, 0}
+};
+
+static usb_hid_subdriver_usage_t lgtch_path[] = {
+	{0xc, 0},
+	{0, 0}
+};
 
 const usb_hid_subdriver_mapping_t usb_hid_subdrivers[] = {
 	{
 		path_kbd,
+		-1,
+		USB_HID_PATH_COMPARE_END 
+		| USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
+		0,
+		0,
+		{
+			.init = usb_kbd_init,
+			.deinit = usb_kbd_deinit,
+			.poll = usb_kbd_polling_callback,
+			.poll_end = NULL
+		},
+		
+	},
+	{
+		lgtch_path,
 		1,
 		USB_HID_PATH_COMPARE_END 
 		| USB_HID_PATH_COMPARE_USAGE_PAGE_ONLY,
-		NULL,
-		NULL,
+		0x046d,
+		0xc30e,
 		{
-			usb_kbd_init,
-			usb_kbd_deinit,
-			usb_kbd_polling_callback,
-			NULL
-		},
-		
+			.init = NULL,
+			.deinit = NULL,
+			.poll = usb_lgtch_polling_callback,
+			.poll_end = NULL
+		}
 	},
-	{NULL, 0, 0, NULL, NULL, {NULL, NULL, NULL, NULL}}
+	{NULL, -1, 0, 0, 0, {NULL, NULL, NULL, NULL}}
 };
 
Index: uspace/drv/usbhid/subdrivers.h
===================================================================
--- uspace/drv/usbhid/subdrivers.h	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/subdrivers.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -54,8 +54,8 @@
 typedef struct usb_hid_subdriver_mapping {
 	const usb_hid_subdriver_usage_t *usage_path;
-	int path_size;
+	int report_id;
 	int compare;
-	const char *vendor_id;
-	const char *product_id;
+	uint16_t vendor_id;
+	uint16_t product_id;
 	usb_hid_subdriver_t subdriver;
 } usb_hid_subdriver_mapping_t;
Index: uspace/drv/usbhid/usbhid.c
===================================================================
--- uspace/drv/usbhid/usbhid.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhid/usbhid.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -67,5 +67,5 @@
 static int usb_hid_set_boot_kbd_subdriver(usb_hid_dev_t *hid_dev)
 {
-	assert(hid_dev->subdriver_count == 0);
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
 	
 	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
@@ -97,5 +97,5 @@
 static int usb_hid_set_boot_mouse_subdriver(usb_hid_dev_t *hid_dev)
 {
-	assert(hid_dev->subdriver_count == 0);
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
 	
 	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
@@ -127,5 +127,5 @@
 static int usb_hid_set_generic_hid_subdriver(usb_hid_dev_t *hid_dev)
 {
-	assert(hid_dev->subdriver_count == 0);
+	assert(hid_dev != NULL && hid_dev->subdriver_count == 0);
 	
 	hid_dev->subdrivers = (usb_hid_subdriver_t *)malloc(
@@ -164,8 +164,8 @@
 
 static bool usb_hid_path_matches(usb_hid_dev_t *hid_dev, 
-    const usb_hid_subdriver_usage_t *path, int path_size, int compare)
+    const usb_hid_subdriver_mapping_t *mapping)
 {
 	assert(hid_dev != NULL);
-	assert(path != NULL);
+	assert(mapping != NULL);
 	
 	usb_hid_report_path_t *usage_path = usb_hid_report_path();
@@ -174,20 +174,28 @@
 		return false;
 	}
-	int i;
-	for (i = 0; i < path_size; ++i) {
+	int i = 0;
+	while (mapping->usage_path[i].usage != 0 
+	    || mapping->usage_path[i].usage_page != 0) {
 		if (usb_hid_report_path_append_item(usage_path, 
-		    path[i].usage_page, path[i].usage) != EOK) {
+		    mapping->usage_path[i].usage_page, 
+		    mapping->usage_path[i].usage) != EOK) {
 			usb_log_debug("Failed to append to usage path.\n");
 			usb_hid_report_path_free(usage_path);
 			return false;
 		}
+		++i;
+	}
+	
+	if (mapping->report_id >= 0) {
+		usb_hid_report_path_set_report_id(usage_path, 
+		    mapping->report_id);
 	}
 	
 	assert(hid_dev->parser != NULL);
 	
-	usb_log_debug("Compare flags: %d\n", compare);
+	usb_log_debug("Compare flags: %d\n", mapping->compare);
 	size_t size = usb_hid_report_input_length(hid_dev->parser, usage_path, 
-	    compare);
-	usb_log_debug("Size of the input report: %d\n", size);
+	    mapping->compare);
+	usb_log_debug("Size of the input report: %zuB\n", size);
 	
 	usb_hid_report_path_free(usage_path);
@@ -231,35 +239,40 @@
 static int usb_hid_find_subdrivers(usb_hid_dev_t *hid_dev)
 {
+	assert(hid_dev != NULL);
+	
 	const usb_hid_subdriver_t *subdrivers[USB_HID_MAX_SUBDRIVERS];
 	
 	int i = 0, count = 0;
 	const usb_hid_subdriver_mapping_t *mapping = &usb_hid_subdrivers[i];
+
+	bool ids_matched;
+	bool matched;
 	
 	while (count < USB_HID_MAX_SUBDRIVERS &&
 	    (mapping->usage_path != NULL
-	    || mapping->vendor_id != NULL
-	    || mapping->product_id != NULL)) {
+	    || mapping->vendor_id != 0 || mapping->product_id != 0)) {
 		// check the vendor & product ID
-		if (mapping->vendor_id != NULL && mapping->product_id == NULL) {
-			usb_log_warning("Missing Product ID for Vendor ID %s\n",
+		if (mapping->vendor_id != 0 && mapping->product_id == 0) {
+			usb_log_warning("Missing Product ID for Vendor ID %u\n",
 			    mapping->vendor_id);
 			return EINVAL;
 		}
-		if (mapping->product_id != NULL && mapping->vendor_id == NULL) {
-			usb_log_warning("Missing Vendor ID for Product ID %s\n",
+		if (mapping->product_id != 0 && mapping->vendor_id == 0) {
+			usb_log_warning("Missing Vendor ID for Product ID %u\n",
 			    mapping->product_id);
 			return EINVAL;
 		}
 		
-		if (mapping->vendor_id != NULL) {
-			assert(mapping->product_id != NULL);
-			usb_log_debug("Comparing device against vendor ID %s"
-			    " and product ID %s.\n", mapping->vendor_id,
+		ids_matched = false;
+		matched = false;
+		
+		if (mapping->vendor_id != 0) {
+			assert(mapping->product_id != 0);
+			usb_log_debug("Comparing device against vendor ID %u"
+			    " and product ID %u.\n", mapping->vendor_id,
 			    mapping->product_id);
 			if (usb_hid_ids_match(hid_dev, mapping)) {
-				usb_log_debug("Matched.\n");
-				subdrivers[count++] = &mapping->subdriver;
-				// skip the checking of usage path
-				goto next;
+				usb_log_debug("IDs matched.\n");
+				ids_matched = true;
 			}
 		}
@@ -267,13 +280,17 @@
 		if (mapping->usage_path != NULL) {
 			usb_log_debug("Comparing device against usage path.\n");
-			if (usb_hid_path_matches(hid_dev, 
-			    mapping->usage_path, mapping->path_size,
-			    mapping->compare)) {
-				subdrivers[count++] = &mapping->subdriver;
-			} else {
-				usb_log_debug("Not matched.\n");
+			if (usb_hid_path_matches(hid_dev, mapping)) {
+				// does not matter if IDs were matched
+				matched = true;
 			}
-		}
-	next:
+		} else {
+			// matched only if IDs were matched and there is no path
+			matched = ids_matched;
+		}
+		
+		if (matched) {
+			subdrivers[count++] = &mapping->subdriver;
+		}
+		
 		mapping = &usb_hid_subdrivers[++i];
 	}
@@ -287,4 +304,6 @@
 static int usb_hid_check_pipes(usb_hid_dev_t *hid_dev, usb_device_t *dev)
 {
+	assert(hid_dev != NULL && dev != NULL);
+	
 	int rc = EOK;
 	
Index: uspace/drv/usbhub/ports.c
===================================================================
--- uspace/drv/usbhub/ports.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhub/ports.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -83,5 +83,5 @@
 void usb_hub_process_interrupt(usb_hub_info_t * hub,
 	uint16_t port) {
-	usb_log_debug("interrupt at port %d\n", port);
+	usb_log_debug("interrupt at port %zu\n", (size_t) port);
 	//determine type of change
 	//usb_pipe_t *pipe = hub->control_pipe;
@@ -93,5 +93,5 @@
 	if (opResult != EOK) {
 		usb_log_error("Failed to get port %zu status: %s.\n",
-		    port, str_error(opResult));
+		    (size_t) port, str_error(opResult));
 		return;
 	}
@@ -100,5 +100,6 @@
 		bool device_connected = usb_port_is_status(status,
 		    USB_HUB_FEATURE_PORT_CONNECTION);
-		usb_log_debug("Connection change on port %zu: %s.\n", port,
+		usb_log_debug("Connection change on port %zu: %s.\n",
+		    (size_t) port,
 		    device_connected ? "device attached" : "device removed");
 
@@ -109,5 +110,5 @@
 				usb_log_error(
 				    "Cannot handle change on port %zu: %s.\n",
-				    str_error(opResult));
+				    (size_t) port, str_error(opResult));
 			}
 		} else {
@@ -210,5 +211,5 @@
 static void usb_hub_port_reset_completed(usb_hub_info_t * hub,
 	uint16_t port, uint32_t status){
-	usb_log_debug("Port %zu reset complete.\n", port);
+	usb_log_debug("Port %zu reset complete.\n", (size_t) port);
 	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
 		/* Finalize device adding. */
@@ -222,5 +223,5 @@
 		usb_log_warning(
 		    "Port %zu reset complete but port not enabled.\n",
-		    port);
+		    (size_t) port);
 	}
 }
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbhub/usbhub.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -260,6 +260,6 @@
 				    port+1, USB_HUB_FEATURE_PORT_POWER);
 				if (opResult != EOK) {
-					usb_log_error("cannot power on port %d;  %d\n",
-					    port+1, opResult);
+					usb_log_error("cannot power on port %zu: %s.\n",
+					    port+1, str_error(opResult));
 				}
 			}
@@ -269,6 +269,6 @@
 			    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
 			if (opResult != EOK) {
-				usb_log_error("cannot power hub;  %d\n",
-				  opResult);
+				usb_log_error("cannot power hub: %s\n",
+				    str_error(opResult));
 			}
 		}
@@ -356,5 +356,5 @@
 	}
 
-	usb_log_info("Controlling hub `%s' (%d ports).\n",
+	usb_log_info("Controlling hub `%s' (%zu ports).\n",
 	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
 	return EOK;
@@ -424,6 +424,6 @@
 			    port, USB_HUB_FEATURE_PORT_POWER);
 			if (opResult != EOK) {
-				usb_log_error("cannot power on port %d;  %d\n",
-				    port, opResult);
+				usb_log_error("Cannot power on port %zu: %s.\n",
+				    port, str_error(opResult));
 			}
 		}
Index: uspace/drv/usbkbd/kbddev.c
===================================================================
--- uspace/drv/usbkbd/kbddev.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbkbd/kbddev.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -567,6 +567,6 @@
 	
 	if (count != kbd_dev->key_count) {
-		usb_log_warning("Number of received keycodes (%d) differs from"
-		    " expected number (%d).\n", count, kbd_dev->key_count);
+		usb_log_warning("Number of received keycodes (%zu) differs from"
+		    " expected (%zu).\n", count, kbd_dev->key_count);
 		return;
 	}
Index: uspace/drv/usbmid/main.c
===================================================================
--- uspace/drv/usbmid/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbmid/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -53,12 +53,5 @@
 	usb_log_info("Taking care of new MID `%s'.\n", dev->ddf_dev->name);
 
-	int rc;
-
-	rc = usb_pipe_start_long_transfer(&dev->ctrl_pipe);
-	if (rc != EOK) {
-		usb_log_error("Failed to start transfer on control pipe: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
+	usb_pipe_start_long_transfer(&dev->ctrl_pipe);
 
 	bool accept = usbmid_explore_device(dev);
Index: uspace/drv/usbmouse/init.c
===================================================================
--- uspace/drv/usbmouse/init.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbmouse/init.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -125,10 +125,4 @@
 	}
 	
-	/* Open the control pipe. */
-	rc = usb_pipe_start_session(&dev->ctrl_pipe);
-	if (rc != EOK) {
-		goto leave;
-	}
-	
 	/* Set the boot protocol. */
 	rc = usb_control_request_set(&dev->ctrl_pipe,
@@ -140,9 +134,5 @@
 	}
 	
-	/* Close the control pipe (ignore errors). */
-	usb_pipe_end_session(&dev->ctrl_pipe);
-
-
-	/* Everything allright. */
+	/* Everything all right. */
 	dev->driver_data = mouse;
 	mouse->mouse_fun->driver_data = mouse;
Index: uspace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/usbmouse/main.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -54,5 +54,6 @@
 	}
 
-	usb_log_debug("Polling pipe at endpoint %d.\n", dev->pipes[0].pipe->endpoint_no);
+	usb_log_debug("Polling pipe at endpoint %d.\n",
+	    dev->pipes[0].pipe->endpoint_no);
 
 	rc = usb_device_auto_poll(dev, 0,
@@ -66,5 +67,5 @@
 	}
 
-	usb_log_info("controlling new mouse (handle %llu).\n",
+	usb_log_info("controlling new mouse (handle %" PRIun ").\n",
 	    dev->ddf_dev->handle);
 
Index: uspace/drv/vhc/conndev.c
===================================================================
--- uspace/drv/vhc/conndev.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/drv/vhc/conndev.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -99,5 +99,5 @@
 		int rc = get_device_name(callback, devname, DEVICE_NAME_MAXLENGTH);
 
-		usb_log_info("New virtual device `%s' (id = %x).\n",
+		usb_log_info("New virtual device `%s' (id = %" PRIxn ").\n",
 		    rc == EOK ? devname : "<unknown>", dev->id);
 
@@ -122,5 +122,6 @@
 	}
 
-	usb_log_info("Virtual device disconnected (id = %x).\n", dev->id);
+	usb_log_info("Virtual device disconnected (id = %" PRIxn ").\n",
+	    dev->id);
 	virtdev_destroy_device(dev);
 }
Index: uspace/lib/c/include/ipc/dev_iface.h
===================================================================
--- uspace/lib/c/include/ipc/dev_iface.h	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/c/include/ipc/dev_iface.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -45,4 +45,6 @@
 	/** Interface provided by USB host controller. */
 	USBHC_DEV_IFACE,
+	/** Interface provided by USB HID devices. */
+	USBHID_DEV_IFACE,
 
 	DEV_IFACE_MAX
Index: uspace/lib/drv/generic/dev_iface.c
===================================================================
--- uspace/lib/drv/generic/dev_iface.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/drv/generic/dev_iface.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -43,4 +43,5 @@
 #include "remote_usb.h"
 #include "remote_usbhc.h"
+#include "remote_usbhid.h"
 #include "remote_pci.h"
 
@@ -51,5 +52,6 @@
 		&remote_pci_iface,
 		&remote_usb_iface,
-		&remote_usbhc_iface
+		&remote_usbhc_iface,
+		&remote_usbhid_iface
 	}
 };
Index: uspace/lib/drv/generic/remote_usbhid.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhid.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/lib/drv/generic/remote_usbhid.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2010-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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "usbhid_iface.h"
+#include "ddf/driver.h"
+
+static void remote_usbhid_get_event_length(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhid_get_event(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+// static void remote_usbhid_(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+
+/** Remote USB HID interface operations. */
+static remote_iface_func_ptr_t remote_usbhid_iface_ops [] = {
+	remote_usbhid_get_event_length,
+	remote_usbhid_get_event
+};
+
+/** Remote USB HID interface structure.
+ */
+remote_iface_t remote_usbhid_iface = {
+	.method_count = sizeof(remote_usbhid_iface_ops) /
+	    sizeof(remote_usbhid_iface_ops[0]),
+	.methods = remote_usbhid_iface_ops
+};
+
+usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+
+void remote_usbhid_get_event_length(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_event_length) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	int len = hid_iface->get_event_length(fun);
+	if (len == 0) {
+		len = EEMPTY;
+	}
+	if (len < 0) {
+		async_answer_0(callid, len);
+	} else {
+		async_answer_1(callid, EOK, len);
+	}
+}
+
+void remote_usbhid_get_event(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhid_iface_t *hid_iface = (usbhid_iface_t *) iface;
+
+	if (!hid_iface->get_event) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	unsigned int flags = DEV_IPC_GET_ARG1(*call);
+
+	size_t len;
+	ipc_callid_t data_callid;
+	if (!async_data_read_receive(&data_callid, &len)) {
+		async_answer_0(callid, EPARTY);
+		return;
+	}
+	/* Check that length is even number. Truncate otherwise. */
+	if ((len % 2) == 1) {
+		len--;
+	}
+	if (len == 0) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+	}
+
+	int rc;
+
+	size_t items = len / 2;
+	uint16_t *usage_pages_and_usages = malloc(sizeof(uint16_t) * len);
+	if (usage_pages_and_usages == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(callid, ENOMEM);
+	}
+
+	size_t act_items;
+	int rc = hid_iface->get_event(fun, usage_pages_and_usages,
+	    usage_pages_and_usages + items, items, &act_items, flags);
+	if (rc != EOK) {
+		free(usage_pages_and_usages);
+		async_answer_0(data_callid, rc);
+		async_answer_0(callid, rc);
+	}
+	if (act_items >= items) {
+		/* This shall not happen. */
+		// FIXME: how about an assert here?
+		act_items = items;
+	}
+
+	async_data_read_finalize(data_callid, usage_pages_and_usages,
+	    act_items * 2 * sizeof(uint16_t));
+
+	free(usage_pages_and_usages);
+
+	async_answer_0(callid, EOK);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/remote_usbhid.h
===================================================================
--- uspace/lib/drv/include/remote_usbhid.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/lib/drv/include/remote_usbhid.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,44 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBDRV_REMOTE_USBHID_H_
+#define LIBDRV_REMOTE_USBHID_H_
+
+remote_iface_t remote_usbhid_iface;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/lib/drv/include/usbhid_iface.h
===================================================================
--- uspace/lib/drv/include/usbhid_iface.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/lib/drv/include/usbhid_iface.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,100 @@
+/*
+ * 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 libdrv
+ * @{
+ */
+/** @file
+ * USB HID interface definition.
+ */
+
+#ifndef LIBDRV_USBHID_IFACE_H_
+#define LIBDRV_USBHID_IFACE_H_
+
+#include "ddf/driver.h"
+#include <usb/usb.h>
+
+/** IPC methods for USB HID device interface. */
+typedef enum {
+	/** Get number of events reported in single burst.
+	 * Parameters: none
+	 * Answer:
+	 * - EOK (expected always as long as device support USB HID interface)
+	 * Parameters of the answer:
+	 * - number of items
+	 */
+	IPC_M_USBHID_GET_EVENT_LENGTH,
+	/** Get single event from the HID device.
+	 * The word single refers to set of individual events that were
+	 * available at particular point in time.
+	 * Parameters:
+	 * - flags
+	 * The call is followed by data read expecting two concatenated
+	 * arrays.
+	 * Answer:
+	 * - EOK - events returned
+	 * - EAGAIN - no event ready (only in non-blocking mode)
+	 *
+	 * It is okay if the client requests less data. Extra data must
+	 * be truncated by the driver.
+	 */
+	IPC_M_USBHID_GET_EVENT
+} usbhid_iface_funcs_t;
+
+/** USB HID interface flag - return immediately if no data are available. */
+#define USBHID_IFACE_FLAG_NON_BLOCKING (1 << 0)
+
+/** USB HID device communication interface. */
+typedef struct {
+	/** Get number of items in the event.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @return Number of events or error code.
+	 */
+	int (*get_event_length)(ddf_fun_t *fun);
+
+	/** Get single event from the HID device.
+	 *
+	 * @param[in] fun DDF function answering the request.
+	 * @param[out] usage_page Array of usage pages and usages.
+	 * @param[out] usage Array of data (1:1 with @p usage).
+	 * @param[in] size Size of @p usage and @p data arrays.
+	 * @param[out] act_size Actual number of returned events.
+	 * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
+	 * @return Error code.
+	 */
+	int (*get_event)(ddf_fun_t *fun,
+	    uint16_t *usage_page, uint16_t *usage, size_t size, size_t *act_size,
+	    unsigned int flags);
+} usbhid_iface_t;
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/Makefile	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -42,4 +42,5 @@
 	src/dp.c \
 	src/dump.c \
+	src/hidiface.c \
 	src/hidparser.c \
 	src/hub.c \
Index: uspace/lib/usb/include/usb/classes/hid/iface.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hid/iface.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/lib/usb/include/usb/classes/hid/iface.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,47 @@
+/*
+ * 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
+ * Client functions for accessing USB HID interface.
+ */
+#ifndef LIBUSB_CLASSES_HID_IFACE_H_
+#define LIBUSB_CLASSES_HID_IFACE_H_
+
+#include <sys/types.h>
+
+int usbhid_dev_get_event_length(int);
+int usbhid_dev_get_event(int, uint16_t *, uint16_t *, size_t, size_t *,
+    unsigned int);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/debug.h
===================================================================
--- uspace/lib/usb/include/usb/debug.h	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/include/usb/debug.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -36,4 +36,5 @@
 #define LIBUSB_DEBUG_H_
 #include <stdio.h>
+#include <inttypes.h>
 #include <usb/usb.h>
 #include <assert.h>
@@ -85,5 +86,6 @@
 void usb_log_enable(usb_log_level_t, const char *);
 
-void usb_log_printf(usb_log_level_t, const char *, ...);
+void usb_log_printf(usb_log_level_t, const char *, ...)
+	PRINTF_ATTRIBUTE(2, 3);
 
 /** Log fatal error. */
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/include/usb/pipes.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -99,4 +99,18 @@
 	/** Number of active transfers over the pipe. */
 	int refcount;
+	/** Number of failed attempts to open the HC phone.
+	 * When user requests usb_pipe_start_long_transfer() and the operation
+	 * fails, there is no way to report this to the user.
+	 * That the soft reference counter is increased to record the attempt.
+	 * When the user then request e.g. usb_pipe_read(), it will try to
+	 * add reference as well.
+	 * If that fails, it is reported to the user. If it is okay, the
+	 * real reference counter is incremented.
+	 * The problem might arise when ending the long transfer (since
+	 * the number of references would be only 1, but logically it shall be
+	 * two).
+	 * Decrementing the soft counter first shall solve this.
+	 */
+	int refcount_soft;
 
 	/** Whether to automatically reset halt on the endpoint.
@@ -163,9 +177,5 @@
 int usb_pipe_unregister(usb_pipe_t *, usb_hc_connection_t *);
 
-int usb_pipe_start_session(usb_pipe_t *);
-int usb_pipe_end_session(usb_pipe_t *);
-bool usb_pipe_is_session_started(usb_pipe_t *);
-
-int usb_pipe_start_long_transfer(usb_pipe_t *);
+void usb_pipe_start_long_transfer(usb_pipe_t *);
 void usb_pipe_end_long_transfer(usb_pipe_t *);
 
Index: uspace/lib/usb/src/devdrv.c
===================================================================
--- uspace/lib/usb/src/devdrv.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/devdrv.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -236,8 +236,5 @@
 
 	/* It is worth to start a long transfer. */
-	rc = usb_pipe_start_long_transfer(ctrl_pipe);
-	if (rc != EOK) {
-		return rc;
-	}
+	usb_pipe_start_long_transfer(ctrl_pipe);
 
 	/* Get the device descriptor. */
Index: uspace/lib/usb/src/devpoll.c
===================================================================
--- uspace/lib/usb/src/devpoll.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/devpoll.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -78,5 +78,5 @@
 		usb_endpoint_mapping_t *mapping
 		    = &polling_data->dev->pipes[polling_data->pipe_index];
-		usb_log_debug("Poll0x%x: started polling of `%s' - " \
+		usb_log_debug("Poll%p: started polling of `%s' - " \
 		    "interface %d (%s,%d,%d), %zuB/%zu.\n",
 		    polling_data,
@@ -100,5 +100,5 @@
 			if (rc == EOK) {
 				usb_log_debug(
-				    "Poll0x%x: received: '%s' (%zuB).\n",
+				    "Poll%p: received: '%s' (%zuB).\n",
 				    polling_data,
 				    usb_debug_str_buffer(polling_data->buffer,
@@ -107,5 +107,5 @@
 			} else {
 				usb_log_debug(
-				    "Poll0x%x: polling failed: %s.\n",
+				    "Poll%p: polling failed: %s.\n",
 				    polling_data, str_error(rc));
 			}
Index: uspace/lib/usb/src/hidiface.c
===================================================================
--- uspace/lib/usb/src/hidiface.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
+++ uspace/lib/usb/src/hidiface.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -0,0 +1,146 @@
+/*
+ * 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
+ * Client functions for accessing USB HID interface (implementation).
+ */
+#include <dev_iface.h>
+#include <usbhid_iface.h>
+#include <usb/classes/hid/iface.h>
+#include <errno.h>
+#include <str_error.h>
+#include <async.h>
+#include <assert.h>
+
+/** Ask for event array length.
+ *
+ * @param dev_phone Opened phone to DDF device providing USB HID interface.
+ * @return Number of usages returned or negative error code.
+ */
+int usbhid_dev_get_event_length(int dev_phone)
+{
+	if (dev_phone < 0) {
+		return EINVAL;
+	}
+
+	sysarg_t len;
+	int rc = async_req_1_1(dev_phone, DEV_IFACE_ID(USBHID_DEV_IFACE),
+	    IPC_M_USBHID_GET_EVENT_LENGTH, &len);
+	if (rc == EOK) {
+		return (int) len;
+	} else {
+		return rc;
+	}
+}
+
+/** Request for next event from HID device.
+ *
+ * @param[in] dev_phone Opened phone to DDF device providing USB HID interface.
+ * @param[out] usage_pages Where to store usage pages.
+ * @param[out] usages Where to store usages (actual data).
+ * @param[in] usage_count Length of @p usage_pages and @p usages buffer
+ *	(in items, not bytes).
+ * @param[out] actual_usage_count Number of usages actually returned by the
+ *	device driver.
+ * @param[in] flags Flags (see USBHID_IFACE_FLAG_*).
+ * @return Error code.
+ */
+int usbhid_dev_get_event(int dev_phone, uint16_t *usage_pages, uint16_t *usages,
+    size_t usage_count, size_t *actual_usage_count, unsigned int flags)
+{
+	if (dev_phone < 0) {
+		return EINVAL;
+	}
+	if ((usage_pages == NULL) || (usages == NULL)) {
+		return ENOMEM;
+	}
+	if (usage_count == 0) {
+		return EINVAL;
+	}
+
+	size_t buffer_size = sizeof(uint16_t) * usage_count * 2;
+	uint16_t *buffer = malloc(buffer_size);
+	if (buffer == NULL) {
+		return ENOMEM;
+	}
+
+	aid_t opening_request = async_send_2(dev_phone,
+	    DEV_IFACE_ID(USBHID_DEV_IFACE), IPC_M_USBHID_GET_EVENT,
+	    flags, NULL);
+	if (opening_request == 0) {
+		free(buffer);
+		return ENOMEM;
+	}
+
+	ipc_call_t data_request_call;
+	aid_t data_request = async_data_read(dev_phone, buffer, buffer_size,
+	    &data_request_call);
+	if (data_request == 0) {
+		async_wait_for(opening_request, NULL);
+		free(buffer);
+		return ENOMEM;
+	}
+
+	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) {
+		/* Prefer return code of the opening request. */
+		if (opening_request_rc != EOK) {
+			return (int) opening_request_rc;
+		} else {
+			return (int) data_request_rc;
+		}
+	}
+
+	if (opening_request_rc != EOK) {
+		return (int) opening_request_rc;
+	}
+
+	size_t actual_size = IPC_GET_ARG2(data_request_call);
+	size_t items = actual_size / 2;
+
+	/* Copy the individual items. */
+	memcpy(usage_pages, buffer, items * sizeof(uint16_t));
+	memcpy(usages, buffer + items, items * sizeof(uint16_t));
+
+	if (actual_usage_count != NULL) {
+		*actual_usage_count = items;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/hidparser.c
===================================================================
--- uspace/lib/usb/src/hidparser.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/hidparser.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -167,5 +167,5 @@
 
 			usb_log_debug2(
-				"i(%u) data(%X) value(%X): TAG %u, class %u, size %u - ", i, 
+				"i(%zu) data(%X) value(%X): TAG %d, class %u, size %u - ", i,
 			    data[i], usb_hid_report_tag_data_int32(data+i+1,item_size), 
 			    tag, class, item_size);
@@ -576,5 +576,5 @@
 		report_item = list_get_instance(item, usb_hid_report_item_t, link);
 
-		usb_log_debug("\tOFFSET: %X\n", report_item->offset);
+		usb_log_debug("\tOFFSET: %zX\n", report_item->offset);
 		usb_log_debug("\tCOUNT: %X\n", report_item->count);
 		usb_log_debug("\tSIZE: %X\n", report_item->size);
Index: uspace/lib/usb/src/hidreport.c
===================================================================
--- uspace/lib/usb/src/hidreport.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/hidreport.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -109,5 +109,5 @@
 	
 	if (*d != sizeof(usb_standard_hid_descriptor_t)) {
-		usb_log_error("HID descriptor hass wrong size (%u, expected %u"
+		usb_log_error("HID descriptor has wrong size (%u, expected %zu"
 		    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
 		return EINVAL;
@@ -149,5 +149,5 @@
 		free(*report_desc);
 		*report_desc = NULL;
-		usb_log_error("Report descriptor has wrong size (%u, expected "
+		usb_log_error("Report descriptor has wrong size (%zu, expected "
 		    "%u)\n", actual_size, length);
 		return EINVAL;
Index: uspace/lib/usb/src/pipepriv.c
===================================================================
--- uspace/lib/usb/src/pipepriv.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/pipepriv.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -77,10 +77,11 @@
  *
  * @param pipe The USB pipe.
+ * @param hide_failure Whether to hide failure when adding reference
+ *	(use soft refcount).
  * @return Error code.
  * @retval EOK Currently always.
  */
-int pipe_add_ref(usb_pipe_t *pipe)
+int pipe_add_ref(usb_pipe_t *pipe, bool hide_failure)
 {
-another_try:
 	pipe_acquire(pipe);
 
@@ -89,8 +90,10 @@
 		int phone = devman_device_connect(pipe->wire->hc_handle, 0);
 		if (phone < 0) {
-			// TODO: treat some error as non-recoverable
-			// and return error from here
+			if (hide_failure) {
+				pipe->refcount_soft++;
+				phone = EOK;
+			}
 			pipe_release(pipe);
-			goto another_try;
+			return phone;
 		}
 		/*
@@ -114,4 +117,9 @@
 {
 	pipe_acquire(pipe);
+	if (pipe->refcount_soft > 0) {
+		pipe->refcount_soft--;
+		pipe_release(pipe);
+		return;
+	}
 	assert(pipe->refcount > 0);
 	pipe->refcount--;
Index: uspace/lib/usb/src/pipepriv.h
===================================================================
--- uspace/lib/usb/src/pipepriv.h	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/pipepriv.h	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -37,4 +37,5 @@
 
 #include <usb/pipes.h>
+#include <bool.h>
 
 void pipe_acquire(usb_pipe_t *);
@@ -44,5 +45,5 @@
 void pipe_end_transaction(usb_pipe_t *);
 
-int pipe_add_ref(usb_pipe_t *);
+int pipe_add_ref(usb_pipe_t *, bool);
 void pipe_drop_ref(usb_pipe_t *);
 
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/pipes.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -229,62 +229,4 @@
 }
 
-
-/** 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_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.
- *
- * @deprecated
- * Obsoleted with introduction of usb_pipe_start_long_transfer
- *
- * @param pipe Endpoint pipe to start the session on.
- * @return Error code.
- */
-int usb_pipe_start_session(usb_pipe_t *pipe)
-{
-	usb_log_warning("usb_pipe_start_session() was deprecated.\n");
-	return EOK;
-}
-
-
-/** Ends a session on the endpoint pipe.
- *
- * @deprecated
- * Obsoleted with introduction of usb_pipe_end_long_transfer
- *
- * @see usb_pipe_start_session
- *
- * @param pipe Endpoint pipe to end the session on.
- * @return Error code.
- */
-int usb_pipe_end_session(usb_pipe_t *pipe)
-{
-	usb_log_warning("usb_pipe_end_session() was deprecated.\n");
-	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_pipe_is_session_started(usb_pipe_t *pipe)
-{
-	pipe_acquire(pipe);
-	bool started = pipe->refcount > 0;
-	pipe_release(pipe);
-	return started;
-}
-
 /** Prepare pipe for a long transfer.
  *
@@ -297,7 +239,7 @@
  * @return Error code.
  */
-int usb_pipe_start_long_transfer(usb_pipe_t *pipe)
-{
-	return pipe_add_ref(pipe);
+void usb_pipe_start_long_transfer(usb_pipe_t *pipe)
+{
+	(void) pipe_add_ref(pipe, true);
 }
 
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/pipesinit.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -365,4 +365,5 @@
 	pipe->direction = direction;
 	pipe->refcount = 0;
+	pipe->refcount_soft = 0;
 	pipe->auto_reset_halt = false;
 
@@ -419,9 +420,5 @@
 	int rc;
 
-	rc = usb_pipe_start_long_transfer(pipe);
-	if (rc != EOK) {
-		return rc;
-	}
-
+	usb_pipe_start_long_transfer(pipe);
 
 	uint8_t dev_descr_start[CTRL_PIPE_MIN_PACKET_SIZE];
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision 618f9ed0d05aeb2f9366eacc8428e206d3ead1fa)
+++ uspace/lib/usb/src/pipesio.c	(revision 44b1674ec560a7cde85edaf566ac5467993d0963)
@@ -173,5 +173,5 @@
 
 	int rc;
-	rc = pipe_add_ref(pipe);
+	rc = pipe_add_ref(pipe, false);
 	if (rc != EOK) {
 		return rc;
@@ -296,5 +296,5 @@
 	int rc;
 
-	rc = pipe_add_ref(pipe);
+	rc = pipe_add_ref(pipe, false);
 	if (rc != EOK) {
 		return rc;
@@ -447,5 +447,5 @@
 	int rc;
 
-	rc = pipe_add_ref(pipe);
+	rc = pipe_add_ref(pipe, false);
 	if (rc != EOK) {
 		return rc;
@@ -579,5 +579,5 @@
 	int rc;
 
-	rc = pipe_add_ref(pipe);
+	rc = pipe_add_ref(pipe, false);
 	if (rc != EOK) {
 		return rc;
