Index: uspace/drv/usbhid/hiddev.c
===================================================================
--- uspace/drv/usbhid/hiddev.c	(revision a763eb4d5e9d22c780e468eaa52dfda2c2e80ed4)
+++ uspace/drv/usbhid/hiddev.c	(revision 103cf26a44475a0b5eab1330fbc1d8306d448745)
@@ -440,4 +440,5 @@
 	if (rc != EOK) {
 		/* TODO: end session?? */
+		usb_endpoint_pipe_end_session(&hid_dev->ctrl_pipe);
 		usb_log_error("Failed to process descriptors: %s.\n",
 		    str_error(rc));
Index: uspace/drv/usbhid/hiddev.h
===================================================================
--- uspace/drv/usbhid/hiddev.h	(revision a763eb4d5e9d22c780e468eaa52dfda2c2e80ed4)
+++ uspace/drv/usbhid/hiddev.h	(revision 103cf26a44475a0b5eab1330fbc1d8306d448745)
@@ -32,4 +32,9 @@
 /** @file
  * Generic USB HID device structure and API.
+ *
+ * @todo Add function for parsing report - this is generic HID function, not
+ *       keyboard-specific, as the report parser is also generic.
+ * @todo Add function for polling as that is also a generic HID process.
+ * @todo Add interrupt in pipe to the structure.
  */
 
Index: uspace/drv/usbhid/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbddev.c	(revision a763eb4d5e9d22c780e468eaa52dfda2c2e80ed4)
+++ uspace/drv/usbhid/kbddev.c	(revision 103cf26a44475a0b5eab1330fbc1d8306d448745)
@@ -94,4 +94,10 @@
 	.flags = 0
 };
+
+typedef enum usbhid_kbd_flags {
+	USBHID_KBD_STATUS_UNINITIALIZED = 0,
+	USBHID_KBD_STATUS_INITIALIZED = 1,
+	USBHID_KBD_STATUS_TO_DESTROY = -1
+} usbhid_kbd_flags;
 
 /*----------------------------------------------------------------------------*/
@@ -232,5 +238,5 @@
 	
 	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized);
+	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
 	usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 
 	    buffer, BOOTP_BUFFER_OUT_SIZE);
@@ -565,5 +571,5 @@
                                     uint8_t *buffer, size_t actual_size)
 {
-	assert(kbd_dev->initialized);
+	assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
 	assert(kbd_dev->hid_dev->parser != NULL);
 	
@@ -619,5 +625,5 @@
 	
 	kbd_dev->console_phone = -1;
-	kbd_dev->initialized = 0;
+	kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED;
 	
 	return kbd_dev;
@@ -625,31 +631,8 @@
 
 /*----------------------------------------------------------------------------*/
-/**
- * Properly destroys the USB/HID keyboard structure.
- *
- * @param kbd_dev Pointer to the structure to be destroyed.
- */
-static void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
-{
-	if (kbd_dev == NULL || *kbd_dev == NULL) {
-		return;
-	}
-	
-	// hangup phone to the console
-	async_hangup((*kbd_dev)->console_phone);
-	
-	if ((*kbd_dev)->hid_dev != NULL) {
-		usbhid_dev_free(&(*kbd_dev)->hid_dev);
-		assert((*kbd_dev)->hid_dev == NULL);
-	}
-	
-	if ((*kbd_dev)->repeat_mtx != NULL) {
-		/* TODO: replace by some check and wait */
-		assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
-		free((*kbd_dev)->repeat_mtx);
-	}
-
-	free(*kbd_dev);
-	*kbd_dev = NULL;
+
+static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)
+{
+	kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;
 }
 
@@ -693,5 +676,5 @@
 	}
 	
