Index: uspace/drv/usbhid/main.c
===================================================================
--- uspace/drv/usbhid/main.c	(revision eb1a2f485e907e821965b3aafca2d8a5355f3518)
+++ uspace/drv/usbhid/main.c	(revision 92574f413b9e9e99c9c0d1cf1c3a3b1bdf6ccbcb)
@@ -51,4 +51,5 @@
 #include <usb/descriptor.h>
 #include <io/console.h>
+#include <stdint.h>
 #include "hid.h"
 #include "descparser.h"
@@ -61,4 +62,5 @@
 
 #define GUESSED_POLL_ENDPOINT 1
+#define BOOTP_REPORT_SIZE 6
 
 /** Keyboard polling endpoint description for boot protocol class. */
@@ -207,7 +209,7 @@
 	}
 /*
-	printf("type: %d\n", type);
-	printf("mods: 0x%x\n", mods);
-	printf("keycode: %u\n", key);
+	usb_log_debug2("type: %d\n", type);
+	usb_log_debug2("mods: 0x%x\n", mods);
+	usb_log_debug2("keycode: %u\n", key);
 */
 	
@@ -239,7 +241,8 @@
 	ev.c = layout[active_layout]->parse_ev(&ev);
 
-	printf("Sending key %d to the console\n", ev.key);
+	usb_log_debug("Sending key %d to the console\n", ev.key);
 	assert(console_callback_phone != -1);
-	async_msg_4(console_callback_phone, KBD_EVENT, ev.type, ev.key, ev.mods, ev.c);
+	async_msg_4(console_callback_phone, KBD_EVENT, ev.type, ev.key, 
+	    ev.mods, ev.c);
 }
 /*
@@ -249,9 +252,99 @@
 	/*
 	 * TODO:
-	 * 1) key press / key release - how does the keyboard notify about release?
+	 * 1) key press / key release - how does the keyboard notify about 
+	 *    release?
 	 * 2) layouts (use the already defined), not important now
 	 * 3) 
 	 */
 
