Index: uspace/drv/hid/adb-kbd/Makefile
===================================================================
--- uspace/drv/hid/adb-kbd/Makefile	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/Makefile	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2017 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = drv
+BINARY = adb-kbd
+
+SOURCES = \
+	main.c \
+	adb-kbd.c \
+	ctl.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/hid/adb-kbd/adb-kbd.c
===================================================================
--- uspace/drv/hid/adb-kbd/adb-kbd.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/adb-kbd.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/** @file
+ * @brief ADB keyboard port driver.
+ */
+
+#include <async.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <io/console.h>
+#include <ipc/adb.h>
+#include <ipc/kbdev.h>
+#include <loc.h>
+#include <vfs/vfs.h>
+
+#include "adb-kbd.h"
+#include "ctl.h"
+
+static void adb_kbd_events(ipc_callid_t, ipc_call_t *, void *);
+static void adb_kbd_reg0_data(adb_kbd_t *, uint16_t);
+static void adb_kbd_conn(ipc_callid_t, ipc_call_t *, void *);
+
+/** Add ADB keyboard device */
+int adb_kbd_add(adb_kbd_t *kbd)
+{
+	int rc;
+	bool bound = false;
+
+	kbd->fun = ddf_fun_create(kbd->dev, fun_exposed, "a");
+	if (kbd->fun == NULL) {
+		ddf_msg(LVL_ERROR, "Error creating function");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	kbd->parent_sess = ddf_dev_parent_sess_get(kbd->dev);
+	if (kbd->parent_sess == NULL) {
+		ddf_msg(LVL_ERROR, "Error connecting parent driver");
+		rc = EIO;
+		goto error;
+	}
+
+	async_exch_t *exch = async_exchange_begin(kbd->parent_sess);
+	if (exch == NULL) {
+		ddf_msg(LVL_ERROR, "Error starting exchange with parent");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	port_id_t port;
+	rc = async_create_callback_port(exch, INTERFACE_ADB_CB, 0, 0,
+	    adb_kbd_events, kbd, &port);
+
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error creating callback from device");
+		goto error;
+	}
+
+	ddf_fun_set_conn_handler(kbd->fun, adb_kbd_conn);
+
+	rc = ddf_fun_bind(kbd->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error binding function");
+		goto error;
+	}
+
+	bound = true;
+
+	rc = ddf_fun_add_to_category(kbd->fun, "keyboard");
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error adding function to category");
+		goto error;
+	}
+
+	return EOK;
+error:
+	if (bound)
+		ddf_fun_unbind(kbd->fun);
+
+	if (kbd->parent_sess != NULL) {
+		async_hangup(kbd->parent_sess);
+		kbd->parent_sess = NULL;
+	}
+
+	if (kbd->fun != NULL) {
+		ddf_fun_destroy(kbd->fun);
+		kbd->fun = NULL;
+	}
+
+	return rc;
+}
+
+/** Remove ADB keyboard device */
+int adb_kbd_remove(adb_kbd_t *con)
+{
+	return ENOTSUP;
+}
+
+/** ADB keyboard device gone */
+int adb_kbd_gone(adb_kbd_t *con)
+{
+	return ENOTSUP;
+}
+
+static void adb_kbd_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	adb_kbd_t *kbd = (adb_kbd_t *) arg;
+
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		int retval = EOK;
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			adb_kbd_reg0_data(kbd, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+		async_answer_0(callid, retval);
+	}
+}
+
+static void adb_kbd_data(adb_kbd_t *kbd, uint8_t b)
+{
+	kbd_event_type_t etype;
+	unsigned int key;
+	int rc;
+
+	rc = adb_kbd_key_translate(b, &etype, &key);
+	if (rc != EOK)
+		return;
+
+	if (kbd->client_sess == NULL)
+		return;
+
+	async_exch_t *exch = async_exchange_begin(kbd->client_sess);
+	async_msg_4(exch, KBDEV_EVENT, etype, key, 0, 0);
+	async_exchange_end(exch);
+}
+
+static void adb_kbd_reg0_data(adb_kbd_t *kbd, uint16_t data)
+{
+	uint8_t b0 = (data >> 8) & 0xff;
+	uint8_t b1 = data & 0xff;
+
+	if (b0 != 0xff)
+		adb_kbd_data(kbd, b0);
+
+	if (b1 != 0xff)
+		adb_kbd_data(kbd, b1);
+	(void)b0; (void)b1;
+}
+
+/** Handle client connection */
+static void adb_kbd_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	sysarg_t method;
+	adb_kbd_t *kbd;
+
+	/*
+	 * Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+
+	kbd = (adb_kbd_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
+
+	while (true) {
+		callid = async_get_call(&call);
+		method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		async_sess_t *sess =
+		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
+		if (sess != NULL) {
+			kbd->client_sess = sess;
+			async_answer_0(callid, EOK);
+		} else {
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/hid/adb-kbd/adb-kbd.h
===================================================================
--- uspace/drv/hid/adb-kbd/adb-kbd.h	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/adb-kbd.h	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+/** @file
+ */
+
+#ifndef ADB_KBD_H
+#define ADB_KBD_H
+
+#include <async.h>
+#include <ddf/driver.h>
+
+/** ADB keyboard */
+typedef struct {
+	ddf_dev_t *dev;
+	async_sess_t *parent_sess;
+	ddf_fun_t *fun;
+	async_sess_t *client_sess;
+} adb_kbd_t;
+
+extern int adb_kbd_add(adb_kbd_t *);
+extern int adb_kbd_remove(adb_kbd_t *);
+extern int adb_kbd_gone(adb_kbd_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/hid/adb-kbd/adb-kbd.ma
===================================================================
--- uspace/drv/hid/adb-kbd/adb-kbd.ma	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/adb-kbd.ma	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,1 @@
+10 adb/keyboard
Index: uspace/drv/hid/adb-kbd/ctl.c
===================================================================
--- uspace/drv/hid/adb-kbd/ctl.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/ctl.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2011 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.
+ */
+
+/**
+ * @file
+ * @brief Apple ADB keyboard controller
+ */
+
+#include <errno.h>
+#include <io/console.h>
+#include <io/keycode.h>
+
+#include "ctl.h"
+
+#define KBD_KEY_RELEASE  0x80
+
+static unsigned int scanmap[] = {
+	[0x00] = KC_A,
+	[0x01] = KC_S,
+	[0x02] = KC_D,
+	[0x03] = KC_F,
+	[0x04] = KC_H,
+	[0x05] = KC_G,
+	[0x06] = KC_Z,
+	[0x07] = KC_X,
+	[0x08] = KC_C,
+	[0x09] = KC_V,
+	[0x0a] = KC_BACKSLASH,
+	[0x0b] = KC_B,
+	[0x0c] = KC_Q,
+	[0x0d] = KC_W,
+	[0x0e] = KC_E,
+	[0x0f] = KC_R,
+	[0x10] = KC_Y,
+	[0x11] = KC_T,
+	[0x12] = KC_1,
+	[0x13] = KC_2,
+	[0x14] = KC_3,
+	[0x15] = KC_4,
+	[0x16] = KC_6,
+	[0x17] = KC_5,
+	[0x18] = KC_EQUALS,
+	[0x19] = KC_9,
+	[0x1a] = KC_7,
+	[0x1b] = KC_MINUS,
+	[0x1c] = KC_8,
+	[0x1d] = KC_0,
+	[0x1e] = KC_RBRACKET,
+	[0x1f] = KC_O,
+	[0x20] = KC_U,
+	[0x21] = KC_LBRACKET,
+	[0x22] = KC_I,
+	[0x23] = KC_P,
+	[0x24] = KC_ENTER,
+	[0x25] = KC_L,
+	[0x26] = KC_J,
+	[0x27] = KC_QUOTE,
+	[0x28] = KC_K,
+	[0x29] = KC_SEMICOLON,
+	[0x2a] = KC_BACKSLASH,
+	[0x2b] = KC_COMMA,
+	[0x2c] = KC_SLASH,
+	[0x2d] = KC_N,
+	[0x2e] = KC_M,
+	[0x2f] = KC_PERIOD,
+	[0x30] = KC_TAB,
+	[0x31] = KC_SPACE,
+	[0x32] = KC_BACKTICK,
+	[0x33] = KC_BACKSPACE,
+	[0x34] = 0,
+	[0x35] = KC_ESCAPE,
+	[0x36] = KC_LCTRL,
+	[0x37] = 0,
+	[0x38] = KC_LSHIFT,
+	[0x39] = KC_CAPS_LOCK,
+	[0x3a] = KC_LALT,
+	[0x3b] = KC_LEFT,
+	[0x3c] = KC_RIGHT,
+	[0x3d] = KC_DOWN,
+	[0x3e] = KC_UP,
+	[0x3f] = 0,
+	[0x40] = 0,
+	[0x41] = KC_NPERIOD,
+	[0x42] = 0,
+	[0x43] = KC_NTIMES,
+	[0x44] = 0,
+	[0x45] = KC_NPLUS,
+	[0x46] = 0,
+	[0x47] = KC_NUM_LOCK,
+	[0x48] = 0,
+	[0x49] = 0,
+	[0x4a] = 0,
+	[0x4b] = KC_NSLASH,
+	[0x4c] = KC_NENTER,
+	[0x4d] = 0,
+	[0x4e] = KC_NMINUS,
+	[0x4f] = 0,
+	[0x50] = 0,
+	[0x51] = 0,
+	[0x52] = KC_N0,
+	[0x53] = KC_N1,
+	[0x54] = KC_N2,
+	[0x55] = KC_N3,
+	[0x56] = KC_N4,
+	[0x57] = KC_N5,
+	[0x58] = KC_N6,
+	[0x59] = KC_N7,
+	[0x5a] = 0,
+	[0x5b] = KC_N8,
+	[0x5c] = KC_N9,
+	[0x5d] = 0,
+	[0x5e] = 0,
+	[0x5f] = 0,
+	[0x60] = KC_F5,
+	[0x61] = KC_F6,
+	[0x62] = KC_F7,
+	[0x63] = KC_F3,
+	[0x64] = KC_F8,
+	[0x65] = KC_F9,
+	[0x66] = 0,
+	[0x67] = KC_F11,
+	[0x68] = 0,
+	[0x69] = KC_SYSREQ,
+	[0x6a] = 0,
+	[0x6b] = KC_SCROLL_LOCK,
+	[0x6c] = 0,
+	[0x6d] = KC_F10,
+	[0x6e] = 0,
+	[0x6f] = KC_F12,
+	[0x70] = 0,
+	[0x71] = KC_PAUSE,
+	[0x72] = KC_INSERT,
+	[0x73] = KC_HOME,
+	[0x74] = KC_PAGE_UP,
+	[0x75] = KC_DELETE,
+	[0x76] = KC_F4,
+	[0x77] = KC_END,
+	[0x78] = KC_F2,
+	[0x79] = KC_PAGE_DOWN,
+	[0x7a] = KC_F1,
+	[0x7b] = KC_RSHIFT,
+	[0x7c] = KC_RALT,
+	[0x7d] = KC_RCTRL,
+	[0x7e] = 0,
+	[0x7f] = 0
+};
+
+/** Translate ADB keyboard scancode into keyboard event.
+ *
+ * @param scancode Scancode
+ * @param rtype Place to store type of keyboard event (press or release)
+ * @param rkey Place to store key code
+ *
+ * @return EOK on success, ENOENT if no translation exists
+ */
+int adb_kbd_key_translate(sysarg_t scancode, kbd_event_type_t *rtype,
+    unsigned int *rkey)
+{
+	kbd_event_type_t etype;
+	unsigned int key;
+
+	if (scancode & KBD_KEY_RELEASE) {
+		scancode &= ~KBD_KEY_RELEASE;
+		etype = KEY_RELEASE;
+	} else {
+		etype = KEY_PRESS;
+	}
+
+	if (scancode >= sizeof(scanmap) / sizeof(unsigned int))
+		return ENOENT;
+
+	key = scanmap[scancode];
+	if (key == 0)
+		return ENOENT;
+
+	*rtype = etype;
+	*rkey = key;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/drv/hid/adb-kbd/ctl.h
===================================================================
--- uspace/drv/hid/adb-kbd/ctl.h	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/ctl.h	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+/**
+ * @file
+ * @brief Apple ADB keyboard controller
+ */
+
+#ifndef CTL_H
+#define CTL_H
+
+extern int adb_kbd_key_translate(sysarg_t, kbd_event_type_t *, unsigned int *);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/hid/adb-kbd/main.c
===================================================================
--- uspace/drv/hid/adb-kbd/main.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-kbd/main.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017 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 genarch
+ * @{
+ */
+/** @file ADB keyboard driver
+ */
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "adb-kbd.h"
+
+#define NAME  "adb-kbd"
+
+static int adb_kbd_dev_add(ddf_dev_t *dev);
+static int adb_kbd_dev_remove(ddf_dev_t *dev);
+static int adb_kbd_dev_gone(ddf_dev_t *dev);
+static int adb_kbd_fun_online(ddf_fun_t *fun);
+static int adb_kbd_fun_offline(ddf_fun_t *fun);
+
+static driver_ops_t driver_ops = {
+	.dev_add = adb_kbd_dev_add,
+	.dev_remove = adb_kbd_dev_remove,
+	.dev_gone = adb_kbd_dev_gone,
+	.fun_online = adb_kbd_fun_online,
+	.fun_offline = adb_kbd_fun_offline
+};
+
+static driver_t adb_kbd_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+static int adb_kbd_dev_add(ddf_dev_t *dev)
+{
+	adb_kbd_t *adb_kbd;
+
+        ddf_msg(LVL_DEBUG, "adb_kbd_dev_add(%p)", dev);
+	adb_kbd = ddf_dev_data_alloc(dev, sizeof(adb_kbd_t));
+	if (adb_kbd == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state.");
+		return ENOMEM;
+	}
+
+	adb_kbd->dev = dev;
+
+	return adb_kbd_add(adb_kbd);
+}
+
+static int adb_kbd_dev_remove(ddf_dev_t *dev)
+{
+        adb_kbd_t *adb_kbd = (adb_kbd_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "adb_kbd_dev_remove(%p)", dev);
+
+        return adb_kbd_remove(adb_kbd);
+}
+
+static int adb_kbd_dev_gone(ddf_dev_t *dev)
+{
+        adb_kbd_t *adb_kbd = (adb_kbd_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "adb_kbd_dev_gone(%p)", dev);
+
+        return adb_kbd_gone(adb_kbd);
+}
+
+static int adb_kbd_fun_online(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "adb_kbd_fun_online()");
+        return ddf_fun_online(fun);
+}
+
+static int adb_kbd_fun_offline(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "adb_kbd_fun_offline()");
+        return ddf_fun_offline(fun);
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": ADB keyboard driver\n");
+	ddf_log_init(NAME);
+	return ddf_driver_main(&adb_kbd_driver);
+}
+
+/** @}
+ */
Index: uspace/drv/hid/adb-mouse/Makefile
===================================================================
--- uspace/drv/hid/adb-mouse/Makefile	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-mouse/Makefile	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2017 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.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = drv
+BINARY = adb-mouse
+
+SOURCES = \
+	main.c \
+	adb-mouse.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/hid/adb-mouse/adb-mouse.c
===================================================================
--- uspace/drv/hid/adb-mouse/adb-mouse.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-mouse/adb-mouse.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2011 Martin Decky
+ * 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.
+ */
+
+/** @file
+ * @brief ADB mouse driver
+ */
+
+#include <async.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <ipc/adb.h>
+#include <ipc/mouseev.h>
+#include <loc.h>
+#include <stdio.h>
+
+#include "adb-mouse.h"
+
+static void adb_mouse_conn(ipc_callid_t, ipc_call_t *, void *);
+
+static void adb_mouse_event_button(adb_mouse_t *mouse, int bnum, int bpress)
+{
+	async_exch_t *exch = async_exchange_begin(mouse->client_sess);
+	async_msg_2(exch, MOUSEEV_BUTTON_EVENT, bnum, bpress);
+	async_exchange_end(exch);
+}
+
+static void adb_mouse_event_move(adb_mouse_t *mouse, int dx, int dy, int dz)
+{
+	async_exch_t *exch = async_exchange_begin(mouse->client_sess);
+	async_msg_3(exch, MOUSEEV_MOVE_EVENT, dx, dy, dz);
+	async_exchange_end(exch);
+}
+
+/** Process mouse data */
+static void adb_mouse_data(adb_mouse_t *mouse, sysarg_t data)
+{
+	bool b1, b2;
+	uint16_t udx, udy;
+	int dx, dy;
+
+	/* Extract fields. */
+	b1 = ((data >> 15) & 1) == 0;
+	udy = (data >> 8) & 0x7f;
+	b2 = ((data >> 7) & 1) == 0;
+	udx = data & 0x7f;
+
+	/* Decode 7-bit two's complement signed values. */
+	dx = (udx & 0x40) ? (udx - 0x80) : udx;
+	dy = (udy & 0x40) ? (udy - 0x80) : udy;
+
+	if (b1 != mouse->b1_pressed) {
+		adb_mouse_event_button(mouse, 1, b1);
+		mouse->b1_pressed = b1;
+	}
+
+	if (b2 != mouse->b2_pressed) {
+		adb_mouse_event_button(mouse, 2, b2);
+		mouse->b2_pressed = b2;
+	}
+
+	if (dx != 0 || dy != 0)
+		adb_mouse_event_move(mouse, dx, dy, 0);
+}
+
+static void adb_mouse_events(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	adb_mouse_t *mouse = (adb_mouse_t *) arg;
+
+	/* Ignore parameters, the connection is already opened */
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		int retval = EOK;
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case ADB_REG_NOTIF:
+			adb_mouse_data(mouse, IPC_GET_ARG1(call));
+			break;
+		default:
+			retval = ENOENT;
+		}
+
+		async_answer_0(callid, retval);
+	}
+}
+
+/** Add ADB mouse device */
+int adb_mouse_add(adb_mouse_t *mouse)
+{
+	int rc;
+	bool bound = false;
+
+	mouse->fun = ddf_fun_create(mouse->dev, fun_exposed, "a");
+	if (mouse->fun == NULL) {
+		ddf_msg(LVL_ERROR, "Error creating function");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	mouse->parent_sess = ddf_dev_parent_sess_get(mouse->dev);
+	if (mouse->parent_sess == NULL) {
+		ddf_msg(LVL_ERROR, "Error connecting parent driver");
+		rc = EIO;
+		goto error;
+	}
+
+	async_exch_t *exch = async_exchange_begin(mouse->parent_sess);
+	if (exch == NULL) {
+		ddf_msg(LVL_ERROR, "Error starting exchange with parent");
+		rc = ENOMEM;
+		goto error;
+	}
+
+	port_id_t port;
+	rc = async_create_callback_port(exch, INTERFACE_ADB_CB, 0, 0,
+	    adb_mouse_events, mouse, &port);
+
+	async_exchange_end(exch);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error creating callback from device");
+		goto error;
+	}
+
+	ddf_fun_set_conn_handler(mouse->fun, adb_mouse_conn);
+
+	rc = ddf_fun_bind(mouse->fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error binding function");
+		goto error;
+	}
+
+	bound = true;
+
+	rc = ddf_fun_add_to_category(mouse->fun, "mouse");
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error adding function to category");
+		goto error;
+	}
+
+	return EOK;
+error:
+	if (bound)
+		ddf_fun_unbind(mouse->fun);
+
+	if (mouse->parent_sess != NULL) {
+		async_hangup(mouse->parent_sess);
+		mouse->parent_sess = NULL;
+	}
+
+	if (mouse->fun != NULL) {
+		ddf_fun_destroy(mouse->fun);
+		mouse->fun = NULL;
+	}
+
+	return rc;
+}
+
+/** Remove ADB mouse device */
+int adb_mouse_remove(adb_mouse_t *con)
+{
+	return ENOTSUP;
+}
+
+/** ADB mouse device gone */
+int adb_mouse_gone(adb_mouse_t *con)
+{
+	return ENOTSUP;
+}
+
+/** Handle client connection */
+static void adb_mouse_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	sysarg_t method;
+	adb_mouse_t *mouse;
+
+	/*
+	 * Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	async_answer_0(iid, EOK);
+
+	mouse = (adb_mouse_t *)ddf_dev_data_get(ddf_fun_get_dev((ddf_fun_t *)arg));
+
+	while (true) {
+		callid = async_get_call(&call);
+		method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up. */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		async_sess_t *sess =
+		    async_callback_receive_start(EXCHANGE_SERIALIZE, &call);
+		if (sess != NULL) {
+			mouse->client_sess = sess;
+			async_answer_0(callid, EOK);
+		} else {
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/hid/adb-mouse/adb-mouse.h
===================================================================
--- uspace/drv/hid/adb-mouse/adb-mouse.h	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-mouse/adb-mouse.h	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 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.
+ */
+
+/** @file ADB mouse driver
+ */
+
+#ifndef ADB_MOUSE_H
+#define ADB_MOUSE_H
+
+#include <async.h>
+#include <ddf/driver.h>
+#include <stdbool.h>
+
+/** ADB mouse */
+typedef struct {
+	ddf_dev_t *dev;
+	async_sess_t *parent_sess;
+	ddf_fun_t *fun;
+	async_sess_t *client_sess;
+	bool b1_pressed;
+	bool b2_pressed;
+} adb_mouse_t;
+
+extern int adb_mouse_add(adb_mouse_t *);
+extern int adb_mouse_remove(adb_mouse_t *);
+extern int adb_mouse_gone(adb_mouse_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/drv/hid/adb-mouse/adb-mouse.ma
===================================================================
--- uspace/drv/hid/adb-mouse/adb-mouse.ma	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-mouse/adb-mouse.ma	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,1 @@
+10 adb/mouse
Index: uspace/drv/hid/adb-mouse/main.c
===================================================================
--- uspace/drv/hid/adb-mouse/main.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
+++ uspace/drv/hid/adb-mouse/main.c	(revision 0dd477996e38407057517d8fe2b97d416cd4e667)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017 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 genarch
+ * @{
+ */
+/** @file ADB keyboard driver
+ */
+
+#include <ddf/driver.h>
+#include <ddf/log.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "adb-mouse.h"
+
+#define NAME  "adb-mouse"
+
+static int adb_mouse_dev_add(ddf_dev_t *dev);
+static int adb_mouse_dev_remove(ddf_dev_t *dev);
+static int adb_mouse_dev_gone(ddf_dev_t *dev);
+static int adb_mouse_fun_online(ddf_fun_t *fun);
+static int adb_mouse_fun_offline(ddf_fun_t *fun);
+
+static driver_ops_t driver_ops = {
+	.dev_add = adb_mouse_dev_add,
+	.dev_remove = adb_mouse_dev_remove,
+	.dev_gone = adb_mouse_dev_gone,
+	.fun_online = adb_mouse_fun_online,
+	.fun_offline = adb_mouse_fun_offline
+};
+
+static driver_t adb_mouse_driver = {
+	.name = NAME,
+	.driver_ops = &driver_ops
+};
+
+static int adb_mouse_dev_add(ddf_dev_t *dev)
+{
+	adb_mouse_t *adb_mouse;
+
+        ddf_msg(LVL_DEBUG, "adb_mouse_dev_add(%p)", dev);
+	adb_mouse = ddf_dev_data_alloc(dev, sizeof(adb_mouse_t));
+	if (adb_mouse == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state.");
+		return ENOMEM;
+	}
+
+	adb_mouse->dev = dev;
+
+	return adb_mouse_add(adb_mouse);
+}
+
+static int adb_mouse_dev_remove(ddf_dev_t *dev)
+{
+        adb_mouse_t *adb_mouse = (adb_mouse_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "adb_mouse_dev_remove(%p)", dev);
+
+        return adb_mouse_remove(adb_mouse);
+}
+
+static int adb_mouse_dev_gone(ddf_dev_t *dev)
+{
+        adb_mouse_t *adb_mouse = (adb_mouse_t *)ddf_dev_data_get(dev);
+
+        ddf_msg(LVL_DEBUG, "adb_mouse_dev_gone(%p)", dev);
+
+        return adb_mouse_gone(adb_mouse);
+}
+
+static int adb_mouse_fun_online(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "adb_mouse_fun_online()");
+        return ddf_fun_online(fun);
+}
+
+static int adb_mouse_fun_offline(ddf_fun_t *fun)
+{
+        ddf_msg(LVL_DEBUG, "adb_mouse_fun_offline()");
+        return ddf_fun_offline(fun);
+}
+
+int main(int argc, char *argv[])
+{
+	printf(NAME ": ADB mouse driver\n");
+	ddf_log_init(NAME);
+	return ddf_driver_main(&adb_mouse_driver);
+}
+
+/** @}
+ */