-	if (kbd_dev->initialized) {
+	if (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED) {
 		usb_log_warning("Keyboard structure already initialized.\n");
 		return EINVAL;
@@ -706,5 +689,5 @@
 	}
 	
-	assert(kbd_dev->hid_dev->initialized);
+	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
 	
 	// save the size of the report (boot protocol report by default)
@@ -758,5 +741,5 @@
 	usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
 	
-	kbd_dev->initialized = 1;
+	kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED;
 	usb_log_info("HID/KBD device structure initialized.\n");
 	
@@ -872,7 +855,10 @@
 	usbhid_kbd_poll(kbd_dev);
 	
+	// as there is another fibril using this device, so we must leave the
+	// structure to it, but mark it for destroying.
+	usbhid_kbd_mark_unusable(kbd_dev);
 	// at the end, properly destroy the KBD structure
-	usbhid_kbd_free(&kbd_dev);
-	assert(kbd_dev == NULL);
+//	usbhid_kbd_free(&kbd_dev);
+//	assert(kbd_dev == NULL);
 
 	return EOK;
@@ -996,4 +982,41 @@
 }
 
+/*----------------------------------------------------------------------------*/
+
+int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev)
+{
+	return (kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
+}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Properly destroys the USB/HID keyboard structure.
+ *
+ * @param kbd_dev Pointer to the structure to be destroyed.
+ */
+void usbhid_kbd_free(usbhid_kbd_t **kbd_dev)
+{
+	if (kbd_dev == NULL || *kbd_dev == NULL) {
+		return;
+	}
+	
+	// hangup phone to the console
+	async_hangup((*kbd_dev)->console_phone);
+	
+	if ((*kbd_dev)->hid_dev != NULL) {
+		usbhid_dev_free(&(*kbd_dev)->hid_dev);
+		assert((*kbd_dev)->hid_dev == NULL);
+	}
+	
+	if ((*kbd_dev)->repeat_mtx != NULL) {
+		/* TODO: replace by some check and wait */
+		assert(!fibril_mutex_is_locked((*kbd_dev)->repeat_mtx));
+		free((*kbd_dev)->repeat_mtx);
+	}
+
+	free(*kbd_dev);
+	*kbd_dev = NULL;
+}
+
 /**
  * @}
Index: uspace/drv/usbhid/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbddev.h	(revision a763eb4d5e9d22c780e468eaa52dfda2c2e80ed4)
+++ uspace/drv/usbhid/kbddev.h	(revision 103cf26a44475a0b5eab1330fbc1d8306d448745)
@@ -101,5 +101,10 @@
 	fibril_mutex_t *repeat_mtx;
 	
-	/** State of the structure (for checking before use). */
+	/** State of the structure (for checking before use). 
+	 * 
+	 * 0 - not initialized
+	 * 1 - initialized
+	 * -1 - ready for destroying
+	 */
 	int initialized;
 } usbhid_kbd_t;
@@ -108,4 +113,8 @@
 
 int usbhid_kbd_try_add_device(ddf_dev_t *dev);
+
+int usbhid_kbd_is_usable(const usbhid_kbd_t *kbd_dev);
+
+void usbhid_kbd_free(usbhid_kbd_t **kbd_dev);
 
 void usbhid_kbd_push_ev(usbhid_kbd_t *kbd_dev, int type, unsigned int key);
Index: uspace/drv/usbhid/kbdrepeat.c
===================================================================
--- uspace/drv/usbhid/kbdrepeat.c	(revision a763eb4d5e9d22c780e468eaa52dfda2c2e80ed4)
+++ uspace/drv/usbhid/kbdrepeat.c	(revision 103cf26a44475a0b5eab1330fbc1d8306d448745)
@@ -77,4 +77,11 @@
 
 	while (true) {
+		// check if the kbd structure is usable
+		if (!usbhid_kbd_is_usable(kbd)) {
+			usbhid_kbd_free(&kbd);
+			assert(kbd == NULL);
+			return;
+		}
+		
 		fibril_mutex_lock(kbd->repeat_mtx);
 