+static const keycode_t usb_hid_modifiers_boot_keycodes[5] = {
+	KC_NUM_LOCK,      /* USB_HID_MOD_BOOT_NUM_LOCK */
+	KC_CAPS_LOCK,     /* USB_HID_MOD_BOOT_CAPS_LOCK */
+	KC_SCROLL_LOCK,   /* USB_HID_MOD_BOOT_SCROLL_LOCK */
+	0,                /* USB_HID_MOD_BOOT_COMPOSE */
+	0                 /* USB_HID_MOD_BOOT_KANA */
+};
+
+static void usbkbd_check_modifier_changes(usb_hid_dev_kbd_t *kbd_dev,
+    uint8_t modifiers)
+{
+	/*
+	 * TODO: why the USB keyboard has NUM_, SCROLL_ and CAPS_LOCK
+	 *       both as modifiers and as keys with their own scancodes???
+	 *
+	 * modifiers should be sent as normal keys to usbkbd_parse_scancode()!!
+	 * so maybe it would be better if I received it from report parser in 
+	 * that way
+	 */
+	
+	int i;
+	for (i = 0; i < USB_HID_MOD_BOOT_COUNT; ++i) {
+		if ((modifiers & usb_hid_modifiers_boot_consts[i]) &&
+		    !(kbd_dev->modifiers & usb_hid_modifiers_boot_consts[i])) {
+			// modifier pressed
+			if (usb_hid_modifiers_boot_keycodes[i] != 0) {
+				kbd_push_ev(KEY_PRESS, 
+				    usb_hid_modifiers_boot_keycodes[i]);
+			}
+		} else if (!(modifiers & usb_hid_modifiers_boot_consts[i]) &&
+		    (kbd_dev->modifiers & usb_hid_modifiers_boot_consts[i])) {
+			// modifier released
+			if (usb_hid_modifiers_boot_keycodes[i] != 0) {
+				kbd_push_ev(KEY_RELEASE, 
+				    usb_hid_modifiers_boot_keycodes[i]);
+			}
+		}	// no change
+	}
+}
+
+static void usbkbd_check_key_changes(usb_hid_dev_kbd_t *kbd_dev, 
+    const uint8_t *key_codes)
+{
+	// TODO: phantom state!!
+	
+	unsigned int key;
+	unsigned int i, j;
+	
+	// TODO: quite dummy right now, think of better implementation
+	
+	// key releases
+	for (j = 0; j < kbd_dev->keycode_count; ++j) {
+		// try to find the old key in the new key list
+		i = 0;
+		while (i < kbd_dev->keycode_count
+		    && key_codes[i] != kbd_dev->keycodes[j]) {
+			++j;
+		}
+		
+		if (j == kbd_dev->keycode_count) {
+			// not found, i.e. the key was released
+			key = usbkbd_parse_scancode(kbd_dev->keycodes[j]);
+			kbd_push_ev(KEY_RELEASE, key);
+		} else {
+			// found, nothing happens
+		}
+	}
+	
+	// key presses
+	for (i = 0; i < kbd_dev->keycode_count; ++i) {
+		// try to find the new key in the old key list
+		j = 0;
+		while (j < kbd_dev->keycode_count 
+		    && kbd_dev->keycodes[j] != key_codes[i]) { 
+			++j;
+		}
+		
+		assert(kbd_dev->keycode_count <= kbd_dev->keycode_count);
+		
+		if (j == kbd_dev->keycode_count) {
+			// not found, i.e. new key pressed
+			key = usbkbd_parse_scancode(key_codes[i]);
+			kbd_push_ev(KEY_PRESS, key);
+		} else {
+			// found, nothing happens
+		}
+	}
+}
+
 /*
  * Callbacks for parser
@@ -260,23 +353,27 @@
     uint8_t modifiers, void *arg)
 {
-	printf("Got keys: ");
+	if (arg == NULL) {
+		usb_log_warning("Missing argument in callback "
+		    "usbkbd_process_keycodes().\n");
+		return;
+	}
+
+	usb_log_debug2("Got keys from parser: ");
 	unsigned i;
 	for (i = 0; i < count; ++i) {
-		printf("%d ", key_codes[i]);
-	}
-	printf("\n");
-
-	for (i = 0; i < count; ++i) {
-		// TODO: Key press / release
-
-		// TODO: NOT WORKING
-		unsigned int key = usbkbd_parse_scancode(key_codes[i]);
-
-		if (key == 0) {
-			continue;
-		}
-		kbd_push_ev(KEY_PRESS, key);
-	}
-	printf("\n");
+		usb_log_debug2("%d ", key_codes[i]);
+	}
+	usb_log_debug2("\n");
+	
+	usb_hid_dev_kbd_t *kbd_dev = (usb_hid_dev_kbd_t *)arg;
+	
+	if (count != kbd_dev->keycode_count) {
+		usb_log_warning("Number of received keycodes (%d) differs from"
+		    " expected number (%d).\n", count, kbd_dev->keycode_count);
+		return;
+	}
+	
+	usbkbd_check_modifier_changes(kbd_dev, modifiers);
+	usbkbd_check_key_changes(kbd_dev, key_codes);
 }
 
@@ -291,10 +388,11 @@
 	for (i = 0; i < kbd_dev->conf->config_descriptor.interface_count; ++i) {
 		// TODO: endianness
-		uint16_t length = 
-		    kbd_dev->conf->interfaces[i].hid_desc.report_desc_info.length;
+		uint16_t length =  kbd_dev->conf->interfaces[i].hid_desc.
+		    report_desc_info.length;
 		size_t actual_size = 0;
 
 		// allocate space for the report descriptor
-		kbd_dev->conf->interfaces[i].report_desc = (uint8_t *)malloc(length);
+		kbd_dev->conf->interfaces[i].report_desc = 
+		    (uint8_t *)malloc(length);
 		
 		// get the descriptor from the device
@@ -317,4 +415,5 @@
 	return EOK;
 }
+
 static int usbkbd_process_descriptors(usb_hid_dev_kbd_t *kbd_dev)
 {
@@ -388,5 +487,5 @@
 	free(descriptors);
 	if (rc != EOK) {
-		printf("Problem with parsing standard descriptors.\n");
+		usb_log_warning("Problem with parsing standard descriptors.\n");
 		return rc;
 	}
@@ -395,5 +494,5 @@
 	rc = usbkbd_get_report_descriptor(kbd_dev);
 	if (rc != EOK) {
-		printf("Problem with parsing HID REPORT descriptor.\n");
+		usb_log_warning("Problem with parsing REPORT descriptor.\n");
 		return rc;
 	}
@@ -405,7 +504,8 @@
 	 * 1) select one configuration (lets say the first)
 	 * 2) how many interfaces?? how to select one??
-     *    ("The default setting for an interface is always alternate setting zero.")
+	 *    ("The default setting for an interface is always alternate 
+	 *      setting zero.")
 	 * 3) find endpoint which is IN and INTERRUPT (parse), save its number
-     *    as the endpoint for polling
+	 *    as the endpoint for polling
 	 */
 
