Index: uspace/drv/usbhid/hidreq.c
===================================================================
--- uspace/drv/usbhid/hidreq.c	(revision 62f42128db41689201e2d22635ff36cbfb822e94)
+++ uspace/drv/usbhid/hidreq.c	(revision f8e4cb62ab74e6b5a3272ed17535d0e8f98fae57)
@@ -41,7 +41,7 @@
 #include <usb/debug.h>
 #include <usb/request.h>
+#include <usb/pipes.h>
 
 #include "hidreq.h"
-#include "hiddev.h"
 
 /*----------------------------------------------------------------------------*/
@@ -60,21 +60,26 @@
  *         usb_control_request_set().
  */
-int usbhid_req_set_report(usbhid_dev_t *hid_dev,
+int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
     usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size)
 {
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_report(): no HID device structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
 	if (sess_rc != EOK) {
 		usb_log_warning("Failed to start a session: %s.\n",
@@ -88,9 +93,9 @@
 	usb_log_debug("Sending Set_Report request to the device.\n");
 	
-	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_REPORT, value, hid_dev->iface, buffer, buf_size);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_REPORT, value, iface_no, buffer, buf_size);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
 
 	if (rc != EOK) {
@@ -122,20 +127,26 @@
  *         usb_control_request_set().
  */
-int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_protocol(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
+int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no,
+    usb_hid_protocol_t protocol)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
 	if (sess_rc != EOK) {
 		usb_log_warning("Failed to start a session: %s.\n",
@@ -145,11 +156,11 @@
 
 	usb_log_debug("Sending Set_Protocol request to the device ("
-	    "protocol: %d, iface: %d).\n", protocol, hid_dev->iface);
-	
-	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_PROTOCOL, protocol, hid_dev->iface, NULL, 0);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
+	    "protocol: %d, iface: %d).\n", protocol, iface_no);
+	
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_PROTOCOL, protocol, iface_no, NULL, 0);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
 
 	if (rc != EOK) {
@@ -182,20 +193,25 @@
  *         usb_control_request_set().
  */
-int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_idle(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
+int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
 	if (sess_rc != EOK) {
 		usb_log_warning("Failed to start a session: %s.\n",
@@ -205,13 +221,13 @@
 
 	usb_log_debug("Sending Set_Idle request to the device ("
-	    "duration: %u, iface: %d).\n", duration, hid_dev->iface);
+	    "duration: %u, iface: %d).\n", duration, iface_no);
 	
 	uint16_t value = duration << 8;
 	
-	rc = usb_control_request_set(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_SET_IDLE, value, hid_dev->iface, NULL, 0);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
+	rc = usb_control_request_set(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_SET_IDLE, value, iface_no, NULL, 0);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
 
 	if (rc != EOK) {
@@ -247,21 +263,27 @@
  *         usb_control_request_set().
  */
-int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 
-    uint8_t *buffer, size_t buf_size, size_t *actual_size)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_report(): no HID device structure"
-		    " given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
+int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
+    size_t *actual_size)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
 	if (sess_rc != EOK) {
 		usb_log_warning("Failed to start a session: %s.\n",
@@ -275,10 +297,10 @@
 	usb_log_debug("Sending Get_Report request to the device.\n");
 	
-	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_GET_REPORT, value, hid_dev->iface, buffer, buf_size,
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_REPORT, value, iface_no, buffer, buf_size,
 	    actual_size);
 
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
 
 	if (rc != EOK) {
@@ -310,20 +332,26 @@
  *         usb_control_request_set().
  */
-int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_protocol(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
+int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t *protocol)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
 	if (sess_rc != EOK) {
 		usb_log_warning("Failed to start a session: %s.\n",
@@ -333,14 +361,14 @@
 
 	usb_log_debug("Sending Get_Protocol request to the device ("
-	    "iface: %d).\n", hid_dev->iface);
+	    "iface: %d).\n", iface_no);
 	
 	uint8_t buffer[1];
 	size_t actual_size = 0;
 	
-	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_GET_PROTOCOL, 0, hid_dev->iface, buffer, 1, &actual_size);
-
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_PROTOCOL, 0, iface_no, buffer, 1, &actual_size);
+
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
 
 	if (rc != EOK) {
@@ -381,20 +409,25 @@
  *         usb_control_request_set().
  */
-int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration)
-{
-	if (hid_dev == NULL) {
-		usb_log_error("usbhid_req_set_idle(): no HID device "
-		    "structure given.\n");
-		return EINVAL;
-	}
-	
-	/*
-	 * No need for checking other parameters, as they are checked in
-	 * the called function (usb_control_request_set()).
-	 */
-	
-	int rc, sess_rc;
-	
-	sess_rc = usb_pipe_start_session(&hid_dev->ctrl_pipe);
+int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration)
+{
+	if (ctrl_pipe == NULL) {
+		usb_log_warning("usbhid_req_set_report(): no pipe given.\n");
+		return EINVAL;
+	}
+	
+	if (iface_no < 0) {
+		usb_log_warning("usbhid_req_set_report(): no interface given."
+		    "\n");
+		return EINVAL;
+	}
+	
+	/*
+	 * No need for checking other parameters, as they are checked in
+	 * the called function (usb_control_request_set()).
+	 */
+	
+	int rc, sess_rc;
+	
+	sess_rc = usb_pipe_start_session(ctrl_pipe);
 	if (sess_rc != EOK) {
 		usb_log_warning("Failed to start a session: %s.\n",
@@ -404,5 +437,5 @@
 
 	usb_log_debug("Sending Get_Idle request to the device ("
-	    "iface: %d).\n", hid_dev->iface);
+	    "iface: %d).\n", iface_no);
 	
 	uint16_t value = 0;
@@ -410,10 +443,10 @@
 	size_t actual_size = 0;
 	
-	rc = usb_control_request_get(&hid_dev->ctrl_pipe, 
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
-	    USB_HIDREQ_GET_IDLE, value, hid_dev->iface, buffer, 1, 
+	rc = usb_control_request_get(ctrl_pipe, 
+	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE, 
+	    USB_HIDREQ_GET_IDLE, value, iface_no, buffer, 1, 
 	    &actual_size);
 
-	sess_rc = usb_pipe_end_session(&hid_dev->ctrl_pipe);
+	sess_rc = usb_pipe_end_session(ctrl_pipe);
 
 	if (rc != EOK) {
Index: uspace/drv/usbhid/hidreq.h
===================================================================
--- uspace/drv/usbhid/hidreq.h	(revision 62f42128db41689201e2d22635ff36cbfb822e94)
+++ uspace/drv/usbhid/hidreq.h	(revision f8e4cb62ab74e6b5a3272ed17535d0e8f98fae57)
@@ -40,4 +40,5 @@
 
 #include <usb/classes/hid.h>
+#include <usb/pipes.h>
 
 #include "hiddev.h"
@@ -45,17 +46,20 @@
 /*----------------------------------------------------------------------------*/
 
-int usbhid_req_set_report(usbhid_dev_t *hid_dev,
+int usbhid_req_set_report(usb_pipe_t *ctrl_pipe, int iface_no,
     usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size);
 
-int usbhid_req_set_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t protocol);
+int usbhid_req_set_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t protocol);
 
-int usbhid_req_set_idle(usbhid_dev_t *hid_dev, uint8_t duration);
+int usbhid_req_set_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t duration);
 
-int usbhid_req_get_report(usbhid_dev_t *hid_dev, usb_hid_report_type_t type, 
-    uint8_t *buffer, size_t buf_size, size_t *actual_size);
+int usbhid_req_get_report(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_report_type_t type, uint8_t *buffer, size_t buf_size, 
+    size_t *actual_size);
 
-int usbhid_req_get_protocol(usbhid_dev_t *hid_dev, usb_hid_protocol_t *protocol);
+int usbhid_req_get_protocol(usb_pipe_t *ctrl_pipe, int iface_no, 
+    usb_hid_protocol_t *protocol);
 
-int usbhid_req_get_idle(usbhid_dev_t *hid_dev, uint8_t *duration);
+int usbhid_req_get_idle(usb_pipe_t *ctrl_pipe, int iface_no, uint8_t *duration);
 
 /*----------------------------------------------------------------------------*/
Index: uspace/drv/usbhid/kbddev.c
===================================================================
--- uspace/drv/usbhid/kbddev.c	(revision 62f42128db41689201e2d22635ff36cbfb822e94)
+++ uspace/drv/usbhid/kbddev.c	(revision f8e4cb62ab74e6b5a3272ed17535d0e8f98fae57)
@@ -46,4 +46,6 @@
 
 #include <usb/usb.h>
+#include <usb/dp.h>
+#include <usb/request.h>
 #include <usb/classes/hid.h>
 #include <usb/pipes.h>
@@ -53,4 +55,6 @@
 #include <usb/classes/hidut.h>
 
+#include <usb/devdrv.h>
+
 #include "kbddev.h"
 #include "hiddev.h"
@@ -86,5 +90,5 @@
 
 /** Keyboard polling endpoint description for boot protocol class. */
-static usb_endpoint_description_t poll_endpoint_description = {
+static usb_endpoint_description_t boot_poll_endpoint_description = {
 	.transfer_type = USB_TRANSFER_INTERRUPT,
 	.direction = USB_DIRECTION_IN,
@@ -94,4 +98,21 @@
 	.flags = 0
 };
+
+/** General keyboard polling endpoint description. */
+//static usb_endpoint_description_t general_poll_endpoint_description = {
+//	.transfer_type = USB_TRANSFER_INTERRUPT,
+//	.direction = USB_DIRECTION_IN,
+//	.interface_class = USB_CLASS_HID,
+//	.flags = 0
+//};
+
+/* Array of endpoints expected on the device, NULL terminated. */
+usb_endpoint_description_t 
+    *usbhid_kbd_endpoints[USBHID_KBD_POLL_EP_COUNT + 1] = {
+	&boot_poll_endpoint_description,
+//	&general_poll_endpoint_description,
+	NULL
+};
+
 
 typedef enum usbhid_kbd_flags {
@@ -149,5 +170,5 @@
 
 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
-static ddf_dev_ops_t keyboard_ops = {
+ddf_dev_ops_t keyboard_ops = {
 	.default_handler = default_connection_handler
 };
@@ -237,7 +258,8 @@
 	    usb_debug_str_buffer(buffer, BOOTP_BUFFER_OUT_SIZE, 0));
 	
-	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
-	usbhid_req_set_report(kbd_dev->hid_dev, USB_HID_REPORT_TYPE_OUTPUT, 
+	assert(kbd_dev->usb_dev != NULL);
+	
+	usbhid_req_set_report(&kbd_dev->usb_dev->ctrl_pipe, 
+	    kbd_dev->usb_dev->interface_no, USB_HID_REPORT_TYPE_OUTPUT, 
 	    buffer, BOOTP_BUFFER_OUT_SIZE);
 }
@@ -370,5 +392,5 @@
 //{
 //	/*
-//	 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
+//	 *  why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
 //	 *       both as modifiers and as keyUSB_HID_LOCK_COUNTs with their own scancodes???
 //	 *
@@ -434,5 +456,5 @@
 	 * First of all, check if the kbd have reported phantom state.
 	 *
-	 * TODO: this must be changed as we don't know which keys are modifiers
+	 *  this must be changed as we don't know which keys are modifiers
 	 *       and which are regular keys.
 	 */
@@ -566,5 +588,6 @@
  * @param actual_size Size of the data from keyboard (report size) in bytes.
  *
- * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report().
+ * @sa usbhid_kbd_process_keycodes(), usb_hid_boot_keyboard_input_report(),
+ *     usb_hid_parse_report().
  */
 static void usbhid_kbd_process_data(usbhid_kbd_t *kbd_dev,
@@ -572,5 +595,5 @@
 {
 	assert(kbd_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
-	assert(kbd_dev->hid_dev->parser != NULL);
+	assert(kbd_dev->parser != NULL);
 	
 	usb_hid_report_in_callbacks_t *callbacks =
@@ -585,5 +608,5 @@
 //	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
 //	    callbacks, kbd_dev);
-	int rc = usb_hid_parse_report(kbd_dev->hid_dev->parser, buffer,
+	int rc = usb_hid_parse_report(kbd_dev->parser, buffer,
 	    actual_size, callbacks, kbd_dev);
 	
@@ -597,4 +620,292 @@
 /* HID/KBD structure manipulation                                             */
 /*----------------------------------------------------------------------------*/
+
+static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)
+{
+	kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;
+}
+
+/*----------------------------------------------------------------------------*/
+/* HID/KBD polling                                                            */
+/*----------------------------------------------------------------------------*/
+/**
+ * Main keyboard polling function.
+ *
+ * This function uses the Interrupt In pipe of the keyboard to poll for events.
+ * The keyboard is initialized in a way that it reports only when a key is 
+ * pressed or released, so there is no actual need for any sleeping between
+ * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
+ *
+ * @param kbd_dev Initialized keyboard structure representing the device to 
+ *                poll.
+ *
+ * @sa usbhid_kbd_process_data()
+ */
+//static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
+//{
+//	int rc, sess_rc;
+//	uint8_t buffer[BOOTP_BUFFER_SIZE];
+//	size_t actual_size;
+	
+//	usb_log_debug("Polling keyboard...\n");
+	
+//	if (!kbd_dev->initialized) {
+//		usb_log_error("HID/KBD device not initialized!\n");
+//		return;
+//	}
+	
+//	assert(kbd_dev->hid_dev != NULL);
+//	assert(kbd_dev->hid_dev->initialized);
+
+//	while (true) {
+//		sess_rc = usb_pipe_start_session(
+//		    &kbd_dev->hid_dev->poll_pipe);
+//		if (sess_rc != EOK) {
+//			usb_log_warning("Failed to start a session: %s.\n",
+//			    str_error(sess_rc));
+//			break;
+//		}
+
+//		rc = usb_pipe_read(&kbd_dev->hid_dev->poll_pipe, 
+//		    buffer, BOOTP_BUFFER_SIZE, &actual_size);
+		
+//		sess_rc = usb_pipe_end_session(
+//		    &kbd_dev->hid_dev->poll_pipe);
+
+//		if (rc != EOK) {
+//			usb_log_warning("Error polling the keyboard: %s.\n",
+//			    str_error(rc));
+//			break;
+//		}
+
+//		if (sess_rc != EOK) {
+//			usb_log_warning("Error closing session: %s.\n",
+//			    str_error(sess_rc));
+//			break;
+//		}
+
+//		/*
+//		 * If the keyboard answered with NAK, it returned no data.
+//		 * This implies that no change happened since last query.
+//		 */
+//		if (actual_size == 0) {
+//			usb_log_debug("Keyboard returned NAK\n");
+//			continue;
+//		}
+
+//		/*
+//		 * TODO: Process pressed keys.
+//		 */
+//		usb_log_debug("Calling usbhid_kbd_process_data()\n");
+//		usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
+		
+//		// disabled for now, no reason to sleep
+//		//async_usleep(kbd_dev->hid_dev->poll_interval);
+//	}
+//}
+
+/*----------------------------------------------------------------------------*/
+/**
+ * Function executed by the main driver fibril.
+ *
+ * Just starts polling the keyboard for events.
+ * 
+ * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 
+ *            representing the device.
+ *
+ * @retval EOK if the fibril finished polling the device.
+ * @retval EINVAL if no device was given in the argument.
+ *
+ * @sa usbhid_kbd_poll()
+ *
+ * @todo Change return value - only case when the fibril finishes is in case
+ *       of some error, so the error should probably be propagated from function
+ *       usbhid_kbd_poll() to here and up.
+ */
+//static int usbhid_kbd_fibril(void *arg)
+//{
+//	if (arg == NULL) {
+//		usb_log_error("No device!\n");
+//		return EINVAL;
+//	}
+	
+//	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
+
+//	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);
+
+//	return EOK;
+//}
+
+static int usbhid_dev_get_report_descriptor(usbhid_kbd_t *kbd_dev)
+{
+	assert(kbd_dev != NULL);
+	assert(kbd_dev->usb_dev != NULL);
+	assert(kbd_dev->usb_dev->interface_no >= 0);
+	
+	usb_dp_parser_t parser =  {
+		.nesting = usb_dp_standard_descriptor_nesting
+	};
+	
+	usb_dp_parser_data_t parser_data = {
+		.data = kbd_dev->usb_dev->descriptors.configuration,
+		.size = kbd_dev->usb_dev->descriptors.configuration_size,
+		.arg = NULL
+	};
+	
+	/*
+	 * First nested descriptor of the configuration descriptor.
+	 */
+	uint8_t *d = 
+	    usb_dp_get_nested_descriptor(&parser, &parser_data, 
+	    kbd_dev->usb_dev->descriptors.configuration);
+	
+	/*
+	 * Find the interface descriptor corresponding to our interface number.
+	 */
+	int i = 0;
+	while (d != NULL && i < kbd_dev->usb_dev->interface_no) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    kbd_dev->usb_dev->descriptors.configuration, d);
+	}
+	
+	if (d == NULL) {
+		usb_log_fatal("The %. interface descriptor not found!\n",
+		    kbd_dev->usb_dev->interface_no);
+		return ENOENT;
+	}
+	
+	/*
+	 * First nested descriptor of the interface descriptor.
+	 */
+	uint8_t *iface_desc = d;
+	d = usb_dp_get_nested_descriptor(&parser, &parser_data, iface_desc);
+	
+	/*
+	 * Search through siblings until the HID descriptor is found.
+	 */
+	while (d != NULL && *(d + 1) != USB_DESCTYPE_HID) {
+		d = usb_dp_get_sibling_descriptor(&parser, &parser_data, 
+		    iface_desc, d);
+	}
+	
+	if (d == NULL) {
+		usb_log_fatal("No HID descriptor found!\n");
+		return ENOENT;
+	}
+	
+	if (*d != sizeof(usb_standard_hid_descriptor_t)) {
+		usb_log_fatal("HID descriptor hass wrong size (%u, expected %u"
+		    ")\n", *d, sizeof(usb_standard_hid_descriptor_t));
+		return EINVAL;
+	}
+	
+	usb_standard_hid_descriptor_t *hid_desc = 
+	    (usb_standard_hid_descriptor_t *)d;
+	
+	uint16_t length =  hid_desc->report_desc_info.length;
+	size_t actual_size = 0;
+	
+	/*
+	 * Start session for the control transfer.
+	 */
+	int sess_rc = usb_pipe_start_session(&kbd_dev->usb_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to start a session: %s.\n",
+		    str_error(sess_rc));
+		return sess_rc;
+	}
+
+	/*
+	 * Allocate space for the report descriptor.
+	 */
+	kbd_dev->report_desc = (uint8_t *)malloc(length);
+	if (kbd_dev->report_desc == NULL) {
+		usb_log_fatal("Failed to allocate space for Report descriptor."
+		    "\n");
+		return ENOMEM;
+	}
+	
+	usb_log_debug("Getting Report descriptor, expected size: %u\n", length);
+	
+	/*
+	 * Get the descriptor from the device.
+	 */
+	int rc = usb_request_get_descriptor(&kbd_dev->usb_dev->ctrl_pipe,
+	    USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
+	    USB_DESCTYPE_HID_REPORT, 0, kbd_dev->usb_dev->interface_no,
+	    kbd_dev->report_desc, length, &actual_size);
+
+	if (rc != EOK) {
+		free(kbd_dev->report_desc);
+		kbd_dev->report_desc = NULL;
+		return rc;
+	}
+
+	if (actual_size != length) {
+		free(kbd_dev->report_desc);
+		kbd_dev->report_desc = NULL;
+		usb_log_fatal("Report descriptor has wrong size (%u, expected "
+		    "%u)\n", actual_size, length);
+		return EINVAL;
+	}
+	
+	/*
+	 * End session for the control transfer.
+	 */
+	sess_rc = usb_pipe_end_session(&kbd_dev->usb_dev->ctrl_pipe);
+	if (sess_rc != EOK) {
+		usb_log_warning("Failed to end a session: %s.\n",
+		    str_error(sess_rc));
+		free(kbd_dev->report_desc);
+		kbd_dev->report_desc = NULL;
+		return sess_rc;
+	}
+	
+	kbd_dev->report_desc_size = length;
+	
+	usb_log_debug("Done.\n");
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int usbhid_kbd_process_report_descriptor(usbhid_kbd_t *kbd_dev)
+{
+	int rc = usbhid_dev_get_report_descriptor(kbd_dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Problem with getting Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	rc = usb_hid_parse_report_descriptor(kbd_dev->parser, 
+	    kbd_dev->report_desc, kbd_dev->report_desc_size);
+	if (rc != EOK) {
+		usb_log_warning("Problem parsing Report descriptor: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+	
+	usb_hid_descriptor_print(kbd_dev->parser);
+	
+	/*
+	 * TODO: if failed, try to parse the boot report descriptor.
+	 */
+	
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+/* API functions                                                              */
+/*----------------------------------------------------------------------------*/
 /**
  * Creates a new USB/HID keyboard structure.
@@ -606,5 +917,5 @@
  *         NULL if not successful (memory error).
  */
-static usbhid_kbd_t *usbhid_kbd_new(void)
+usbhid_kbd_t *usbhid_kbd_new(void)
 {
 	usbhid_kbd_t *kbd_dev = 
@@ -618,21 +929,8 @@
 	memset(kbd_dev, 0, sizeof(usbhid_kbd_t));
 	
-	kbd_dev->hid_dev = usbhid_dev_new();
-	if (kbd_dev->hid_dev == NULL) {
-		usb_log_fatal("Could not create HID device structure.\n");
-		return NULL;
-	}
-	
 	kbd_dev->console_phone = -1;
 	kbd_dev->initialized = USBHID_KBD_STATUS_UNINITIALIZED;
 	
 	return kbd_dev;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void usbhid_kbd_mark_unusable(usbhid_kbd_t *kbd_dev)
-{
-	kbd_dev->initialized = USBHID_KBD_STATUS_TO_DESTROY;
 }
 
@@ -658,5 +956,5 @@
  * @return Other value inherited from function usbhid_dev_init().
  */
-static int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, ddf_dev_t *dev)
+int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, usb_device_t *dev)
 {
 	int rc;
@@ -671,5 +969,5 @@
 	
 	if (dev == NULL) {
-		usb_log_error("Failed to init keyboard structure: no device"
+		usb_log_error("Failed to init keyboard structure: no USB device"
 		    " given.\n");
 		return EINVAL;
@@ -681,21 +979,35 @@
 	}
 	
-	rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize HID device structure: %s\n",
-		   str_error(rc));
-		return rc;
-	}
-	
-	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
+	//rc = usbhid_dev_init(kbd_dev->hid_dev, dev, &poll_endpoint_description);
+	
+	
+//	if (rc != EOK) {
+//		usb_log_error("Failed to initialize HID device structure: %s\n",
+//		   str_error(rc));
+//		return rc;
+//	}
+	
+//	assert(kbd_dev->hid_dev->initialized == USBHID_KBD_STATUS_INITIALIZED);
 	
 	// save the size of the report (boot protocol report by default)
 //	kbd_dev->key_count = BOOTP_REPORT_SIZE;
 	
+	/* The USB device should already be initialized, save it in structure */
+	kbd_dev->usb_dev = dev;
+	
+	/* Get the report descriptor and initialize report parser. */
+	rc = usbhid_kbd_process_report_descriptor(kbd_dev);
+	if (rc != EOK) {
+		usb_log_warning("Could not process report descriptor.\n");
+		return rc;
+	}
+	
+	/*
+	 * TODO: make more general
+	 */
 	usb_hid_report_path_t path;
 	path.usage_page = USB_HIDUT_PAGE_KEYBOARD;
 	kbd_dev->key_count = usb_hid_report_input_length(
-	    kbd_dev->hid_dev->parser, &path);
+	    kbd_dev->parser, &path);
 	
 	usb_log_debug("Size of the input report: %zu\n", kbd_dev->key_count);
@@ -733,11 +1045,12 @@
 	 * Set Idle rate
 	 */
-	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized);
+	//assert(kbd_dev->hid_dev != NULL);
+	//assert(kbd_dev->hid_dev->initialized);
 	//usbhid_req_set_protocol(kbd_dev->hid_dev, USB_HID_PROTOCOL_BOOT);
 	
 	usbhid_kbd_set_led(kbd_dev);
 	
-	usbhid_req_set_idle(kbd_dev->hid_dev, IDLE_RATE);
+	usbhid_req_set_idle(&kbd_dev->usb_dev->ctrl_pipe, 
+	    kbd_dev->usb_dev->interface_no, IDLE_RATE);
 	
 	kbd_dev->initialized = USBHID_KBD_STATUS_INITIALIZED;
@@ -748,239 +1061,33 @@
 
 /*----------------------------------------------------------------------------*/
-/* HID/KBD polling                                                            */
-/*----------------------------------------------------------------------------*/
-/**
- * Main keyboard polling function.
- *
- * This function uses the Interrupt In pipe of the keyboard to poll for events.
- * The keyboard is initialized in a way that it reports only when a key is 
- * pressed or released, so there is no actual need for any sleeping between
- * polls (see usbhid_kbd_try_add_device() or usbhid_kbd_init()).
- *
- * @param kbd_dev Initialized keyboard structure representing the device to 
- *                poll.
- *
- * @sa usbhid_kbd_process_data()
- */
-static void usbhid_kbd_poll(usbhid_kbd_t *kbd_dev)
-{
-	int rc, sess_rc;
-	uint8_t buffer[BOOTP_BUFFER_SIZE];
-	size_t actual_size;
-	
-	usb_log_debug("Polling keyboard...\n");
-	
-	if (!kbd_dev->initialized) {
-		usb_log_error("HID/KBD device not initialized!\n");
+
+bool usbhid_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
+     size_t buffer_size, void *arg)
+{
+	if (dev == NULL || buffer == NULL || arg == NULL) {
+		// do not continue polling (???)
+		return false;
+	}
+	
+	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
+	
+	// TODO: add return value from this function
+	usbhid_kbd_process_data(kbd_dev, buffer, buffer_size);
+	
+	return true;
+}
+
+/*----------------------------------------------------------------------------*/
+
+void usbhid_kbd_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg)
+{
+	if (dev == NULL || arg == NULL) {
 		return;
 	}
 	
-	assert(kbd_dev->hid_dev != NULL);
-	assert(kbd_dev->hid_dev->initialized);
-
-	while (true) {
-		sess_rc = usb_pipe_start_session(
-		    &kbd_dev->hid_dev->poll_pipe);
-		if (sess_rc != EOK) {
-			usb_log_warning("Failed to start a session: %s.\n",
-			    str_error(sess_rc));
-			break;
-		}
-
-		rc = usb_pipe_read(&kbd_dev->hid_dev->poll_pipe, 
-		    buffer, BOOTP_BUFFER_SIZE, &actual_size);
-		
-		sess_rc = usb_pipe_end_session(
-		    &kbd_dev->hid_dev->poll_pipe);
-
-		if (rc != EOK) {
-			usb_log_warning("Error polling the keyboard: %s.\n",
-			    str_error(rc));
-			break;
-		}
-
-		if (sess_rc != EOK) {
-			usb_log_warning("Error closing session: %s.\n",
-			    str_error(sess_rc));
-			break;
-		}
-
-		/*
-		 * If the keyboard answered with NAK, it returned no data.
-		 * This implies that no change happened since last query.
-		 */
-		if (actual_size == 0) {
-			usb_log_debug("Keyboard returned NAK\n");
-			continue;
-		}
-
-		/*
-		 * TODO: Process pressed keys.
-		 */
-		usb_log_debug("Calling usbhid_kbd_process_data()\n");
-		usbhid_kbd_process_data(kbd_dev, buffer, actual_size);
-		
-		// disabled for now, no reason to sleep
-		//async_usleep(kbd_dev->hid_dev->poll_interval);
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Function executed by the main driver fibril.
- *
- * Just starts polling the keyboard for events.
- * 
- * @param arg Initialized keyboard device structure (of type usbhid_kbd_t) 
- *            representing the device.
- *
- * @retval EOK if the fibril finished polling the device.
- * @retval EINVAL if no device was given in the argument.
- *
- * @sa usbhid_kbd_poll()
- *
- * @todo Change return value - only case when the fibril finishes is in case
- *       of some error, so the error should probably be propagated from function
- *       usbhid_kbd_poll() to here and up.
- */
-static int usbhid_kbd_fibril(void *arg)
-{
-	if (arg == NULL) {
-		usb_log_error("No device!\n");
-		return EINVAL;
-	}
-	
-	usbhid_kbd_t *kbd_dev = (usbhid_kbd_t *)arg;
-
-	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);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/* API functions                                                              */
-/*----------------------------------------------------------------------------*/
-/**
- * Function for adding a new device of type USB/HID/keyboard.
- *
- * This functions initializes required structures from the device's descriptors
- * and starts new fibril for polling the keyboard for events and another one for
- * handling auto-repeat of keys.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- * @note Currently supports only boot-protocol keyboards.
- *
- * @param dev Device to add.
- *
- * @retval EOK if successful.
- * @retval ENOMEM if there
- * @return Other error code inherited from one of functions usbhid_kbd_init(),
- *         ddf_fun_bind() and ddf_fun_add_to_class().
- *
- * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
- */
-int usbhid_kbd_try_add_device(ddf_dev_t *dev)
-{
-	/*
-	 * Create default function.
-	 */
-	ddf_fun_t *kbd_fun = ddf_fun_create(dev, fun_exposed, "keyboard");
-	if (kbd_fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/* 
-	 * Initialize device (get and process descriptors, get address, etc.)
-	 */
-	usb_log_debug("Initializing USB/HID KBD device...\n");
-	
-	usbhid_kbd_t *kbd_dev = usbhid_kbd_new();
-	if (kbd_dev == NULL) {
-		usb_log_error("Error while creating USB/HID KBD device "
-		    "structure.\n");
-		ddf_fun_destroy(kbd_fun);
-		return ENOMEM;  // TODO: some other code??
-	}
-	
-	int rc = usbhid_kbd_init(kbd_dev, dev);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize USB/HID KBD device.\n");
-		ddf_fun_destroy(kbd_fun);
-		usbhid_kbd_free(&kbd_dev);
-		return rc;
-	}	
-	
-	usb_log_debug("USB/HID KBD device structure initialized.\n");
-	
-	/*
-	 * Store the initialized keyboard device and keyboard ops
-	 * to the DDF function.
-	 */
-	kbd_fun->driver_data = kbd_dev;
-	kbd_fun->ops = &keyboard_ops;
-
-	rc = ddf_fun_bind(kbd_fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(kbd_fun);
-		usbhid_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class 'keyboard': %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(kbd_fun);
-		usbhid_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	/*
-	 * Create new fibril for handling this keyboard
-	 */
-	fid_t fid = fibril_create(usbhid_kbd_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for `%s' device.\n",
-		    dev->name);
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-	
-	/*
-	 * Create new fibril for auto-repeat
-	 */
-	fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for KBD auto-repeat");
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-
-	(void)keyboard_ops;
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
+	usbhid_kbd_t *kbd = (usbhid_kbd_t *)arg;
+	
+	usbhid_kbd_mark_unusable(kbd);
 }
 
@@ -1014,8 +1121,8 @@
 	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)->hid_dev != NULL) {
+//		usbhid_dev_free(&(*kbd_dev)->hid_dev);
+//		assert((*kbd_dev)->hid_dev == NULL);
+//	}
 	
 	if ((*kbd_dev)->repeat_mtx != NULL) {
@@ -1024,4 +1131,6 @@
 		free((*kbd_dev)->repeat_mtx);
 	}
+	
+	/* TODO: what about the USB device structure?? */
 
 	free(*kbd_dev);
Index: uspace/drv/usbhid/kbddev.h
===================================================================
--- uspace/drv/usbhid/kbddev.h	(revision 62f42128db41689201e2d22635ff36cbfb822e94)
+++ uspace/drv/usbhid/kbddev.h	(revision f8e4cb62ab74e6b5a3272ed17535d0e8f98fae57)
@@ -46,5 +46,7 @@
 #include <usb/pipes.h>
 
-#include "hiddev.h"
+#include <usb/devdrv.h>
+
+//#include "hiddev.h"
 
 /*----------------------------------------------------------------------------*/
@@ -75,7 +77,8 @@
  *       being device-specific.
  */
-typedef struct {
-	/** Structure holding generic USB/HID device information. */
-	usbhid_dev_t *hid_dev;
+typedef struct usbhid_kbd_t {
+	/** Structure holding generic USB device information. */
+	//usbhid_dev_t *hid_dev;
+	usb_device_t *usb_dev;
 	
 	/** Currently pressed keys (not translated to key codes). */
@@ -101,4 +104,13 @@
 	fibril_mutex_t *repeat_mtx;
 	
+	/** Report descriptor. */
+	uint8_t *report_desc;
+
+	/** Report descriptor size. */
+	size_t report_desc_size;
+
+	/** HID Report parser. */
+	usb_hid_report_parser_t *parser;
+	
 	/** State of the structure (for checking before use). 
 	 * 
@@ -112,5 +124,24 @@
 /*----------------------------------------------------------------------------*/
 
-int usbhid_kbd_try_add_device(ddf_dev_t *dev);
+enum {
+	USBHID_KBD_POLL_EP_NO = 0,
+	USBHID_KBD_POLL_EP_COUNT = 1
+};
+
+usb_endpoint_description_t *usbhid_kbd_endpoints[USBHID_KBD_POLL_EP_COUNT + 1];
+
+ddf_dev_ops_t keyboard_ops;
+
+/*----------------------------------------------------------------------------*/
+
+usbhid_kbd_t *usbhid_kbd_new(void);
+
+int usbhid_kbd_init(usbhid_kbd_t *kbd_dev, usb_device_t *dev);
+
+bool usbhid_kbd_polling_callback(usb_device_t *dev, uint8_t *buffer,
+     size_t buffer_size, void *arg);
+
+void usbhid_kbd_polling_ended_callback(usb_device_t *dev, bool reason, 
+     void *arg);
 
 int usbhid_kbd_is_initialized(const usbhid_kbd_t *kbd_dev);
Index: uspace/drv/usbhid/kbdrepeat.h
===================================================================
--- uspace/drv/usbhid/kbdrepeat.h	(revision 62f42128db41689201e2d22635ff36cbfb822e94)
+++ uspace/drv/usbhid/kbdrepeat.h	(revision f8e4cb62ab74e6b5a3272ed17535d0e8f98fae57)
@@ -37,5 +37,7 @@
 #define USBHID_KBDREPEAT_H_
 
-#include "kbddev.h"
+struct usbhid_kbd_t;
+
+//#include "kbddev.h"
 
 /*----------------------------------------------------------------------------*/
@@ -43,7 +45,7 @@
 int usbhid_kbd_repeat_fibril(void *arg);
 
-void usbhid_kbd_repeat_start(usbhid_kbd_t *kbd, unsigned int key);
+void usbhid_kbd_repeat_start(struct usbhid_kbd_t *kbd, unsigned int key);
 
-void usbhid_kbd_repeat_stop(usbhid_kbd_t *kbd, unsigned int key);
+void usbhid_kbd_repeat_stop(struct usbhid_kbd_t *kbd, unsigned int key);
 
 #endif /* USBHID_KBDREPEAT_H_ */
Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision 62f42128db41689201e2d22635ff36cbfb822e94)
+++ uspace/drv/usbhid/main.c	(revision f8e4cb62ab74e6b5a3272ed17535d0e8f98fae57)
@@ -41,9 +41,146 @@
 #include <str_error.h>
 
+#include <usb/devdrv.h>
+
 #include "kbddev.h"
+#include "kbdrepeat.h"
 
 /*----------------------------------------------------------------------------*/
 
 #define NAME "usbhid"
+
+/**
+ * Function for adding a new device of type USB/HID/keyboard.
+ *
+ * This functions initializes required structures from the device's descriptors
+ * and starts new fibril for polling the keyboard for events and another one for
+ * handling auto-repeat of keys.
+ *
+ * During initialization, the keyboard is switched into boot protocol, the idle
+ * rate is set to 0 (infinity), resulting in the keyboard only reporting event
+ * when a key is pressed or released. Finally, the LED lights are turned on 
+ * according to the default setup of lock keys.
+ *
+ * @note By default, the keyboards is initialized with Num Lock turned on and 
+ *       other locks turned off.
+ * @note Currently supports only boot-protocol keyboards.
+ *
+ * @param dev Device to add.
+ *
+ * @retval EOK if successful.
+ * @retval ENOMEM if there
+ * @return Other error code inherited from one of functions usbhid_kbd_init(),
+ *         ddf_fun_bind() and ddf_fun_add_to_class().
+ *
+ * @sa usbhid_kbd_fibril(), usbhid_kbd_repeat_fibril()
+ */
+static int usbhid_try_add_device(usb_device_t *dev)
+{
+	/* Create the function exposed under /dev/devices. */
+	ddf_fun_t *kbd_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
+	    "keyboard");
+	if (kbd_fun == NULL) {
+		usb_log_error("Could not create DDF function node.\n");
+		return ENOMEM;
+	}
+	
+	/* 
+	 * Initialize device (get and process descriptors, get address, etc.)
+	 */
+	usb_log_debug("Initializing USB/HID KBD device...\n");
+	
+	usbhid_kbd_t *kbd_dev = usbhid_kbd_new();
+	if (kbd_dev == NULL) {
+		usb_log_error("Error while creating USB/HID KBD device "
+		    "structure.\n");
+		ddf_fun_destroy(kbd_fun);
+		return ENOMEM;  // TODO: some other code??
+	}
+	
+	int rc = usbhid_kbd_init(kbd_dev, dev);
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize USB/HID KBD device.\n");
+		ddf_fun_destroy(kbd_fun);
+		usbhid_kbd_free(&kbd_dev);
+		return rc;
+	}	
+	
+	usb_log_debug("USB/HID KBD device structure initialized.\n");
+	
+	/*
+	 * Store the initialized keyboard device and keyboard ops
+	 * to the DDF function.
+	 */
+	kbd_fun->driver_data = kbd_dev;
+	kbd_fun->ops = &keyboard_ops;
+
+	rc = ddf_fun_bind(kbd_fun);
+	if (rc != EOK) {
+		usb_log_error("Could not bind DDF function: %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usbhid_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
+	if (rc != EOK) {
+		usb_log_error(
+		    "Could not add DDF function to class 'keyboard': %s.\n",
+		    str_error(rc));
+		// TODO: Can / should I destroy the DDF function?
+		ddf_fun_destroy(kbd_fun);
+		usbhid_kbd_free(&kbd_dev);
+		return rc;
+	}
+	
+	/*
+	 * Create new fibril for handling this keyboard
+	 */
+	//fid_t fid = fibril_create(usbhid_kbd_fibril, kbd_dev);
+	
+	/* Start automated polling function.
+	 * This will create a separate fibril that will query the device
+	 * for the data continuously 
+	 */
+       rc = usb_device_auto_poll(dev,
+	   /* Index of the polling pipe. */
+	   USBHID_KBD_POLL_EP_NO,
+	   /* Callback when data arrives. */
+	   usbhid_kbd_polling_callback,
+	   /* How much data to request. */
+	   dev->pipes[USBHID_KBD_POLL_EP_NO].pipe->max_packet_size,
+	   /* Callback when the polling ends. */
+	   usbhid_kbd_polling_ended_callback,
+	   /* Custom argument. */
+	   kbd_dev);
+	
+	
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril for `%s'.\n",
+		    dev->ddf_dev->name);
+		return rc;
+	}
+	//fibril_add_ready(fid);
+	
+	/*
+	 * Create new fibril for auto-repeat
+	 */
+	fid_t fid = fibril_create(usbhid_kbd_repeat_fibril, kbd_dev);
+	if (fid == 0) {
+		usb_log_error("Failed to start fibril for KBD auto-repeat");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+
+	(void)keyboard_ops;
+
+	/*
+	 * Hurrah, device is initialized.
+	 */
+	return EOK;
+}
 
 /*----------------------------------------------------------------------------*/
@@ -58,9 +195,16 @@
  * @retval EREFUSED if the device is not supported.
  */
-static int usbhid_add_device(ddf_dev_t *dev)
+static int usbhid_add_device(usb_device_t *dev)
 {
 	usb_log_debug("usbhid_add_device()\n");
 	
-	int rc = usbhid_kbd_try_add_device(dev);
+	if (dev->interface_no < 0) {
+		usb_log_warning("Device is not a supported keyboard.\n");
+		usb_log_error("Failed to add HID device: endpoint not found."
+		    "\n");
+		return ENOTSUP;
+	}
+	
+	int rc = usbhid_try_add_device(dev);
 	
 	if (rc != EOK) {
@@ -71,5 +215,5 @@
 	}
 	
-	usb_log_info("Keyboard `%s' ready to use.\n", dev->name);
+	usb_log_info("Keyboard `%s' ready to use.\n", dev->ddf_dev->name);
 
 	return EOK;
@@ -78,14 +222,30 @@
 /*----------------------------------------------------------------------------*/
 
-static driver_ops_t kbd_driver_ops = {
-	.add_device = usbhid_add_device,
+/* Currently, the framework supports only device adding. Once the framework
+ * supports unplug, more callbacks will be added. */
+static usb_driver_ops_t usbhid_driver_ops = {
+        .add_device = usbhid_add_device,
 };
 
-/*----------------------------------------------------------------------------*/
-
-static driver_t kbd_driver = {
-	.name = NAME,
-	.driver_ops = &kbd_driver_ops
+
+/* The driver itself. */
+static usb_driver_t usbhid_driver = {
+        .name = NAME,
+        .ops = &usbhid_driver_ops,
+        .endpoints = usbhid_kbd_endpoints
 };
+
+/*----------------------------------------------------------------------------*/
+
+//static driver_ops_t kbd_driver_ops = {
+//	.add_device = usbhid_add_device,
+//};
+
+///*----------------------------------------------------------------------------*/
+
+//static driver_t kbd_driver = {
+//	.name = NAME,
+//	.driver_ops = &kbd_driver_ops
+//};
 
 /*----------------------------------------------------------------------------*/
@@ -95,7 +255,7 @@
 	printf(NAME ": HelenOS USB HID driver.\n");
 
-	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
-
-	return ddf_driver_main(&kbd_driver);
+	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
+
+	return usb_driver_main(&usbhid_driver);
 }
 
