Index: uspace/srv/hid/kbd/Makefile
===================================================================
--- uspace/srv/hid/kbd/Makefile	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/Makefile	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -52,5 +52,4 @@
 	port/adb.c \
 	port/chardev.c \
-	port/dummy.c \
 	port/gxemul.c \
 	port/msim.c \
Index: uspace/srv/hid/kbd/ctl/apple.c
===================================================================
--- uspace/srv/hid/kbd/ctl/apple.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/ctl/apple.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,7 +42,7 @@
 #include <kbd_port.h>
 
-static void apple_ctl_parse_scancode(int scancode);
-static int apple_ctl_init(kbd_port_ops_t *kbd_port);
-static void apple_ctl_set_ind(unsigned mods);
+static void apple_ctl_parse_scancode(int);
+static int apple_ctl_init(kbd_dev_t *);
+static void apple_ctl_set_ind(unsigned);
 
 kbd_ctl_ops_t apple_ctl = {
@@ -54,9 +54,11 @@
 #define KBD_KEY_RELEASE		0x80
 
+static kbd_dev_t *kbd_dev;
+
 static int scanmap[];
 
-static int apple_ctl_init(kbd_port_ops_t *kbd_port)
+static int apple_ctl_init(kbd_dev_t *kdev)
 {
-	(void) kbd_port;
+	kbd_dev = kdev;
 	return 0;
 }
@@ -79,5 +81,5 @@
 	key = scanmap[scancode];
 	if (key != 0)
-		kbd_push_ev(type, key);
+		kbd_push_ev(kbd_dev, type, key);
 }
 
Index: uspace/srv/hid/kbd/ctl/gxe_fb.c
===================================================================
--- uspace/srv/hid/kbd/ctl/gxe_fb.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/ctl/gxe_fb.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -44,7 +44,7 @@
 #include <stroke.h>
 
-static void gxe_fb_ctl_parse_scancode(int scancode);
-static int gxe_fb_ctl_init(kbd_port_ops_t *kbd_port);
-static void gxe_fb_ctl_set_ind(unsigned mods);
+static void gxe_fb_ctl_parse_scancode(int);
+static int gxe_fb_ctl_init(kbd_dev_t *);
+static void gxe_fb_ctl_set_ind(unsigned);
 
 kbd_ctl_ops_t gxe_fb_ctl = {
@@ -53,4 +53,6 @@
 	.set_ind = gxe_fb_ctl_set_ind
 };
+
+static kbd_dev_t *kbd_dev;
 
 /** Scancode parser */
@@ -218,7 +220,7 @@
 };
 
-static int gxe_fb_ctl_init(kbd_port_ops_t *kbd_port)
+static int gxe_fb_ctl_init(kbd_dev_t *kdev)
 {
-	(void) kbd_port;
+	kbd_dev = kdev;
 	ds = 0;
 
@@ -233,5 +235,5 @@
 	ds = gsp_step(&sp, ds, scancode, &mods, &key);
 	if (key != 0) {
-		stroke_sim(mods, key);
+		stroke_sim(kbd_dev, mods, key);
 	}
 }
Index: uspace/srv/hid/kbd/ctl/pc.c
===================================================================
--- uspace/srv/hid/kbd/ctl/pc.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/ctl/pc.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,7 +43,7 @@
 #include <gsp.h>
 
-static void pc_ctl_parse_scancode(int scancode);
-static int pc_ctl_init(kbd_port_ops_t *kbd_port);
-static void pc_ctl_set_ind(unsigned mods);
+static void pc_ctl_parse_scancode(int);
+static int pc_ctl_init(kbd_dev_t *);
+static void pc_ctl_set_ind(unsigned);
 
 kbd_ctl_ops_t pc_ctl = {
@@ -74,5 +74,5 @@
 
 static enum dec_state ds;
-static kbd_port_ops_t *kbd_port;
+static kbd_dev_t *kbd_dev;
 
 static int scanmap_simple[] = {
@@ -208,7 +208,7 @@
 };
 
-static int pc_ctl_init(kbd_port_ops_t *kbd_p)
+static int pc_ctl_init(kbd_dev_t *kdev)
 {
-	kbd_port = kbd_p;
+	kbd_dev = kdev;
 	ds = ds_s;
 	return 0;
@@ -262,5 +262,5 @@
 	key = map[scancode];
 	if (key != 0)
-		kbd_push_ev(type, key);
+		kbd_push_ev(kbd_dev, type, key);
 }
 
@@ -277,6 +277,6 @@
 		b = b | LI_SCROLL;
 
-	(*kbd_port->write)(KBD_CMD_SET_LEDS);
-	(*kbd_port->write)(b);
+	(*kbd_dev->port_ops->write)(KBD_CMD_SET_LEDS);
+	(*kbd_dev->port_ops->write)(b);
 }
 