@@ -421,5 +521,5 @@
 
 	if (kbd_dev == NULL) {
-		fprintf(stderr, NAME ": No memory!\n");
+		usb_log_fatal("No memory!\n");
 		return NULL;
 	}
@@ -476,16 +576,18 @@
 	usb_hid_report_in_callbacks_t *callbacks =
 	    (usb_hid_report_in_callbacks_t *)malloc(
-		sizeof(usb_hid_report_in_callbacks_t));
+	        sizeof(usb_hid_report_in_callbacks_t));
 	callbacks->keyboard = usbkbd_process_keycodes;
 
 	//usb_hid_parse_report(kbd_dev->parser, buffer, actual_size, callbacks, 
 	//    NULL);
-	printf("Calling usb_hid_boot_keyboard_input_report() with size %zu\n",
-	    actual_size);
+	/*usb_log_debug2("Calling usb_hid_boot_keyboard_input_report() with size"
+	    " %zu\n", actual_size);*/
 	//dump_buffer("bufffer: ", buffer, actual_size);
-	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size, callbacks, 
-	    NULL);
-	if (rc != EOK) {
-		printf("Error in usb_hid_boot_keyboard_input_report(): %d\n", rc);
+	int rc = usb_hid_boot_keyboard_input_report(buffer, actual_size,
+	    callbacks, kbd_dev);
+	
+	if (rc != EOK) {
+		usb_log_warning("Error in usb_hid_boot_keyboard_input_report():"
+		    "%s\n", str_error(rc));
 	}
 }
@@ -497,5 +599,5 @@
 	size_t actual_size;
 
-	printf("Polling keyboard...\n");
+	usb_log_info("Polling keyboard...\n");
 
 	while (true) {
@@ -504,5 +606,5 @@
 		sess_rc = usb_endpoint_pipe_start_session(&kbd_dev->poll_pipe);
 		if (sess_rc != EOK) {
-			printf("Failed to start a session: %s.\n",
+			usb_log_warning("Failed to start a session: %s.\n",
 			    str_error(sess_rc));
 			continue;
@@ -514,5 +616,5 @@
 
 		if (rc != EOK) {
-			printf("Error polling the keyboard: %s.\n",
+			usb_log_warning("Error polling the keyboard: %s.\n",
 			    str_error(rc));
 			continue;
@@ -520,5 +622,5 @@
 
 		if (sess_rc != EOK) {
-			printf("Error closing session: %s.\n",
+			usb_log_warning("Error closing session: %s.\n",
 			    str_error(sess_rc));
 			continue;
@@ -530,5 +632,5 @@
 		 */
 		if (actual_size == 0) {
-			printf("Keyboard returned NAK\n");
+			usb_log_debug("Keyboard returned NAK\n");
 			continue;
 		}
@@ -537,5 +639,5 @@
 		 * TODO: Process pressed keys.
 		 */
-		printf("Calling usbkbd_process_interrupt_in()\n");
+		usb_log_debug("Calling usbkbd_process_interrupt_in()\n");
 		usbkbd_process_interrupt_in(kbd_dev, buffer, actual_size);
 	}
@@ -547,8 +649,6 @@
 static int usbkbd_fibril_device(void *arg)
 {
-	printf("!!! USB device fibril\n");
-
 	if (arg == NULL) {
-		printf("No device!\n");
+		usb_log_error("No device!\n");
 		return -1;
 	}
@@ -559,5 +659,5 @@
 	usb_hid_dev_kbd_t *kbd_dev = usbkbd_init_device(dev);
 	if (kbd_dev == NULL) {
-		printf("Error while initializing device.\n");
+		usb_log_error("Error while initializing device.\n");
 		return -1;
 	}
@@ -607,5 +707,5 @@
 	fid_t fid = fibril_create(usbkbd_fibril_device, dev);
 	if (fid == 0) {
-		printf("%s: failed to start fibril for HID device\n", NAME);
+		usb_log_error("Failed to start fibril for HID device\n");
 		return ENOMEM;
 	}
@@ -634,5 +734,5 @@
 int main(int argc, char *argv[])
 {
-	usb_log_enable(USB_LOG_LEVEL_INFO, "usbhid");
+	usb_log_enable(USB_LOG_LEVEL_MAX, NAME);
 	return ddf_driver_main(&kbd_driver);
 }
