Index: uspace/drv/pciintel/pci.c
===================================================================
--- uspace/drv/pciintel/pci.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/drv/pciintel/pci.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -92,25 +92,27 @@
 	pci_fun_t *dev_data = (pci_fun_t *) fnode->driver_data;
 
-  sysarg_t apic;
-  sysarg_t i8259;
+	sysarg_t apic;
+	sysarg_t i8259;
 
 	int irc_phone = -1;
-	int irc_service = 0;
-
-  if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
-    irc_service = SERVICE_APIC;
+	int irc_service = -1;
+
+	if ((sysinfo_get_value("apic", &apic) == EOK) && (apic)) {
+		irc_service = SERVICE_APIC;
 	} else if ((sysinfo_get_value("i8259", &i8259) == EOK) && (i8259)) {
-    irc_service = SERVICE_I8259;
-	}
-
-  if (irc_service == 0)
+		irc_service = SERVICE_I8259;
+	}
+
+	if (irc_service == -1) {
 		return false;
+	}
 
 	irc_phone = service_connect_blocking(irc_service, 0, 0);
-	if (irc_phone < 0)
+	if (irc_phone < 0) {
 		return false;
+	}
 
 	size_t i;
-  for (i = 0; i < dev_data->hw_resources.count; i++) {
+	for (i = 0; i < dev_data->hw_resources.count; i++) {
 		if (dev_data->hw_resources.resources[i].type == INTERRUPT) {
 			int irq = dev_data->hw_resources.resources[i].res.interrupt.irq;
Index: uspace/drv/usbmouse/init.c
===================================================================
--- uspace/drv/usbmouse/init.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/drv/usbmouse/init.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -42,5 +42,5 @@
 
 /** Mouse polling endpoint description for boot protocol subclass. */
-static usb_endpoint_description_t poll_endpoint_description = {
+usb_endpoint_description_t poll_endpoint_description = {
 	.transfer_type = USB_TRANSFER_INTERRUPT,
 	.direction = USB_DIRECTION_IN,
@@ -50,53 +50,4 @@
 	.flags = 0
 };
-
-/** Initialize poll pipe.
- *
- * Expects that session is already started on control pipe zero.
- *
- * @param mouse Mouse device.
- * @param my_interface Interface number.
- * @return Error code.
- */
-static int intialize_poll_pipe(usb_mouse_t *mouse, int my_interface)
-{
-	assert(usb_endpoint_pipe_is_session_started(&mouse->ctrl_pipe));
-
-	int rc;
-
-	void *config_descriptor;
-	size_t config_descriptor_size;
-
-	rc = usb_request_get_full_configuration_descriptor_alloc(
-	    &mouse->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	usb_endpoint_mapping_t endpoint_mapping[1] = {
-		{
-			.pipe = &mouse->poll_pipe,
-			.description = &poll_endpoint_description,
-			.interface_no = my_interface
-		}
-	};
-
-	rc = usb_endpoint_pipe_initialize_from_configuration(endpoint_mapping,
-	    1, config_descriptor, config_descriptor_size, &mouse->wire);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (!endpoint_mapping[0].present) {
-		return ENOENT;
-	}
-
-	mouse->poll_interval_us = 1000 * endpoint_mapping[0].descriptor->poll_interval;
-
-	usb_log_debug("prepared polling endpoint %d (interval %zu).\n",
-	    mouse->poll_pipe.endpoint_no, mouse->poll_interval_us);
-
-	return EOK;
-}
 
 static void default_connection_handler(ddf_fun_t *, ipc_callid_t, ipc_call_t *);
@@ -143,5 +94,5 @@
  * @return Error code.
  */
-int usb_mouse_create(ddf_dev_t *dev)
+int usb_mouse_create(usb_device_t *dev)
 {
 	usb_mouse_t *mouse = malloc(sizeof(usb_mouse_t));
@@ -149,38 +100,11 @@
 		return ENOMEM;
 	}
-	mouse->device = dev;
+	mouse->dev = dev;
 	mouse->console_phone = -1;
 
 	int rc;
 
-	/* Initialize the backing connection. */
-	rc = usb_device_connection_initialize_from_device(&mouse->wire, dev);
-	if (rc != EOK) {
-		goto leave;
-	}
-
-	/* Initialize the default control pipe. */
-	rc = usb_endpoint_pipe_initialize_default_control(&mouse->ctrl_pipe,
-	    &mouse->wire);
-	if (rc != EOK) {
-		goto leave;
-	}
-
-	rc = usb_endpoint_pipe_start_session(&mouse->ctrl_pipe);
-	if (rc != EOK) {
-		goto leave;
-	}
-
-	rc = intialize_poll_pipe(mouse, usb_device_get_assigned_interface(dev));
-
-	/* We can ignore error here. */
-	usb_endpoint_pipe_end_session(&mouse->ctrl_pipe);
-
-	if (rc != EOK) {
-		goto leave;
-	}
-
 	/* Create DDF function. */
-	mouse->mouse_fun = ddf_fun_create(dev, fun_exposed, "mouse");
+	mouse->mouse_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, "mouse");
 	if (mouse->mouse_fun == NULL) {
 		rc = ENOMEM;
Index: uspace/drv/usbmouse/main.c
===================================================================
--- uspace/drv/usbmouse/main.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/drv/usbmouse/main.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -44,5 +44,5 @@
  * @return Error code.
  */
-static int usbmouse_add_device(ddf_dev_t *dev)
+static int usbmouse_add_device(usb_device_t *dev)
 {
 	int rc = usb_mouse_create(dev);
@@ -53,15 +53,18 @@
 	}
 
-	fid_t poll_fibril = fibril_create(usb_mouse_polling_fibril, dev);
-	if (poll_fibril == 0) {
-		usb_log_error("Failed to initialize polling fibril.\n");
-		/* FIXME: free allocated resources. */
-		return ENOMEM;
+	usb_log_debug("Polling pipe at endpoint %d.\n", dev->pipes[0].pipe->endpoint_no);
+
+	rc = usb_device_auto_poll(dev, 0,
+	    usb_mouse_polling_callback, dev->pipes[0].pipe->max_packet_size,
+	    usb_mouse_polling_ended_callback, dev->driver_data);
+
+	if (rc != EOK) {
+		usb_log_error("Failed to start polling fibril: %s.\n",
+		    str_error(rc));
+		return rc;
 	}
 
-	fibril_add_ready(poll_fibril);
-
 	usb_log_info("controlling new mouse (handle %llu).\n",
-	    dev->handle);
+	    dev->ddf_dev->handle);
 
 	return EOK;
@@ -69,12 +72,18 @@
 
 /** USB mouse driver ops. */
-static driver_ops_t mouse_driver_ops = {
+static usb_driver_ops_t mouse_driver_ops = {
 	.add_device = usbmouse_add_device,
 };
 
+static usb_endpoint_description_t *endpoints[] = {
+	&poll_endpoint_description,
+	NULL
+};
+
 /** USB mouse driver. */
-static driver_t mouse_driver = {
+static usb_driver_t mouse_driver = {
 	.name = NAME,
-	.driver_ops = &mouse_driver_ops
+	.ops = &mouse_driver_ops,
+	.endpoints = endpoints
 };
 
@@ -83,5 +92,5 @@
 	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
 
-	return ddf_driver_main(&mouse_driver);
+	return usb_driver_main(&mouse_driver);
 }
 
Index: uspace/drv/usbmouse/mouse.c
===================================================================
--- uspace/drv/usbmouse/mouse.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/drv/usbmouse/mouse.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -40,124 +40,82 @@
 #include <ipc/mouse.h>
 
-/** Fibril function for polling the mouse device.
+/** Mouse polling callback.
  *
- * This function shall not terminate unless the device breaks and fails
- * to send data (e.g. stalls on data request).
- *
- * @param arg ddf_dev_t type representing the mouse device.
- * @return EOK Always.
+ * @param dev Device that is being polled.
+ * @param buffer Data buffer.
+ * @param buffer_size Buffer size in bytes.
+ * @param arg Custom argument - points to usb_mouse_t.
+ * @return Always true.
  */
-int usb_mouse_polling_fibril(void *arg)
+bool usb_mouse_polling_callback(usb_device_t *dev,
+    uint8_t *buffer, size_t buffer_size, void *arg)
 {
-	assert(arg != NULL);
-	ddf_dev_t *dev = (ddf_dev_t *) arg;
-	usb_mouse_t *mouse = (usb_mouse_t *) dev->driver_data;
+	usb_mouse_t *mouse = (usb_mouse_t *) arg;
 
-	assert(mouse);
+	usb_log_debug2("got buffer: %s.\n",
+	    usb_debug_str_buffer(buffer, buffer_size, 0));
 
-	size_t buffer_size = mouse->poll_pipe.max_packet_size;
+	uint8_t butt = buffer[0];
+	char str_buttons[4] = {
+		butt & 1 ? '#' : '.',
+		butt & 2 ? '#' : '.',
+		butt & 4 ? '#' : '.',
+		0
+	};
 
-	if (buffer_size < 4) {
-		usb_log_error("Weird mouse, results will be skewed.\n");
-		buffer_size = 4;
+	int shift_x = ((int) buffer[1]) - 127;
+	int shift_y = ((int) buffer[2]) - 127;
+	int wheel = ((int) buffer[3]) - 127;
+
+	if (buffer[1] == 0) {
+		shift_x = 0;
+	}
+	if (buffer[2] == 0) {
+		shift_y = 0;
+	}
+	if (buffer[3] == 0) {
+		wheel = 0;
 	}
 
-	uint8_t *buffer = malloc(buffer_size);
-	if (buffer == NULL) {
-		usb_log_error("Out of memory, poll fibril aborted.\n");
-		return ENOMEM;
+	if (mouse->console_phone >= 0) {
+		if ((shift_x != 0) || (shift_y != 0)) {
+			/* FIXME: guessed for QEMU */
+			async_req_2_0(mouse->console_phone,
+			    MEVENT_MOVE,
+			    - shift_x / 10,  - shift_y / 10);
+		}
+		if (butt) {
+			/* FIXME: proper button clicking. */
+			async_req_2_0(mouse->console_phone,
+			    MEVENT_BUTTON, 1, 1);
+			async_req_2_0(mouse->console_phone,
+			    MEVENT_BUTTON, 1, 0);
+		}
 	}
 
-	while (true) {
-		async_usleep(mouse->poll_interval_us);
+	usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
+	    str_buttons, shift_x, shift_y, wheel);
 
-		size_t actual_size;
-		int rc;
+	/* Guess. */
+	async_usleep(1000);
 
-		/*
-		 * Error checking note:
-		 * - failure when starting a session is considered
-		 *   temporary (e.g. out of phones, next try might succeed)
-		 * - failure of transfer considered fatal (probably the
-		 *   device was unplugged)
-		 * - session closing not checked (shall not fail anyway)
-		 */
+	return true;
+}
 
-		rc = usb_endpoint_pipe_start_session(&mouse->poll_pipe);
-		if (rc != EOK) {
-			usb_log_warning("Failed to start session, will try again: %s.\n",
-			    str_error(rc));
-			continue;
-		}
+/** Callback when polling is terminated.
+ *
+ * @param dev Device where the polling terminated.
+ * @param recurring_errors Whether the polling was terminated due to
+ *	recurring errors.
+ * @param arg Custom argument - points to usb_mouse_t.
+ */
+void usb_mouse_polling_ended_callback(usb_device_t *dev,
+    bool recurring_errors, void *arg)
+{
+	usb_mouse_t *mouse = (usb_mouse_t *) arg;
 
-		rc = usb_endpoint_pipe_read(&mouse->poll_pipe,
-		    buffer, buffer_size, &actual_size);
-
-		usb_endpoint_pipe_end_session(&mouse->poll_pipe);
-
-		if (rc != EOK) {
-			usb_log_error("Failed reading mouse input: %s.\n",
-			    str_error(rc));
-			break;
-		}
-
-		usb_log_debug2("got buffer: %s.\n",
-		    usb_debug_str_buffer(buffer, buffer_size, 0));
-
-		uint8_t butt = buffer[0];
-		char str_buttons[4] = {
-			butt & 1 ? '#' : '.',
-			butt & 2 ? '#' : '.',
-			butt & 4 ? '#' : '.',
-			0
-		};
-
-		int shift_x = ((int) buffer[1]) - 127;
-		int shift_y = ((int) buffer[2]) - 127;
-		int wheel = ((int) buffer[3]) - 127;
-
-		if (buffer[1] == 0) {
-			shift_x = 0;
-		}
-		if (buffer[2] == 0) {
-			shift_y = 0;
-		}
-		if (buffer[3] == 0) {
-			wheel = 0;
-		}
-
-		if (mouse->console_phone >= 0) {
-			if ((shift_x != 0) || (shift_y != 0)) {
-				/* FIXME: guessed for QEMU */
-				async_req_2_0(mouse->console_phone,
-				    MEVENT_MOVE,
-				    - shift_x / 10,  - shift_y / 10);
-			}
-			if (butt) {
-				/* FIXME: proper button clicking. */
-				async_req_2_0(mouse->console_phone,
-				    MEVENT_BUTTON, 1, 1);
-				async_req_2_0(mouse->console_phone,
-				    MEVENT_BUTTON, 1, 0);
-			}
-		}
-
-		usb_log_debug("buttons=%s  dX=%+3d  dY=%+3d  wheel=%+3d\n",
-		   str_buttons, shift_x, shift_y, wheel);
-	}
-
-	/*
-	 * Device was probably unplugged.
-	 * Hang-up the phone to the console.
-	 * FIXME: release allocated memory.
-	 */
 	async_hangup(mouse->console_phone);
 	mouse->console_phone = -1;
-
-	usb_log_error("Mouse polling fibril terminated.\n");
-
-	return EOK;
 }
-
 
 /**
Index: uspace/drv/usbmouse/mouse.h
===================================================================
--- uspace/drv/usbmouse/mouse.h	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/drv/usbmouse/mouse.h	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -37,5 +37,5 @@
 #define USBMOUSE_MOUSE_H_
 
-#include <ddf/driver.h>
+#include <usb/devdrv.h>
 #include <usb/pipes.h>
 #include <time.h>
@@ -46,13 +46,7 @@
 typedef struct {
 	/** Generic device container. */
-	ddf_dev_t *device;
+	usb_device_t *dev;
 	/** Function representing the device. */
 	ddf_fun_t *mouse_fun;
-	/** Representation of connection to the device. */
-	usb_device_connection_t wire;
-	/** Default (zero) control pipe. */
-	usb_endpoint_pipe_t ctrl_pipe;
-	/** Polling (in) pipe. */
-	usb_endpoint_pipe_t poll_pipe;
 	/** Polling interval in microseconds. */
 	suseconds_t poll_interval_us;
@@ -61,7 +55,12 @@
 } usb_mouse_t;
 
-int usb_mouse_create(ddf_dev_t *);
+#define POLL_PIPE(dev) ((dev)->pipes[0].pipe)
 
-int usb_mouse_polling_fibril(void *);
+extern usb_endpoint_description_t poll_endpoint_description;
+
+int usb_mouse_create(usb_device_t *);
+
+bool usb_mouse_polling_callback(usb_device_t *, uint8_t *, size_t, void *);
+void usb_mouse_polling_ended_callback(usb_device_t *, bool, void *);
 
 #endif
Index: uspace/lib/drv/generic/remote_usbhc.c
===================================================================
--- uspace/lib/drv/generic/remote_usbhc.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/lib/drv/generic/remote_usbhc.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -55,4 +55,6 @@
 static void remote_usbhc_bind_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 static void remote_usbhc_release_address(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_register_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbhc_unregister_endpoint(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 //static void remote_usbhc(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
@@ -73,5 +75,8 @@
 
 	remote_usbhc_control_write,
-	remote_usbhc_control_read
+	remote_usbhc_control_read,
+
+	remote_usbhc_register_endpoint,
+	remote_usbhc_unregister_endpoint
 };
 
@@ -522,4 +527,57 @@
 
 
+void remote_usbhc_register_endpoint(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->register_endpoint) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+#define INIT_FROM_HIGH_DATA(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) / 256
+#define INIT_FROM_LOW_DATA(type, var, arg_no) \
+	type var = (type) DEV_IPC_GET_ARG##arg_no(*call) % 256
+
+	INIT_FROM_HIGH_DATA(usb_address_t, address, 1);
+	INIT_FROM_LOW_DATA(usb_endpoint_t, endpoint, 1);
+	INIT_FROM_HIGH_DATA(usb_transfer_type_t, transfer_type, 2);
+	INIT_FROM_LOW_DATA(usb_direction_t, direction, 2);
+
+#undef INIT_FROM_HIGH_DATA
+#undef INIT_FROM_LOW_DATA
+
+	size_t max_packet_size = (size_t) DEV_IPC_GET_ARG3(*call);
+	unsigned int interval  = (unsigned int) DEV_IPC_GET_ARG4(*call);
+
+	int rc = usb_iface->register_endpoint(fun, address, endpoint,
+	    transfer_type, direction, max_packet_size, interval);
+
+	async_answer_0(callid, rc);
+}
+
+
+void remote_usbhc_unregister_endpoint(ddf_fun_t *fun, void *iface,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	usbhc_iface_t *usb_iface = (usbhc_iface_t *) iface;
+
+	if (!usb_iface->unregister_endpoint) {
+		async_answer_0(callid, ENOTSUP);
+		return;
+	}
+
+	usb_address_t address = (usb_address_t) DEV_IPC_GET_ARG1(*call);
+	usb_endpoint_t endpoint = (usb_endpoint_t) DEV_IPC_GET_ARG2(*call);
+	usb_direction_t direction = (usb_direction_t) DEV_IPC_GET_ARG3(*call);
+
+	int rc = usb_iface->unregister_endpoint(fun,
+	    address, endpoint, direction);
+
+	async_answer_0(callid, rc);
+}
+
 
 /**
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -167,5 +167,27 @@
 	IPC_M_USBHC_CONTROL_READ,
 
-	/* IPC_M_USB_ */
+	/** Register endpoint attributes at host controller.
+	 * This is used to reserve portion of USB bandwidth.
+	 * Parameters:
+	 * - USB address + endpoint number (ADDR * 256 + EP)
+	 * - transfer type + direction (TYPE * 256 + DIR)
+	 * - maximum packet size
+	 * - interval (in milliseconds)
+	 * Answer:
+	 * - EOK - reservation successful
+	 * - ELIMIT - not enough bandwidth to satisfy the request
+	 */
+	IPC_M_USBHC_REGISTER_ENDPOINT,
+
+	/** Revert endpoint registration.
+	 * Parameters:
+	 * - USB address
+	 * - endpoint number
+	 * - data direction
+	 * Answer:
+	 * - EOK - endpoint unregistered
+	 * - ENOENT - unknown endpoint
+	 */
+	IPC_M_USBHC_UNREGISTER_ENDPOINT
 } usbhc_iface_funcs_t;
 
@@ -200,4 +222,9 @@
 	int (*release_address)(ddf_fun_t *, usb_address_t);
 
+	int (*register_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
+	    usb_transfer_type_t, usb_direction_t, size_t, unsigned int);
+	int (*unregister_endpoint)(ddf_fun_t *, usb_address_t, usb_endpoint_t,
+	    usb_direction_t);
+
 	usbhc_iface_transfer_out_t interrupt_out;
 	usbhc_iface_transfer_in_t interrupt_in;
Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/lib/usb/Makefile	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -37,4 +37,6 @@
 	src/ddfiface.c \
 	src/debug.c \
+	src/devdrv.c \
+	src/devpoll.c \
 	src/dp.c \
 	src/dump.c \
Index: uspace/lib/usb/include/usb/devdrv.h
===================================================================
--- uspace/lib/usb/include/usb/devdrv.h	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
+++ uspace/lib/usb/include/usb/devdrv.h	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB device driver framework.
+ */
+#ifndef LIBUSB_DEVDRV_H_
+#define LIBUSB_DEVDRV_H_
+
+#include <usb/pipes.h>
+
+/** USB device structure. */
+typedef struct {
+	/** The default control pipe. */
+	usb_endpoint_pipe_t ctrl_pipe;
+	/** Other endpoint pipes.
+	 * This is an array of other endpoint pipes in the same order as
+	 * in usb_driver_t.
+	 */
+	usb_endpoint_mapping_t *pipes;
+	/** Generic DDF device backing this one. */
+	ddf_dev_t *ddf_dev;
+	/** Custom driver data.
+	 * Do not use the entry in generic device, that is already used
+	 * by the framework.
+	 */
+	void *driver_data;
+
+	/** Connection backing the pipes.
+	 * Typically, you will not need to use this attribute at all.
+	 */
+	usb_device_connection_t wire;
+} usb_device_t;
+
+/** USB driver ops. */
+typedef struct {
+	/** Callback when new device is about to be controlled by the driver. */
+	int (*add_device)(usb_device_t *);
+} usb_driver_ops_t;
+
+/** USB driver structure. */
+typedef struct {
+	/** Driver name.
+	 * This name is copied to the generic driver name and must be exactly
+	 * the same as the directory name where the driver executable resides.
+	 */
+	const char *name;
+	/** Expected endpoints description. */
+	usb_endpoint_description_t **endpoints;
+	/** Driver ops. */
+	usb_driver_ops_t *ops;
+} usb_driver_t;
+
+int usb_driver_main(usb_driver_t *);
+
+typedef bool (*usb_polling_callback_t)(usb_device_t *,
+    uint8_t *, size_t, void *);
+typedef void (*usb_polling_terminted_callback_t)(usb_device_t *, bool, void *);
+
+
+int usb_device_auto_poll(usb_device_t *, size_t,
+    usb_polling_callback_t, size_t, usb_polling_terminted_callback_t, void *);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/lib/usb/include/usb/pipes.h	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -106,5 +106,5 @@
 	const usb_endpoint_description_t *description;
 	/** Interface number the endpoint must belong to (-1 for any). */
-	const int interface_no;
+	int interface_no;
 	/** Found descriptor fitting the description. */
 	usb_standard_endpoint_descriptor_t *descriptor;
@@ -131,5 +131,7 @@
 int usb_endpoint_pipe_initialize_from_configuration(usb_endpoint_mapping_t *,
     size_t, uint8_t *, size_t, usb_device_connection_t *);
-
+int usb_endpoint_pipe_register(usb_endpoint_pipe_t *, unsigned int,
+    usb_hc_connection_t *);
+int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *, usb_hc_connection_t *);
 
 int usb_endpoint_pipe_start_session(usb_endpoint_pipe_t *);
Index: uspace/lib/usb/src/devdrv.c
===================================================================
--- uspace/lib/usb/src/devdrv.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
+++ uspace/lib/usb/src/devdrv.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB device driver framework.
+ */
+#include <usb/devdrv.h>
+#include <usb/request.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+
+static int generic_add_device(ddf_dev_t *);
+
+static driver_ops_t generic_driver_ops = {
+	.add_device = generic_add_device
+};
+static driver_t generic_driver = {
+	.driver_ops = &generic_driver_ops
+};
+
+static usb_driver_t *driver = NULL;
+
+
+/** Main routine of USB device driver.
+ *
+ * Under normal conditions, this function never returns.
+ *
+ * @param drv USB device driver structure.
+ * @return Task exit status.
+ */
+int usb_driver_main(usb_driver_t *drv)
+{
+	assert(drv != NULL);
+
+	/* Prepare the generic driver. */
+	generic_driver.name = drv->name;
+
+	driver = drv;
+
+	return ddf_driver_main(&generic_driver);
+}
+
+/** Log out of memory error on given device.
+ *
+ * @param dev Device causing the trouble.
+ */
+static void usb_log_oom(ddf_dev_t *dev)
+{
+	usb_log_error("Out of memory when adding device `%s'.\n",
+	    dev->name);
+}
+
+/** Count number of pipes the driver expects.
+ *
+ * @param drv USB driver.
+ * @return Number of pipes (excluding default control pipe).
+ */
+static size_t count_other_pipes(usb_driver_t *drv)
+{
+	size_t count = 0;
+	if (drv->endpoints == NULL) {
+		return 0;
+	}
+
+	while (drv->endpoints[count] != NULL) {
+		count++;
+	}
+
+	return count;
+}
+
+/** Initialize endpoint pipes, excluding default control one.
+ *
+ * @param drv The device driver.
+ * @param dev Device to be initialized.
+ * @return Error code.
+ */
+static int initialize_other_pipes(usb_driver_t *drv, usb_device_t *dev)
+{
+	int rc;
+	int my_interface = usb_device_get_assigned_interface(dev->ddf_dev);
+
+	size_t pipe_count = count_other_pipes(drv);
+	dev->pipes = malloc(sizeof(usb_endpoint_mapping_t) * pipe_count);
+	if (dev->pipes == NULL) {
+		usb_log_oom(dev->ddf_dev);
+		return ENOMEM;
+	}
+
+	size_t i;
+
+	/* Initialize to NULL first for rollback purposes. */
+	for (i = 0; i < pipe_count; i++) {
+		dev->pipes[i].pipe = NULL;
+	}
+
+	for (i = 0; i < pipe_count; i++) {
+		dev->pipes[i].pipe = malloc(sizeof(usb_endpoint_pipe_t));
+		if (dev->pipes[i].pipe == NULL) {
+			usb_log_oom(dev->ddf_dev);
+			rc = ENOMEM;
+			goto rollback;
+		}
+
+		dev->pipes[i].description = drv->endpoints[i];
+		dev->pipes[i].interface_no = my_interface;
+	}
+
+	void *config_descriptor;
+	size_t config_descriptor_size;
+	rc = usb_request_get_full_configuration_descriptor_alloc(
+	    &dev->ctrl_pipe, 0, &config_descriptor, &config_descriptor_size);
+	if (rc != EOK) {
+		usb_log_error("Failed retrieving configuration of `%s': %s.\n",
+		    dev->ddf_dev->name, str_error(rc));
+		goto rollback;
+	}
+
+	rc = usb_endpoint_pipe_initialize_from_configuration(dev->pipes,
+	   pipe_count, config_descriptor, config_descriptor_size, &dev->wire);
+	if (rc != EOK) {
+		usb_log_error("Failed initializing USB endpoints: %s.\n",
+		    str_error(rc));
+		goto rollback;
+	}
+
+	/* Register the endpoints. */
+	usb_hc_connection_t hc_conn;
+	rc = usb_hc_connection_initialize_from_device(&hc_conn, dev->ddf_dev);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Failed initializing connection to host controller: %s.\n",
+		    str_error(rc));
+		goto rollback;
+	}
+	rc = usb_hc_connection_open(&hc_conn);
+	if (rc != EOK) {
+		usb_log_error("Failed to connect to host controller: %s.\n",
+		    str_error(rc));
+		goto rollback;
+	}
+	for (i = 0; i < pipe_count; i++) {
+		if (dev->pipes[i].present) {
+			rc = usb_endpoint_pipe_register(dev->pipes[i].pipe,
+			    dev->pipes[i].descriptor->poll_interval,
+			    &hc_conn);
+			/* Ignore error when operation not supported by HC. */
+			if ((rc != EOK) && (rc != ENOTSUP)) {
+				/* FIXME: what shall we do? */
+				dev->pipes[i].present = false;
+				free(dev->pipes[i].pipe);
+				dev->pipes[i].pipe = NULL;
+			}
+		}
+	}
+	/* Ignoring errors here. */
+	usb_hc_connection_close(&hc_conn);
+
+	return EOK;
+
+rollback:
+	for (i = 0; i < pipe_count; i++) {
+		if (dev->pipes[i].pipe != NULL) {
+			free(dev->pipes[i].pipe);
+		}
+	}
+	free(dev->pipes);
+
+	return rc;
+}
+
+/** Initialize all endpoint pipes.
+ *
+ * @param drv The driver.
+ * @param dev The device to be initialized.
+ * @return Error code.
+ */
+static int initialize_pipes(usb_driver_t *drv, usb_device_t *dev)
+{
+	int rc;
+
+	rc = usb_device_connection_initialize_from_device(&dev->wire,
+	    dev->ddf_dev);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Failed initializing connection on device `%s'. %s.\n",
+		    dev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	rc = usb_endpoint_pipe_initialize_default_control(&dev->ctrl_pipe,
+	    &dev->wire);
+	if (rc != EOK) {
+		usb_log_error("Failed to initialize default control pipe " \
+		    "on device `%s': %s.\n",
+		    dev->ddf_dev->name, str_error(rc));
+		return rc;
+	}
+
+	/*
+	 * Initialization of other pipes requires open session on
+	 * default control pipe.
+	 */
+	rc = usb_endpoint_pipe_start_session(&dev->ctrl_pipe);
+	if (rc != EOK) {
+		usb_log_error("Failed to start an IPC session: %s.\n",
+		    str_error(rc));
+		return rc;
+	}
+
+	if (driver->endpoints != NULL) {
+		rc = initialize_other_pipes(driver, dev);
+	}
+
+	/* No checking here. */
+	usb_endpoint_pipe_end_session(&dev->ctrl_pipe);
+
+	return rc;
+}
+
+/** Callback when new device is supposed to be controlled by this driver.
+ *
+ * This callback is a wrapper for USB specific version of @c add_device.
+ *
+ * @param gen_dev Device structure as prepared by DDF.
+ * @return Error code.
+ */
+int generic_add_device(ddf_dev_t *gen_dev)
+{
+	assert(driver);
+	assert(driver->ops);
+	assert(driver->ops->add_device);
+
+	int rc;
+
+	usb_device_t *dev = malloc(sizeof(usb_device_t));
+	if (dev == NULL) {
+		usb_log_error("Out of memory when adding device `%s'.\n",
+		    gen_dev->name);
+		return ENOMEM;
+	}
+
+
+	dev->ddf_dev = gen_dev;
+	dev->ddf_dev->driver_data = dev;
+	dev->driver_data = NULL;
+
+	rc = initialize_pipes(driver, dev);
+	if (rc != EOK) {
+		free(dev);
+		return rc;
+	}
+
+	return driver->ops->add_device(dev);
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/devpoll.c
===================================================================
--- uspace/lib/usb/src/devpoll.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
+++ uspace/lib/usb/src/devpoll.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * 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 libusb
+ * @{
+ */
+/** @file
+ * USB device driver framework - automatic interrupt polling.
+ */
+#include <usb/devdrv.h>
+#include <usb/request.h>
+#include <usb/debug.h>
+#include <errno.h>
+#include <str_error.h>
+#include <assert.h>
+
+/** Maximum number of failed consecutive requests before announcing failure. */
+#define MAX_FAILED_ATTEMPTS 3
+
+/** Data needed for polling. */
+typedef struct {
+	usb_device_t *dev;
+	size_t pipe_index;
+	usb_polling_callback_t callback;
+	usb_polling_terminted_callback_t terminated_callback;
+	size_t request_size;
+	uint8_t *buffer;
+	void *custom_arg;
+} polling_data_t;
+
+/** Polling fibril.
+ *
+ * @param arg Pointer to polling_data_t.
+ * @return Always EOK.
+ */
+static int polling_fibril(void *arg)
+{
+	polling_data_t *polling_data = (polling_data_t *) arg;
+	assert(polling_data);
+
+	usb_endpoint_pipe_t *pipe
+	    = polling_data->dev->pipes[polling_data->pipe_index].pipe;
+
+	size_t failed_attempts = 0;
+	while (failed_attempts < MAX_FAILED_ATTEMPTS) {
+		int rc;
+
+		rc = usb_endpoint_pipe_start_session(pipe);
+		if (rc != EOK) {
+			failed_attempts++;
+			continue;
+		}
+
+		size_t actual_size;
+		rc = usb_endpoint_pipe_read(pipe, polling_data->buffer,
+		    polling_data->request_size, &actual_size);
+
+		/* Quit the session regardless of errors. */
+		usb_endpoint_pipe_end_session(pipe);
+
+		if (rc != EOK) {
+			failed_attempts++;
+			continue;
+		}
+
+		/* We have the data, execute the callback now. */
+		bool carry_on = polling_data->callback(polling_data->dev,
+		    polling_data->buffer, actual_size,
+		    polling_data->custom_arg);
+
+		if (!carry_on) {
+			failed_attempts = 0;
+			break;
+		}
+
+		/* Reset as something might be only a temporary problem. */
+		failed_attempts = 0;
+	}
+
+	if (failed_attempts > 0) {
+		usb_log_error(
+		    "Polling of device `%s' terminated: recurring failures.\n",
+		    polling_data->dev->ddf_dev->name);
+	}
+
+	if (polling_data->terminated_callback != NULL) {
+		polling_data->terminated_callback(polling_data->dev,
+		    failed_attempts > 0, polling_data->custom_arg);
+	}
+
+	/* Free the allocated memory. */
+	free(polling_data->buffer);
+	free(polling_data);
+
+	return EOK;
+}
+
+/** Start automatic device polling over interrupt in pipe.
+ *
+ * @warning It is up to the callback to produce delays between individual
+ * requests.
+ *
+ * @warning There is no guarantee when the request to the device
+ * will be sent for the first time (it is possible that this
+ * first request would be executed prior to return from this function).
+ *
+ * @param dev Device to be periodically polled.
+ * @param pipe_index Index of the endpoint pipe used for polling.
+ * @param callback Callback when data are available.
+ * @param request_size How many bytes to ask for in each request.
+ * @param terminated_callback Callback when polling is terminated.
+ * @param arg Custom argument (passed as is to the callbacks).
+ * @return Error code.
+ * @retval EOK New fibril polling the device was already started.
+ */
+int usb_device_auto_poll(usb_device_t *dev, size_t pipe_index,
+    usb_polling_callback_t callback, size_t request_size,
+    usb_polling_terminted_callback_t terminated_callback, void *arg)
+{
+	if ((dev == NULL) || (callback == NULL)) {
+		return EBADMEM;
+	}
+	if (request_size == 0) {
+		return EINVAL;
+	}
+	if ((dev->pipes[pipe_index].pipe->transfer_type != USB_TRANSFER_INTERRUPT)
+	    || (dev->pipes[pipe_index].pipe->direction != USB_DIRECTION_IN)) {
+		return EINVAL;
+	}
+
+	polling_data_t *polling_data = malloc(sizeof(polling_data_t));
+	if (polling_data == NULL) {
+		return ENOMEM;
+	}
+
+	/* Allocate now to prevent immediate failure in the polling fibril. */
+	polling_data->buffer = malloc(request_size);
+	if (polling_data->buffer == NULL) {
+		free(polling_data);
+		return ENOMEM;
+	}
+	polling_data->dev = dev;
+	polling_data->pipe_index = pipe_index;
+	polling_data->callback = callback;
+	polling_data->terminated_callback = terminated_callback;
+	polling_data->request_size = request_size;
+	polling_data->custom_arg = arg;
+
+	fid_t fibril = fibril_create(polling_fibril, polling_data);
+	if (fibril == 0) {
+		free(polling_data->buffer);
+		free(polling_data);
+		/* FIXME: better error code. */
+		return ENOMEM;
+	}
+	fibril_add_ready(fibril);
+
+	/* The allocated buffer etc. will be freed by the fibril. */
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/lib/usb/src/pipesinit.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -38,4 +38,5 @@
 #include <usb/dp.h>
 #include <usb/request.h>
+#include <usbhc_iface.h>
 #include <errno.h>
 #include <assert.h>
@@ -393,4 +394,54 @@
 }
 
+/** Register endpoint with the host controller.
+ *
+ * @param pipe Pipe to be registered.
+ * @param interval Polling interval.
+ * @param hc_connection Connection to the host controller (must be opened).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_register(usb_endpoint_pipe_t *pipe,
+    unsigned int interval,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(pipe);
+	assert(hc_connection);
+
+	if (!usb_hc_connection_is_opened(hc_connection)) {
+		return EBADF;
+	}
+
+#define _PACK(high, low) ((high) * 256 + (low))
+
+	return async_req_5_0(hc_connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_REGISTER_ENDPOINT,
+	    _PACK(pipe->wire->address, pipe->endpoint_no),
+	    _PACK(pipe->transfer_type, pipe->direction),
+	    pipe->max_packet_size, interval);
+
+#undef _PACK
+}
+
+/** Revert endpoint registration with the host controller.
+ *
+ * @param pipe Pipe to be unregistered.
+ * @param hc_connection Connection to the host controller (must be opened).
+ * @return Error code.
+ */
+int usb_endpoint_pipe_unregister(usb_endpoint_pipe_t *pipe,
+    usb_hc_connection_t *hc_connection)
+{
+	assert(pipe);
+	assert(hc_connection);
+
+	if (!usb_hc_connection_is_opened(hc_connection)) {
+		return EBADF;
+	}
+
+	return async_req_4_0(hc_connection->hc_phone,
+	    DEV_IFACE_ID(USBHC_DEV_IFACE), IPC_M_USBHC_UNREGISTER_ENDPOINT,
+	    pipe->wire->address, pipe->endpoint_no, pipe->direction);
+}
+
 /**
  * @}
Index: uspace/lib/usb/src/recognise.c
===================================================================
--- uspace/lib/usb/src/recognise.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/lib/usb/src/recognise.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -374,5 +374,6 @@
 	 * naming etc., something more descriptive could be created.
 	 */
-	rc = asprintf(&child_name, "usbdev%02zu", this_device_name_index);
+	rc = asprintf(&child_name, "usb%02zu_a%d",
+	    this_device_name_index, address);
 	if (rc < 0) {
 		goto failure;
Index: uspace/srv/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 17ceb7293c4b3e05a924f81338db1e3c118dea83)
+++ uspace/srv/hw/irc/apic/apic.c	(revision 6298d806bfbee483788e8fa047dce6116a5deda6)
@@ -54,4 +54,6 @@
 #define NAME  "apic"
 
+static bool apic_found = false;
+
 static int apic_enable_irq(sysarg_t irq)
 {
@@ -79,5 +81,15 @@
 		callid = async_get_call(&call);
 		
-		switch (IPC_GET_IMETHOD(call)) {
+		sysarg_t method = IPC_GET_IMETHOD(call);
+		if (method == IPC_M_PHONE_HUNGUP) {
+			return;
+		}
+
+		if (!apic_found) {
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+
+		switch (method) {
 		case IRC_ENABLE_INTERRUPT:
 			async_answer_0(callid, apic_enable_irq(IPC_GET_ARG1(call)));
@@ -97,17 +109,15 @@
  *
  */
-static bool apic_init(void)
+static void apic_init(void)
 {
 	sysarg_t apic;
 	
-	if ((sysinfo_get_value("apic", &apic) != EOK) || (!apic)) {
-		printf(NAME ": No APIC found\n");
-		return false;
+	apic_found = sysinfo_get_value("apic", &apic) && apic;
+	if (!apic_found) {
+		printf(NAME ": Warning: no APIC found\n");
 	}
 	
 	async_set_client_connection(apic_connection);
 	service_register(SERVICE_APIC);
-	
-	return true;
 }
 
@@ -116,7 +126,6 @@
 	printf(NAME ": HelenOS APIC driver\n");
 	
-	if (!apic_init())
-		return -1;
-	
+	apic_init();
+
 	printf(NAME ": Accepting connections\n");
 	async_manager();