Index: uspace/srv/hid/kbd/ctl/stty.c
===================================================================
--- uspace/srv/hid/kbd/ctl/stty.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/ctl/stty.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -43,7 +43,7 @@
 #include <stroke.h>
 
-static void stty_ctl_parse_scancode(int scancode);
-static int stty_ctl_init(kbd_port_ops_t *kbd_port);
-static void stty_ctl_set_ind(unsigned mods);
+static void stty_ctl_parse_scancode(int);
+static int stty_ctl_init(kbd_dev_t *);
+static void stty_ctl_set_ind(unsigned);
 
 kbd_ctl_ops_t stty_ctl = {
@@ -52,4 +52,6 @@
 	.set_ind = stty_ctl_set_ind
 };
+
+static kbd_dev_t *kbd_dev;
 
 /** Scancode parser */
@@ -217,7 +219,7 @@
 };
 
-static int stty_ctl_init(kbd_port_ops_t *kbd_port)
+static int stty_ctl_init(kbd_dev_t *kdev)
 {
-	(void) kbd_port;
+	kbd_dev = kdev;
 	ds = 0;
 
@@ -232,5 +234,5 @@
 	ds = gsp_step(&sp, ds, scancode, &mods, &key);
 	if (key != 0) {
-		stroke_sim(mods, key);
+		stroke_sim(kbd_dev, mods, key);
 	}
 }
Index: uspace/srv/hid/kbd/ctl/sun.c
===================================================================
--- uspace/srv/hid/kbd/ctl/sun.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/ctl/sun.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Jakub Jermar
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,7 +43,7 @@
 #include <kbd_port.h>
 
-static void sun_ctl_parse_scancode(int scancode);
-static int sun_ctl_init(kbd_port_ops_t *kbd_port);
-static void sun_ctl_set_ind(unsigned mods);
+static void sun_ctl_parse_scancode(int);
+static int sun_ctl_init(kbd_dev_t *);
+static void sun_ctl_set_ind(unsigned);
 
 kbd_ctl_ops_t sun_ctl = {
@@ -52,4 +53,6 @@
 };
 
+static kbd_dev_t *kbd_dev;
+
 #define KBD_KEY_RELEASE		0x80
 #define KBD_ALL_KEYS_UP		0x7f
@@ -57,6 +60,7 @@
 static int scanmap_simple[];
 
-static int sun_ctl_init(kbd_port_ops_t *kbd_port)
+static int sun_ctl_init(kbd_dev_t *kdev)
 {
+	kbd_dev = kdev;
 	return 0;
 }
@@ -82,5 +86,5 @@
 	key = scanmap_simple[scancode];
 	if (key != 0)
-		kbd_push_ev(type, key);
+		kbd_push_ev(kbd_dev, type, key);
 }
 
Index: uspace/srv/hid/kbd/genarch/stroke.c
===================================================================
--- uspace/srv/hid/kbd/genarch/stroke.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/genarch/stroke.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -52,5 +52,5 @@
 
 /** Simulate keystroke using sequences of key presses and releases. */
-void stroke_sim(unsigned mod, unsigned key)
+void stroke_sim(kbd_dev_t *kdev, unsigned mod, unsigned key)
 {
 	int i;
@@ -60,5 +60,5 @@
 	while (mods_keys[i][0] != 0) {
 		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(KEY_PRESS, mods_keys[i][1]);
+			kbd_push_ev(kdev, KEY_PRESS, mods_keys[i][1]);
 		}
 		++i;
@@ -67,6 +67,6 @@
 	/* Simulate key press and release. */
 	if (key != 0) {
-		kbd_push_ev(KEY_PRESS, key);
-		kbd_push_ev(KEY_RELEASE, key);
+		kbd_push_ev(kdev, KEY_PRESS, key);
+		kbd_push_ev(kdev, KEY_RELEASE, key);
 	}
 
@@ -75,5 +75,5 @@
 	while (mods_keys[i][0] != 0) {
 		if (mod & mods_keys[i][0]) {
-			kbd_push_ev(KEY_RELEASE, mods_keys[i][1]);
+			kbd_push_ev(kdev, KEY_RELEASE, mods_keys[i][1]);
 		}
 		++i;
Index: uspace/srv/hid/kbd/generic/kbd.c
===================================================================
--- uspace/srv/hid/kbd/generic/kbd.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/generic/kbd.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -36,4 +37,5 @@
  */
 
+#include <adt/list.h>
 #include <ipc/services.h>
 #include <ipc/kbd.h>
@@ -63,4 +65,7 @@
 #define NAMESPACE  "hid_in"
 
+static void kbd_devs_yield(void);
+static void kbd_devs_reclaim(void);
+
 int client_phone = -1;
 
@@ -71,6 +76,6 @@
 static unsigned lock_keys;
 
-static kbd_port_ops_t *kbd_port;
-static kbd_ctl_ops_t *kbd_ctl;
+/** List of keyboard devices */
+static link_t kbd_devs;
 
 bool irc_service = false;
@@ -87,11 +92,11 @@
 static int active_layout = 0;
 
-void kbd_push_scancode(int scancode)
+void kbd_push_scancode(kbd_dev_t *kdev, int scancode)
 {
 /*	printf("scancode: 0x%x\n", scancode);*/
-	(*kbd_ctl->parse_scancode)(scancode);
-}
-
-void kbd_push_ev(int type, unsigned int key)
+	(*kdev->ctl_ops->parse_scancode)(scancode);
+}
+
+void kbd_push_ev(kbd_dev_t *kdev, int type, unsigned int key)
 {
 	kbd_event_t ev;
@@ -133,5 +138,5 @@
 
 			/* Update keyboard lock indicator lights. */
-			(*kbd_ctl->set_ind)(mods);
+			(*kdev->ctl_ops->set_ind)(mods);
 		} else {
 			lock_keys = lock_keys & ~mod_mask;
@@ -204,9 +209,9 @@
 			break;
 		case KBD_YIELD:
-			(*kbd_port->yield)();
+			kbd_devs_yield();
 			retval = 0;
 			break;
 		case KBD_RECLAIM:
-			(*kbd_port->reclaim)();
+			kbd_devs_reclaim();
 			retval = 0;
 			break;
@@ -218,57 +223,113 @@
 }
 
-static void kbd_select_drivers(kbd_port_ops_t **port, kbd_ctl_ops_t **ctl)
-{
+/** Add new keyboard device. */
+static void kbd_add_dev(kbd_port_ops_t *port, kbd_ctl_ops_t *ctl)
+{
+	kbd_dev_t *kdev;
+
+	kdev = malloc(sizeof(kbd_dev_t));
+	if (kdev == NULL) {
+		printf(NAME ": Failed adding keyboard device. Out of memory.\n");
+		return;
+	}
+
+	link_initialize(&kdev->kbd_devs);
+	kdev->port_ops = port;
+	kdev->ctl_ops = ctl;
+
+	/* Initialize port driver. */
+	if ((*kdev->port_ops->init)(kdev) != 0)
+		goto fail;
+
+	/* Initialize controller driver. */
+	if ((*kdev->ctl_ops->init)(kdev) != 0) {
+		/* XXX Uninit port */
+		goto fail;
+	}
+
+	list_append(&kdev->kbd_devs, &kbd_devs);
+	return;
+fail:
+	free(kdev);
+}
+
+/** Add legacy drivers/devices. */
+static void kbd_add_legacy_devs(void)
+{
+	/*
+	 * Need to add these drivers based on config unless we can probe
+	 * them automatically.
+	 */
 #if defined(UARCH_amd64)
-	*port = &chardev_port;
-	*ctl = &pc_ctl;
-#elif defined(UARCH_arm32) && defined(MACHINE_gta02)
-	*port = &chardev_port;
-	*ctl = &stty_ctl;
-#elif defined(UARCH_arm32) && defined(MACHINE_testarm)
-	*port = &gxemul_port;
-	#ifdef CONFIG_FB
-		*ctl = &gxe_fb_ctl;
-	#else
-		*ctl = &stty_ctl;
-	#endif
-#elif defined(UARCH_arm32) && defined(MACHINE_integratorcp)
-	*port = &pl050_port;
-	*ctl = &pc_ctl;
-#elif defined(UARCH_ia32)
-	*port = &chardev_port;
-	*ctl = &pc_ctl;
-#elif defined(MACHINE_i460GX)
-	*port = &chardev_port;
-	*ctl = &pc_ctl;
-#elif defined(MACHINE_ski)
-	*port = &ski_port;
-	*ctl = &stty_ctl;
-#elif defined(MACHINE_msim)
-	*port = &msim_port;
-	*ctl = &stty_ctl;
-#elif defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)
-	*port = &gxemul_port;
-	#ifdef CONFIG_FB
-		*ctl = &gxe_fb_ctl;
-	#else
-		*ctl = &stty_ctl;
-	#endif
-#elif defined(UARCH_ppc32)
-	*port = &adb_port;
-	*ctl = &apple_ctl;
-#elif defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
-	*port = &niagara_port;
-	*ctl = &stty_ctl;
-#elif defined(UARCH_sparc64) && defined(MACHINE_serengeti)
-	*port = &sgcn_port;
-	*ctl = &stty_ctl;
-#elif defined(UARCH_sparc64) && defined(MACHINE_generic)
-	*port = &sun_port;
-	*ctl = &sun_ctl;
-#else
-	*port = &dummy_port;
-	*ctl = &pc_ctl;
-#endif
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_gta02)
+	kbd_add_dev(&chardev_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_testarm) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_arm32) && defined(MACHINE_integratorcp)
+	kbd_add_dev(&pl050_port, &pc_ctl);
+#endif
+#if defined(UARCH_ia32)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(MACHINE_i460GX)
+	kbd_add_dev(&chardev_port, &pc_ctl);
+#endif
+#if defined(MACHINE_ski)
+	kbd_add_dev(&ski_port, &stty_ctl);
+#endif
+#if defined(MACHINE_msim)
+	kbd_add_dev(&msim_port, &pc_ctl);
+#endif
+#if (defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul)) && defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &gxe_fb_ctl);
+#endif
+#if defined(MACHINE_lgxemul) || defined(MACHINE_bgxemul) && !defined(CONFIG_FB)
+	kbd_add_dev(&gxemul_port, &stty_ctl);
+#endif
+#if defined(UARCH_ppc32)
+	kbd_add_dev(&adb_port, &apple_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(PROCESSOR_sun4v)
+	kbd_add_dev(&niagara_port, &stty_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(MACHINE_serengeti)
+	kbd_add_dev(&sgcn_port, &stty_ctl);
+#endif
+#if defined(UARCH_sparc64) && defined(MACHINE_generic)
+	kbd_add_dev(&sun_port, &sun_ctl);
+#endif
+	/* Silence warning on abs32le about kbd_add_dev() being unused */
+	(void) kbd_add_dev;
+}
+
+static void kbd_devs_yield(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+
+		/* Yield port */
+		(*kdev->port_ops->yield)();
+	}
+}
+
+static void kbd_devs_reclaim(void)
+{
+	/* For each keyboard device */
+	list_foreach(kbd_devs, kdev_link) {
+		kbd_dev_t *kdev = list_get_instance(kdev_link, kbd_dev_t,
+		    kbd_devs);
+
+		/* Reclaim port */
+		(*kdev->port_ops->reclaim)();
+	}
 }
 
@@ -279,4 +340,6 @@
 	sysarg_t fhc;
 	sysarg_t obio;
+	
+	list_initialize(&kbd_devs);
 	
 	if (((sysinfo_get_value("kbd.cir.fhc", &fhc) == EOK) && (fhc))
@@ -289,14 +352,6 @@
 	}
 	
-	/* Select port and controller drivers. */
-	kbd_select_drivers(&kbd_port, &kbd_ctl);
-
-	/* Initialize port driver. */
-	if ((*kbd_port->init)() != 0)
-		return -1;
-
-	/* Initialize controller driver. */
-	if ((*kbd_ctl->init)(kbd_port) != 0)
-		return -1;
+	/* Add legacy devices. */
+	kbd_add_legacy_devs();
 
 	/* Initialize (reset) layout. */
Index: uspace/srv/hid/kbd/include/kbd.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd.h	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/include/kbd.h	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,11 +39,26 @@
 #define KBD_KBD_H_
 
+#include <adt/list.h>
 #include <bool.h>
+
+struct kbd_port_ops;
+struct kbd_ctl_ops;
+
+typedef struct kbd_dev {
+	/** Link to kbd_devs list */
+	link_t kbd_devs;
+
+	/** Port ops */
+	struct kbd_port_ops *port_ops;
+
+	/** Ctl ops */
+	struct kbd_ctl_ops *ctl_ops;
+} kbd_dev_t;
 
 extern bool irc_service;
 extern int irc_phone;
 
-extern void kbd_push_scancode(int);
-extern void kbd_push_ev(int, unsigned int);
+extern void kbd_push_scancode(kbd_dev_t *, int);
+extern void kbd_push_ev(kbd_dev_t *, int, unsigned int);
 
 #endif
Index: uspace/srv/hid/kbd/include/kbd_ctl.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd_ctl.h	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/include/kbd_ctl.h	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -40,7 +40,9 @@
 #include <kbd_port.h>
 
-typedef struct {
+struct kbd_dev;
+
+typedef struct kbd_ctl_ops {
 	void (*parse_scancode)(int);
-	int (*init)(kbd_port_ops_t *);
+	int (*init)(struct kbd_dev *);
 	void (*set_ind)(unsigned);
 } kbd_ctl_ops_t;
Index: uspace/srv/hid/kbd/include/kbd_port.h
===================================================================
--- uspace/srv/hid/kbd/include/kbd_port.h	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/include/kbd_port.h	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -40,6 +40,8 @@
 #include <sys/types.h>
 
-typedef struct {
-	int (*init)(void);
+struct kbd_dev;
+
+typedef struct kbd_port_ops {
+	int (*init)(struct kbd_dev *);
 	void (*yield)(void);
 	void (*reclaim)(void);
Index: uspace/srv/hid/kbd/include/stroke.h
===================================================================
--- uspace/srv/hid/kbd/include/stroke.h	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/include/stroke.h	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -38,5 +38,7 @@
 #define KBD_STROKE_H_
 
-extern void stroke_sim(unsigned, unsigned);
+#include <kbd.h>
+
+extern void stroke_sim(kbd_dev_t *, unsigned, unsigned);
 
 #endif
Index: uspace/srv/hid/kbd/include/sun.h
===================================================================
--- uspace/srv/hid/kbd/include/sun.h	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/include/sun.h	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -38,6 +38,8 @@
 #define KBD_SUN_H_
 
-extern int ns16550_port_init(void);
-extern int z8530_port_init(void);
+#include <kbd.h>
+
+extern int ns16550_port_init(kbd_dev_t *);
+extern int z8530_port_init(kbd_dev_t *);
 
 #endif
Index: uspace/srv/hid/kbd/port/adb.c
===================================================================
--- uspace/srv/hid/kbd/port/adb.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/adb.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2010 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -49,5 +49,5 @@
 static void adb_kbd_reg0_data(uint16_t data);
 
-static int adb_port_init(void);
+static int adb_port_init(kbd_dev_t *);
 static void adb_port_yield(void);
 static void adb_port_reclaim(void);
@@ -61,12 +61,15 @@
 };
 
+static kbd_dev_t *kbd_dev;
 static int dev_phone;
 
 #define NAME "kbd"
 
-static int adb_port_init(void)
+static int adb_port_init(kbd_dev_t *kdev)
 {
 	const char *dev = "adb/kbd";
 	devmap_handle_t handle;
+
+	kbd_dev = kdev;
 	
 	int rc = devmap_device_get_handle(dev, &handle, 0);
@@ -137,7 +140,7 @@
 
 	if (b0 != 0xff)
-		kbd_push_scancode(b0);
+		kbd_push_scancode(kbd_dev, b0);
 	if (b1 != 0xff)
-		kbd_push_scancode(b1);
+		kbd_push_scancode(kbd_dev, b1);
 }
 
Index: uspace/srv/hid/kbd/port/chardev.c
===================================================================
--- uspace/srv/hid/kbd/port/chardev.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/chardev.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -49,5 +49,5 @@
 static void kbd_port_events(ipc_callid_t iid, ipc_call_t *icall);
 
-static int chardev_port_init(void);
+static int chardev_port_init(kbd_dev_t *);
 static void chardev_port_yield(void);
 static void chardev_port_reclaim(void);
@@ -61,4 +61,5 @@
 };
 
+static kbd_dev_t *kbd_dev;
 static int dev_phone;
 
@@ -71,9 +72,11 @@
 static const unsigned int num_devs = sizeof(in_devs) / sizeof(in_devs[0]);
 
-static int chardev_port_init(void)
+static int chardev_port_init(kbd_dev_t *kdev)
 {
 	devmap_handle_t handle;
 	unsigned int i;
 	int rc;
+	
+	kbd_dev = kdev;
 	
 	for (i = 0; i < num_devs; i++) {
@@ -133,5 +136,5 @@
 		switch (IPC_GET_IMETHOD(call)) {
 		case CHAR_NOTIF_BYTE:
-			kbd_push_scancode(IPC_GET_ARG1(call));
+			kbd_push_scancode(kbd_dev, IPC_GET_ARG1(call));
 			break;
 		default:
Index: pace/srv/hid/kbd/port/dummy.c
===================================================================
--- uspace/srv/hid/kbd/port/dummy.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ 	(revision )
@@ -1,72 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * 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 kbd_port
- * @brief	Dummy keyboard port driver.
- * @ingroup  kbd
- * @{
- */ 
-/** @file
- */
-
-#include <kbd_port.h>
-#include <kbd.h>
-
-static int dummy_port_init(void);
-static void dummy_port_yield(void);
-static void dummy_port_reclaim(void);
-static void dummy_port_write(uint8_t data);
-
-kbd_port_ops_t dummy_port = {
-	.init = dummy_port_init,
-	.yield = dummy_port_yield,
-	.reclaim = dummy_port_reclaim,
-	.write = dummy_port_write
-};
-
-
-static int dummy_port_init(void)
-{
-	return 0;
-}
-
-static void dummy_port_yield(void)
-{
-}
-
-static void dummy_port_reclaim(void)
-{
-}
-
-static void dummy_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: uspace/srv/hid/kbd/port/gxemul.c
===================================================================
--- uspace/srv/hid/kbd/port/gxemul.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/gxemul.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2007 Michal Kebrt
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,5 +43,5 @@
 #include <errno.h>
 
-static int gxemul_port_init(void);
+static int gxemul_port_init(kbd_dev_t *);
 static void gxemul_port_yield(void);
 static void gxemul_port_reclaim(void);
@@ -53,4 +54,6 @@
 	.write = gxemul_port_write
 };
+
+static kbd_dev_t *kbd_dev;
 
 static irq_cmd_t gxemul_cmds[] = {
@@ -73,6 +76,8 @@
 
 /** Initializes keyboard handler. */
-static int gxemul_port_init(void)
+static int gxemul_port_init(kbd_dev_t *kdev)
 {
+	kbd_dev = kdev;
+	
 	sysarg_t addr;
 	if (sysinfo_get_value("kbd.address.virtual", &addr) != EOK)
@@ -113,5 +118,5 @@
 	int scan_code = IPC_GET_ARG2(*call);
 
-	kbd_push_scancode(scan_code);
+	kbd_push_scancode(kbd_dev, scan_code);
 }
 
Index: uspace/srv/hid/kbd/port/msim.c
===================================================================
--- uspace/srv/hid/kbd/port/msim.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/msim.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Josef Cejka
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,5 +43,5 @@
 #include <errno.h>
 
-static int msim_port_init(void);
+static int msim_port_init(kbd_dev_t *);
 static void msim_port_yield(void);
 static void msim_port_reclaim(void);
@@ -53,4 +54,6 @@
 	.write = msim_port_write
 };
+
+static kbd_dev_t *kbd_dev;
 
 static irq_cmd_t msim_cmds[] = {
@@ -72,6 +75,8 @@
 static void msim_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 
-static int msim_port_init(void)
+static int msim_port_init(kbd_dev_t *kdev)
 {
+	kbd_dev = kdev;
+
 	sysarg_t vaddr;
 	if (sysinfo_get_value("kbd.address.virtual", &vaddr) != EOK)
@@ -105,5 +110,5 @@
 {
 	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
+	kbd_push_scancode(kbd_dev, scan_code);
 }
 
Index: uspace/srv/hid/kbd/port/niagara.c
===================================================================
--- uspace/srv/hid/kbd/port/niagara.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/niagara.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2008 Pavel Rimsky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -46,5 +47,5 @@
 #include <errno.h>
 
-static int niagara_port_init(void);
+static int niagara_port_init(kbd_dev_t *);
 static void niagara_port_yield(void);
 static void niagara_port_reclaim(void);
@@ -57,4 +58,6 @@
 	.write = niagara_port_write
 };
+
+static kbd_dev_t *kbd_dev;
 
 #define POLL_INTERVAL  10000
@@ -91,6 +94,8 @@
  * Maps the shared buffer and creates the polling thread. 
  */
-static int niagara_port_init(void)
+static int niagara_port_init(kbd_dev_t *kdev)
 {
+	kbd_dev = kdev;
+	
 	sysarg_t paddr;
 	if (sysinfo_get_value("niagara.inbuf.address", &paddr) != EOK)
@@ -144,5 +149,5 @@
 		input_buffer->read_ptr =
 			((input_buffer->read_ptr) + 1) % INPUT_BUFFER_SIZE;
-		kbd_push_scancode(c);
+		kbd_push_scancode(kbd_dev, c);
 	}
 }
Index: uspace/srv/hid/kbd/port/ns16550.c
===================================================================
--- uspace/srv/hid/kbd/port/ns16550.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/ns16550.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -93,7 +93,11 @@
 static uintptr_t ns16550_kernel; 
 
-int ns16550_port_init(void)
+static kbd_dev_t *kbd_dev;
+
+int ns16550_port_init(kbd_dev_t *kdev)
 {
 	void *vaddr;
+
+	kbd_dev = kdev;
 
 	if (sysinfo_get_value("kbd.address.physical", &ns16550_physical) != EOK)
@@ -119,5 +123,5 @@
 {
 	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
+	kbd_push_scancode(kbd_dev, scan_code);
 	
 	if (irc_service)
Index: uspace/srv/hid/kbd/port/pl050.c
===================================================================
--- uspace/srv/hid/kbd/port/pl050.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/pl050.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Vineeth Pillai
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -46,5 +47,5 @@
 #include <errno.h>
 
-static int pl050_port_init(void);
+static int pl050_port_init(kbd_dev_t *);
 static void pl050_port_yield(void);
 static void pl050_port_reclaim(void);
@@ -57,4 +58,6 @@
 	.write = pl050_port_write
 };
+
+static kbd_dev_t *kbd_dev;
 
 #define PL050_STAT_RXFULL  (1 << 4)
@@ -94,6 +97,8 @@
 static void pl050_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 
-static int pl050_port_init(void)
+static int pl050_port_init(kbd_dev_t *kdev)
 {
+	kbd_dev = kdev;
+	
 	sysarg_t addr;
 	if (sysinfo_get_value("kbd.address.status", &addr) != EOK)
@@ -134,5 +139,5 @@
 	int scan_code = IPC_GET_ARG2(*call);
 
-	kbd_push_scancode(scan_code);
+	kbd_push_scancode(kbd_dev, scan_code);
 	return;
 }
Index: uspace/srv/hid/kbd/port/sgcn.c
===================================================================
--- uspace/srv/hid/kbd/port/sgcn.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/sgcn.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2008 Pavel Rimsky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -46,5 +47,5 @@
 #include <errno.h>
 
-static int sgcn_port_init(void);
+static int sgcn_port_init(kbd_dev_t *);
 static void sgcn_port_yield(void);
 static void sgcn_port_reclaim(void);
@@ -58,4 +59,6 @@
 };
 
+static kbd_dev_t *kbd_dev;
+
 #define POLL_INTERVAL  10000
 
@@ -113,6 +116,8 @@
  * Maps the physical memory (SRAM) and creates the polling thread. 
  */
-static int sgcn_port_init(void)
-{
+static int sgcn_port_init(kbd_dev_t *kdev)
+{
+	kbd_dev = kdev;
+	
 	sysarg_t sram_paddr;
 	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
@@ -179,5 +184,5 @@
 		buf_ptr = (volatile char *)
 			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		kbd_push_scancode(c);
+		kbd_push_scancode(kbd_dev, c);
 	}
 }
Index: uspace/srv/hid/kbd/port/ski.c
===================================================================
--- uspace/srv/hid/kbd/port/ski.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/ski.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2005 Jakub Jermar
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -45,5 +45,5 @@
 #include <bool.h>
 
-static int ski_port_init(void);
+static int ski_port_init(kbd_dev_t *);
 static void ski_port_yield(void);
 static void ski_port_reclaim(void);
@@ -57,4 +57,6 @@
 };
 
+static kbd_dev_t *kbd_dev;
+
 #define SKI_GETCHAR		21
 
@@ -67,8 +69,10 @@
 
 /** Initialize Ski port driver. */
-static int ski_port_init(void)
+static int ski_port_init(kbd_dev_t *kdev)
 {
 	thread_id_t tid;
 	int rc;
+
+	kbd_dev = kdev;
 
 	rc = thread_create(ski_thread_impl, NULL, "kbd_poll", &tid);
@@ -106,5 +110,5 @@
 			if (c == 0)
 				break;
-			kbd_push_scancode(c);
+			kbd_push_scancode(kbd_dev, c);
 		}
 
Index: uspace/srv/hid/kbd/port/sun.c
===================================================================
--- uspace/srv/hid/kbd/port/sun.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/sun.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2009 Martin Decky
+ * Copyright (c) 2011 Jiri Svoboda
  * All rights reserved.
  *
@@ -42,5 +43,5 @@
 #include <bool.h>
 
-static int sun_port_init(void);
+static int sun_port_init(kbd_dev_t *);
 static void sun_port_yield(void);
 static void sun_port_reclaim(void);
@@ -63,5 +64,5 @@
  *
  */
-static int sun_port_init(void)
+static int sun_port_init(kbd_dev_t *kdev)
 {
 	sysarg_t z8530;
@@ -74,10 +75,10 @@
 	
 	if (z8530) {
-		if (z8530_port_init() == 0)
+		if (z8530_port_init(kdev) == 0)
 			return 0;
 	}
 	
 	if (ns16550) {
-		if (ns16550_port_init() == 0)
+		if (ns16550_port_init(kdev) == 0)
 			return 0;
 	}
Index: uspace/srv/hid/kbd/port/z8530.c
===================================================================
--- uspace/srv/hid/kbd/port/z8530.c	(revision 56ad8182fe6d96f99cbc03b4179f8a786125041c)
+++ uspace/srv/hid/kbd/port/z8530.c	(revision 9be360ee65739363f6f9a07bfff0dac29a8b2888)
@@ -46,4 +46,6 @@
 #include <errno.h>
 
+static kbd_dev_t *kbd_dev;
+
 #define CHAN_A_STATUS  4
 #define CHAN_A_DATA    6
@@ -85,6 +87,8 @@
 static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
 
-int z8530_port_init(void)
+int z8530_port_init(kbd_dev_t *kdev)
 {
+	kbd_dev = kdev;
+	
 	sysarg_t kaddr;
 	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
@@ -107,5 +111,5 @@
 {
 	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
+	kbd_push_scancode(kbd_dev, scan_code);
 	
 	if (irc_service)
