Index: uspace/drv/bus/usb/usbhid/kbd.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,5 +1,0 @@
-/*
- * Dummy file because of shared layout sources.
- *
- * Do not delete.
- */
Index: uspace/drv/bus/usb/usbhid/kbd/layout.h
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/layout.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,1 +1,0 @@
-../layout.h
Index: uspace/drv/bus/usb/usbhid/kbd/main.c
===================================================================
--- uspace/drv/bus/usb/usbhid/kbd/main.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,244 +1,0 @@
-/*
- * Copyright (c) 2010 Vojtech Horky
- * Copyright (c) 2011 Lubos Slovak
- * 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 drvusbhid
- * @{
- */
-/**
- * @file
- * Main routines of USB KBD driver.
- */
-
-#include <ddf/driver.h>
-#include <usb/debug.h>
-#include <errno.h>
-#include <str_error.h>
-
-#include <usb/dev/driver.h>
-
-#include "kbddev.h"
-#include "kbdrepeat.h"
-
-/*----------------------------------------------------------------------------*/
-
-#define NAME "usbkbd"
-
-/**
- * Function for adding a new device of type USB/HID/keyboard.
- *
- * This functions initializes required structures from the device's descriptors
- * and starts new fibril for polling the keyboard for events and another one for
- * handling auto-repeat of keys.
- *
- * During initialization, the keyboard is switched into boot protocol, the idle
- * rate is set to 0 (infinity), resulting in the keyboard only reporting event
- * when a key is pressed or released. Finally, the LED lights are turned on 
- * according to the default setup of lock keys.
- *
- * @note By default, the keyboards is initialized with Num Lock turned on and 
- *       other locks turned off.
- * @note Currently supports only boot-protocol keyboards.
- *
- * @param dev Device to add.
- *
- * @retval EOK if successful.
- * @retval ENOMEM if there
- * @return Other error code inherited from one of functions usb_kbd_init(),
- *         ddf_fun_bind() and ddf_fun_add_to_class().
- *
- * @sa usb_kbd_fibril(), usb_kbd_repeat_fibril()
- */
-static int usb_kbd_try_add_device(usb_device_t *dev)
-{
-	/* Create the function exposed under /dev/devices. */
-	ddf_fun_t *kbd_fun = ddf_fun_create(dev->ddf_dev, fun_exposed, 
-	    "keyboard");
-	if (kbd_fun == NULL) {
-		usb_log_error("Could not create DDF function node.\n");
-		return ENOMEM;
-	}
-	
-	/* 
-	 * Initialize device (get and process descriptors, get address, etc.)
-	 */
-	usb_log_debug("Initializing USB/HID KBD device...\n");
-	
-	usb_kbd_t *kbd_dev = usb_kbd_new();
-	if (kbd_dev == NULL) {
-		usb_log_error("Error while creating USB/HID KBD device "
-		    "structure.\n");
-		ddf_fun_destroy(kbd_fun);
-		return ENOMEM;  // TODO: some other code??
-	}
-	
-	int rc = usb_kbd_init(kbd_dev, dev);
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to initialize USB/HID KBD device.\n");
-		ddf_fun_destroy(kbd_fun);
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}	
-	
-	usb_log_debug("USB/HID KBD device structure initialized.\n");
-	
-	/*
-	 * Store the initialized keyboard device and keyboard ops
-	 * to the DDF function.
-	 */
-	kbd_fun->driver_data = kbd_dev;
-	kbd_fun->ops = &keyboard_ops;
-
-	rc = ddf_fun_bind(kbd_fun);
-	if (rc != EOK) {
-		usb_log_error("Could not bind DDF function: %s.\n",
-		    str_error(rc));
-		// TODO: Can / should I destroy the DDF function?
-		ddf_fun_destroy(kbd_fun);
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	rc = ddf_fun_add_to_class(kbd_fun, "keyboard");
-	if (rc != EOK) {
-		usb_log_error(
-		    "Could not add DDF function to class 'keyboard': %s.\n",
-		    str_error(rc));
-		ddf_fun_destroy(kbd_fun);
-		usb_kbd_free(&kbd_dev);
-		return rc;
-	}
-	
-	/* Start automated polling function.
-	 * This will create a separate fibril that will query the device
-	 * for the data continuously 
-	 */
-       rc = usb_device_auto_poll(dev,
-	   /* Index of the polling pipe. */
-	   USB_KBD_POLL_EP_NO,
-	   /* Callback when data arrives. */
-	   usb_kbd_polling_callback,
-	   /* How much data to request. */
-	   dev->pipes[USB_KBD_POLL_EP_NO].pipe->max_packet_size,
-	   /* Callback when the polling ends. */
-	   usb_kbd_polling_ended_callback,
-	   /* Custom argument. */
-	   kbd_dev);
-	
-	
-	if (rc != EOK) {
-		usb_log_error("Failed to start polling fibril for `%s'.\n",
-		    dev->ddf_dev->name);
-		return rc;
-	}
-	
-	/*
-	 * Create new fibril for auto-repeat
-	 */
-	fid_t fid = fibril_create(usb_kbd_repeat_fibril, kbd_dev);
-	if (fid == 0) {
-		usb_log_error("Failed to start fibril for KBD auto-repeat");
-		return ENOMEM;
-	}
-	fibril_add_ready(fid);
-
-	(void)keyboard_ops;
-
-	/*
-	 * Hurrah, device is initialized.
-	 */
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Callback for passing a new device to the driver.
- *
- * @note Currently, only boot-protocol keyboards are supported by this driver.
- *
- * @param dev Structure representing the new device.
- *
- * @retval EOK if successful. 
- * @retval EREFUSED if the device is not supported.
- */
-static int usb_kbd_add_device(usb_device_t *dev)
-{
-	usb_log_debug("usb_kbd_add_device()\n");
-	
-	if (dev->interface_no < 0) {
-		usb_log_warning("Device is not a supported keyboard.\n");
-		usb_log_error("Failed to add USB KBD device: endpoint not "
-		    "found.\n");
-		return ENOTSUP;
-	}
-	
-	int rc = usb_kbd_try_add_device(dev);
-	
-	if (rc != EOK) {
-		usb_log_warning("Device is not a supported keyboard.\n");
-		usb_log_error("Failed to add KBD device: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	
-	usb_log_info("Keyboard `%s' ready to use.\n", dev->ddf_dev->name);
-
-	return EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-/* Currently, the framework supports only device adding. Once the framework
- * supports unplug, more callbacks will be added. */
-static usb_driver_ops_t usb_kbd_driver_ops = {
-        .add_device = usb_kbd_add_device,
-};
-
-
-/* The driver itself. */
-static usb_driver_t usb_kbd_driver = {
-        .name = NAME,
-        .ops = &usb_kbd_driver_ops,
-        .endpoints = usb_kbd_endpoints
-};
-
-/*----------------------------------------------------------------------------*/
-
-int main(int argc, char *argv[])
-{
-	printf(NAME ": HelenOS USB KBD driver.\n");
-
-	usb_log_enable(USB_LOG_LEVEL_DEBUG, NAME);
-
-	return usb_driver_main(&usb_kbd_driver);
-}
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbhid/layout.h
===================================================================
--- uspace/drv/bus/usb/usbhid/layout.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2009 Jiri Svoboda
- * Copyright (c) 2011 Lubos Slovak 
- * (copied from /uspace/srv/hid/kbd/include/layout.h)
- * 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 drvusbhid
- * @{
- */
-/** @file
- * Keyboard layout.
- */
-
-#ifndef USB_HID_LAYOUT_H_
-#define USB_HID_LAYOUT_H_
-
-#include <sys/types.h>
-#include <io/console.h>
-
-typedef struct {
-	void (*reset)(void);
-	wchar_t (*parse_ev)(kbd_event_t *);
-} layout_op_t;
-
-extern layout_op_t us_qwerty_op;
-extern layout_op_t us_dvorak_op;
-extern layout_op_t cz_op;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbhub/Makefile
===================================================================
--- uspace/drv/bus/usb/usbhub/Makefile	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/drv/bus/usb/usbhub/Makefile	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -1,4 +1,5 @@
 #
 # Copyright (c) 2010 Vojtech Horky
+# Copyright (c) 2011 Jan Vesely
 # All rights reserved.
 #
@@ -43,7 +44,6 @@
 SOURCES = \
 	main.c \
-	utils.c \
 	usbhub.c \
-	ports.c
+	port.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/bus/usb/usbhub/main.c
===================================================================
--- uspace/drv/bus/usb/usbhub/main.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/drv/bus/usb/usbhub/main.c	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -38,7 +39,7 @@
 #include <usb/dev/driver.h>
 #include <usb/classes/classes.h>
+#include <usb/debug.h>
 
 #include "usbhub.h"
-#include "usbhub_private.h"
 
 /** Hub status-change endpoint description.
@@ -56,5 +57,5 @@
 
 /**
- * usb hub driver operations
+ * USB hub driver operations
  *
  * The most important one is add_device, which is set to usb_hub_add_device.
@@ -64,15 +65,10 @@
 };
 
-/**
- * hub endpoints, excluding control endpoint
- */
+/** Hub endpoints, excluding control endpoint. */
 static usb_endpoint_description_t *usb_hub_endpoints[] = {
 	&hub_status_change_endpoint_description,
-	NULL
+	NULL,
 };
-
-/**
- * static usb hub driver information
- */
+/** Static usb hub driver information. */
 static usb_driver_t usb_hub_driver = {
 	.name = NAME,
@@ -85,5 +81,4 @@
 {
 	printf(NAME ": HelenOS USB hub driver.\n");
-
 	usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
 
@@ -94,3 +89,2 @@
  * @}
  */
-
Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * Hub ports functions.
+ */
+
+#include <bool.h>
+#include <devman.h>
+#include <errno.h>
+#include <str_error.h>
+#include <inttypes.h>
+#include <fibril_synch.h>
+
+#include <usb/debug.h>
+#include <usb/dev/hub.h>
+
+#include "port.h"
+#include "usbhub.h"
+#include "status.h"
+
+/** Information for fibril for device discovery. */
+struct add_device_phase1 {
+	usb_hub_info_t *hub;
+	usb_hub_port_t *port;
+	usb_speed_t speed;
+};
+
+static void usb_hub_port_removed_device(usb_hub_port_t *port,
+    usb_hub_info_t *hub);
+static void usb_hub_port_reset_completed(usb_hub_port_t *port,
+    usb_port_status_t status);
+static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status);
+static int enable_port_callback(int port_no, void *arg);
+static int add_device_phase1_worker_fibril(void *arg);
+static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_info_t *hub,
+    usb_speed_t speed);
+
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+int usb_hub_port_clear_feature(
+    usb_hub_port_t *port, usb_hub_class_feature_t feature)
+{
+	assert(port);
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
+		.request = USB_DEVREQ_CLEAR_FEATURE,
+		.value = feature,
+		.index = port->port_number,
+		.length = 0,
+	};
+	return usb_pipe_control_write(port->control_pipe, &clear_request,
+	    sizeof(clear_request), NULL, 0);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Clear feature on hub port.
+ *
+ * @param hc Host controller telephone
+ * @param address Hub address
+ * @param port_index Port
+ * @param feature Feature selector
+ * @return Operation result
+ */
+int usb_hub_port_set_feature(
+    usb_hub_port_t *port, usb_hub_class_feature_t feature)
+{
+	assert(port);
+	usb_device_request_setup_packet_t clear_request = {
+		.request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
+		.request = USB_DEVREQ_SET_FEATURE,
+		.index = port->port_number,
+		.value = feature,
+		.length = 0,
+	};
+	return usb_pipe_control_write(port->control_pipe, &clear_request,
+	    sizeof(clear_request), NULL, 0);
+}
+/*----------------------------------------------------------------------------*/
+void usb_hub_port_reset_fail(usb_hub_port_t *port)
+{
+	assert(port);
+	fibril_mutex_lock(&port->mutex);
+	port->reset_completed = true;
+	port->reset_okay = false;
+	fibril_condvar_broadcast(&port->reset_cv);
+	fibril_mutex_unlock(&port->mutex);
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process interrupts on given hub port
+ *
+ * Accepts connection, over current and port reset change.
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub)
+{
+	assert(port);
+	assert(hub);
+	usb_log_debug("Interrupt at port %zu\n", port->port_number);
+
+	usb_port_status_t status;
+	const int opResult = get_port_status(port, &status);
+	if (opResult != EOK) {
+		usb_log_error("Failed to get port %zu status: %s.\n",
+		    port->port_number, str_error(opResult));
+		return;
+	}
+
+	/* Connection change */
+	if (status & USB_HUB_PORT_C_STATUS_CONNECTION) {
+		const bool connected =
+		    (status & USB_HUB_PORT_STATUS_CONNECTION) != 0;
+		usb_log_debug("Connection change on port %zu: device %s.\n",
+		    port->port_number, connected ? "attached" : "removed");
+
+		/* ACK the change */
+		const int opResult = usb_hub_port_clear_feature(port,
+		    USB_HUB_FEATURE_C_PORT_CONNECTION);
+		if (opResult != EOK) {
+			usb_log_warning("Failed to clear port-change-connection"
+			    " flag: %s.\n", str_error(opResult));
+		}
+
+		if (connected) {
+			const int opResult = create_add_device_fibril(port, hub,
+			    usb_port_speed(status));
+			if (opResult != EOK) {
+				usb_log_error(
+				    "Cannot handle change on port %zu: %s.\n",
+				    port->port_number, str_error(opResult));
+			}
+		} else {
+			/* If enabled change was reported leave the removal
+			 * to that handler, it shall ACK the change too. */
+			if (!(status & USB_HUB_PORT_C_STATUS_ENABLED)) {
+				usb_hub_port_removed_device(port, hub);
+			}
+		}
+	}
+
+	/* Enable change, ports are automatically disabled on errors. */
+	if (status & USB_HUB_PORT_C_STATUS_ENABLED) {
+		usb_log_info("Port %zu, disabled because of errors.\n",
+		   port->port_number);
+		usb_hub_port_removed_device(port, hub);
+		const int rc = usb_hub_port_clear_feature(port,
+		        USB_HUB_FEATURE_C_PORT_ENABLE);
+		if (rc != EOK) {
+			usb_log_error(
+			    "Failed to clear port %zu enable change feature: "
+			    "%s.\n", port->port_number, str_error(rc));
+		}
+
+	}
+
+	/* Suspend change */
+	if (status & USB_HUB_PORT_C_STATUS_SUSPEND) {
+		usb_log_error("Port %zu went to suspend state, this should"
+		    "NOT happen as we do not support suspend state!",
+		    port->port_number);
+		const int rc = usb_hub_port_clear_feature(port,
+		        USB_HUB_FEATURE_C_PORT_SUSPEND);
+		if (rc != EOK) {
+			usb_log_error(
+			    "Failed to clear port %zu suspend change feature: "
+			    "%s.\n", port->port_number, str_error(rc));
+		}
+	}
+
+	/* Over current */
+	if (status & USB_HUB_PORT_C_STATUS_OC) {
+		/* According to the USB specs:
+		 * 11.13.5 Over-current Reporting and Recovery
+		 * Hub device is responsible for putting port in power off
+		 * mode. USB system software is responsible for powering port
+		 * back on when the over-current condition is gone */
+		const int rc = usb_hub_port_clear_feature(port,
+		    USB_HUB_FEATURE_C_PORT_OVER_CURRENT);
+		if (rc != EOK) {
+			usb_log_error(
+			    "Failed to clear port %zu OC change feature: %s.\n",
+			    port->port_number, str_error(rc));
+		}
+		if (!(status & ~USB_HUB_PORT_STATUS_OC)) {
+			const int rc = usb_hub_port_set_feature(
+			    port, USB_HUB_FEATURE_PORT_POWER);
+			if (rc != EOK) {
+				usb_log_error(
+				    "Failed to set port %d power after OC:"
+				    " %s.\n", port->port_number, str_error(rc));
+			}
+		}
+	}
+
+	/* Port reset, set on port reset complete. */
+	if (status & USB_HUB_PORT_C_STATUS_RESET) {
+		usb_hub_port_reset_completed(port, status);
+	}
+
+	usb_log_debug("Port %zu status 0x%08" PRIx32 "\n",
+	    port->port_number, status);
+}
+
+/**
+ * routine called when a device on port has been removed
+ *
+ * If the device on port had default address, it releases default address.
+ * Otherwise does not do anything, because DDF does not allow to remove device
+ * from it`s device tree.
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+static void usb_hub_port_removed_device(usb_hub_port_t *port,
+    usb_hub_info_t *hub)
+{
+	assert(port);
+	assert(hub);
+	if (port->attached_device.address >= 0) {
+		fibril_mutex_lock(&port->mutex);
+		port->attached_device.address = -1;
+		port->attached_device.handle = 0;
+		fibril_mutex_unlock(&port->mutex);
+		usb_log_info("Removed device on port %zu.\n",
+		    port->port_number);
+	} else {
+		usb_log_warning(
+		    "Device on port %zu removed before being registered.\n",
+		    port->port_number);
+
+		/*
+		 * Device was removed before port reset completed.
+		 * We will announce a failed port reset to unblock the
+		 * port reset callback from new device wrapper.
+		 */
+		usb_hub_port_reset_fail(port);
+	}
+}
+
+/**
+ * Process port reset change
+ *
+ * After this change port should be enabled, unless some problem occurred.
+ * This functions triggers second phase of enabling new device.
+ * @param hub
+ * @param port
+ * @param status
+ */
+static void usb_hub_port_reset_completed(usb_hub_port_t *port,
+    usb_port_status_t status)
+{
+	assert(port);
+	fibril_mutex_lock(&port->mutex);
+	/* Finalize device adding. */
+	port->reset_completed = true;
+	port->reset_okay = (status & USB_HUB_PORT_STATUS_ENABLED) != 0;
+
+	if (port->reset_okay) {
+		usb_log_debug("Port %zu reset complete.\n", port->port_number);
+	} else {
+		usb_log_warning(
+		    "Port %zu reset complete but port not enabled.\n",
+		    port->port_number);
+	}
+	fibril_condvar_broadcast(&port->reset_cv);
+	fibril_mutex_unlock(&port->mutex);
+
+	/* Clear the port reset change. */
+	int rc = usb_hub_port_clear_feature(port, USB_HUB_FEATURE_C_PORT_RESET);
+	if (rc != EOK) {
+		usb_log_error(
+		    "Failed to clear port %d reset change feature: %s.\n",
+		    port->port_number, str_error(rc));
+	}
+}
+/*----------------------------------------------------------------------------*/
+/** Retrieve port status.
+ *
+ * @param[in] ctrl_pipe Control pipe to use.
+ * @param[in] port Port number (starting at 1).
+ * @param[out] status Where to store the port status.
+ * @return Error code.
+ */
+static int get_port_status(usb_hub_port_t *port, usb_port_status_t *status)
+{
+	assert(port);
+	/* USB hub specific GET_PORT_STATUS request. See USB Spec 11.16.2.6
+	 * Generic GET_STATUS request cannot be used because of the difference
+	 * in status data size (2B vs. 4B)*/
+	const usb_device_request_setup_packet_t request = {
+		.request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS,
+		.request = USB_HUB_REQUEST_GET_STATUS,
+		.value = 0,
+		.index = port->port_number,
+		.length = sizeof(usb_port_status_t),
+	};
+	size_t recv_size;
+	usb_port_status_t status_tmp;
+
+	const int rc = usb_pipe_control_read(port->control_pipe,
+	    &request, sizeof(usb_device_request_setup_packet_t),
+	    &status_tmp, sizeof(status_tmp), &recv_size);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	if (recv_size != sizeof (status_tmp)) {
+		return ELIMIT;
+	}
+
+	if (status != NULL) {
+		*status = status_tmp;
+	}
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
+/** Callback for enabling a specific port.
+ *
+ * We wait on a CV until port is reseted.
+ * That is announced via change on interrupt pipe.
+ *
+ * @param port_no Port number (starting at 1).
+ * @param arg Custom argument, points to @c usb_hub_info_t.
+ * @return Error code.
+ */
+static int enable_port_callback(int port_no, void *arg)
+{
+	usb_hub_port_t *port = arg;
+	const int rc =
+	    usb_hub_port_set_feature(port, USB_HUB_FEATURE_PORT_RESET);
+	if (rc != EOK) {
+		usb_log_warning("Port reset failed: %s.\n", str_error(rc));
+		return rc;
+	}
+
+	/*
+	 * Wait until reset completes.
+	 */
+	fibril_mutex_lock(&port->mutex);
+	while (!port->reset_completed) {
+		fibril_condvar_wait(&port->reset_cv, &port->mutex);
+	}
+	fibril_mutex_unlock(&port->mutex);
+
+	if (port->reset_okay) {
+		return EOK;
+	} else {
+		return ESTALL;
+	}
+}
+
+/** Fibril for adding a new device.
+ *
+ * Separate fibril is needed because the port reset completion is announced
+ * via interrupt pipe and thus we cannot block here.
+ *
+ * @param arg Pointer to struct add_device_phase1.
+ * @return 0 Always.
+ */
+static int add_device_phase1_worker_fibril(void *arg)
+{
+	struct add_device_phase1 *data = arg;
+	assert(data);
+
+	usb_address_t new_address;
+	devman_handle_t child_handle;
+
+	const int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
+	    &data->hub->connection, data->speed,
+	    enable_port_callback, (int) data->port->port_number,
+	    data->port, &new_address, &child_handle,
+	    NULL, NULL, NULL);
+
+	if (rc != EOK) {
+		usb_log_error("Failed registering device on port %zu: %s.\n",
+		    data->port->port_number, str_error(rc));
+		goto leave;
+	}
+
+	fibril_mutex_lock(&data->port->mutex);
+	data->port->attached_device.handle = child_handle;
+	data->port->attached_device.address = new_address;
+	fibril_mutex_unlock(&data->port->mutex);
+
+	usb_log_info("Detected new device on `%s' (port %zu), "
+	    "address %d (handle %" PRIun ").\n",
+	    data->hub->usb_device->ddf_dev->name, data->port->port_number,
+	    new_address, child_handle);
+
+leave:
+	fibril_mutex_lock(&data->hub->pending_ops_mutex);
+	assert(data->hub->pending_ops_count > 0);
+	--data->hub->pending_ops_count;
+	fibril_condvar_signal(&data->hub->pending_ops_cv);
+	fibril_mutex_unlock(&data->hub->pending_ops_mutex);
+
+	free(arg);
+
+	return EOK;
+}
+
+/** Start device adding when connection change is detected.
+ *
+ * This fires a new fibril to complete the device addition.
+ *
+ * @param hub Hub where the change occured.
+ * @param port Port index (starting at 1).
+ * @param speed Speed of the device.
+ * @return Error code.
+ */
+static int create_add_device_fibril(usb_hub_port_t *port, usb_hub_info_t *hub,
+    usb_speed_t speed)
+{
+	assert(hub);
+	assert(port);
+	struct add_device_phase1 *data
+	    = malloc(sizeof (struct add_device_phase1));
+	if (data == NULL) {
+		return ENOMEM;
+	}
+	data->hub = hub;
+	data->port = port;
+	data->speed = speed;
+
+	fibril_mutex_lock(&port->mutex);
+	port->reset_completed = false;
+	fibril_mutex_unlock(&port->mutex);
+
+	fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
+	if (fibril == 0) {
+		free(data);
+		return ENOMEM;
+	}
+	fibril_mutex_lock(&hub->pending_ops_mutex);
+	++hub->pending_ops_count;
+	fibril_mutex_unlock(&hub->pending_ops_mutex);
+	fibril_add_ready(fibril);
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/port.h
===================================================================
--- uspace/drv/bus/usb/usbhub/port.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
+++ uspace/drv/bus/usb/usbhub/port.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvusbhub
+ * @{
+ */
+/** @file
+ * Hub ports related functions.
+ */
+#ifndef DRV_USBHUB_PORT_H
+#define DRV_USBHUB_PORT_H
+
+#include <usb/dev/driver.h>
+#include <usb/dev/hub.h>
+#include <usb/classes/hub.h>
+
+typedef struct usb_hub_info_t usb_hub_info_t;
+
+/** Information about single port on a hub. */
+typedef struct {
+	size_t port_number;
+	usb_pipe_t *control_pipe;
+	/** Mutex needed not only by CV for checking port reset. */
+	fibril_mutex_t mutex;
+	/** CV for waiting to port reset completion. */
+	fibril_condvar_t reset_cv;
+	/** Whether port reset is completed.
+	 * Guarded by @c reset_mutex.
+	 */
+	bool reset_completed;
+	/** Whether to announce the port reset as successful. */
+	bool reset_okay;
+
+	/** Information about attached device. */
+	usb_hc_attached_device_t attached_device;
+} usb_hub_port_t;
+
+/** Initialize hub port information.
+ *
+ * @param port Port to be initialized.
+ */
+static inline void usb_hub_port_init(usb_hub_port_t *port, size_t port_number,
+    usb_pipe_t *control_pipe)
+{
+	assert(port);
+	port->attached_device.address = -1;
+	port->attached_device.handle = 0;
+	port->port_number = port_number;
+	port->control_pipe = control_pipe;
+	fibril_mutex_initialize(&port->mutex);
+	fibril_condvar_initialize(&port->reset_cv);
+}
+
+void usb_hub_port_reset_fail(usb_hub_port_t *port);
+void usb_hub_port_process_interrupt(usb_hub_port_t *port, usb_hub_info_t *hub);
+int usb_hub_port_clear_feature(
+    usb_hub_port_t *port, usb_hub_class_feature_t feature);
+int usb_hub_port_set_feature(
+    usb_hub_port_t *port, usb_hub_class_feature_t feature);
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/port_status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/port_status.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,360 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-
-#ifndef HUB_PORT_STATUS_H
-#define	HUB_PORT_STATUS_H
-
-#include <bool.h>
-#include <sys/types.h>
-#include <usb/dev/request.h>
-#include "usbhub_private.h"
-
-/**
- * structure holding port status and changes flags.
- * should not be accessed directly, use supplied getter/setter methods.
- *
- * For more information refer to table 11-15 in
- * "Universal Serial Bus Specification Revision 1.1"
- *
- */
-typedef uint32_t usb_port_status_t;
-
-/**
- * structure holding hub status and changes flags.
- * should not be accessed directly, use supplied getter/setter methods.
- *
- * For more information refer to table 11.16.2.5 in
- * "Universal Serial Bus Specification Revision 1.1"
- *
- */
-typedef uint32_t usb_hub_status_t;
-
-/**
- * set values in request to be it a port status request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_port_status_request(
-    usb_device_request_setup_packet_t *request, uint16_t port) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
-	request->request = USB_HUB_REQUEST_GET_STATUS;
-	request->value = 0;
-	request->length = 4;
-}
-
-/**
- * set values in request to be it a port status request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_hub_status_request(
-    usb_device_request_setup_packet_t *request) {
-	request->index = 0;
-	request->request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS;
-	request->request = USB_HUB_REQUEST_GET_STATUS;
-	request->value = 0;
-	request->length = 4;
-}
-
-/**
- * create request for usb hub port status
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_port_status_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_port_status_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port feature enable request
- * @param request
- * @param port
- * @param feature_selector
- */
-static inline void usb_hub_set_enable_port_feature_request(
-    usb_device_request_setup_packet_t *request, uint16_t port,
-    uint16_t feature_selector) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = feature_selector;
-	request->length = 0;
-}
-
-/**
- * set the device request to be a port feature clear request
- * @param request
- * @param port
- * @param feature_selector
- */
-static inline void usb_hub_set_disable_port_feature_request(
-    usb_device_request_setup_packet_t *request, uint16_t port,
-    uint16_t feature_selector
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
-	request->value = feature_selector;
-	request->length = 0;
-}
-
-/**
- * set the device request to be a port enable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_enable_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_C_PORT_ENABLE;
-	request->length = 0;
-}
-
-/**
- * enable specified port
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_enable_port_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_enable_port_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_disable_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_C_PORT_SUSPEND;
-	request->length = 0;
-}
-
-/**
- * disable specified port
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_disable_port_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_disable_port_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_reset_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_PORT_RESET;
-	request->length = 0;
-}
-
-/**
- * disable specified port
- * @param port
- * @return
- */
-static inline usb_device_request_setup_packet_t *
-usb_hub_create_reset_port_request(uint16_t port) {
-	usb_device_request_setup_packet_t *result =
-	    malloc(sizeof (usb_device_request_setup_packet_t));
-	usb_hub_set_reset_port_request(result, port);
-	return result;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_set_power_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_SET_FEATURE;
-	request->value = USB_HUB_FEATURE_PORT_POWER;
-	request->length = 0;
-}
-
-/**
- * set the device request to be a port disable request
- * @param request
- * @param port
- */
-static inline void usb_hub_unset_power_port_request(
-    usb_device_request_setup_packet_t *request, uint16_t port
-    ) {
-	request->index = port;
-	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
-	request->request = USB_HUB_REQUEST_CLEAR_FEATURE;
-	request->value = USB_HUB_FEATURE_PORT_POWER;
-	request->length = 0;
-}
-
-/**
- * get i`th bit of port status
- * 
- * @param status
- * @param idx
- * @return
- */
-static inline bool usb_port_is_status(usb_port_status_t status, int idx) {
-	return (status & (1 << idx)) != 0;
-}
-
-/**
- * set i`th bit of port status
- * 
- * @param status
- * @param idx
- * @param value
- */
-static inline void usb_port_status_set_bit(
-    usb_port_status_t * status, int idx, bool value) {
-	(*status) = value ?
-	    ((*status) | (1 << (idx))) :
-	    ((*status)&(~(1 << (idx))));
-}
-
-/**
- * get i`th bit of hub status
- * 
- * @param status
- * @param idx
- * @return
- */
-static inline bool usb_hub_is_status(usb_hub_status_t status, int idx) {
-	return (status & (1 << idx)) != 0;
-}
-
-/**
- * set i`th bit of hub status
- * 
- * @param status
- * @param idx
- * @param value
- */
-static inline void usb_hub_status_set_bit(
-    usb_hub_status_t *status, int idx, bool value) {
-	(*status) = value ?
-	    ((*status) | (1 << (idx))) :
-	    ((*status)&(~(1 << (idx))));
-}
-
-/**
- * low speed device on the port indicator
- * 
- * @param status
- * @return true if low speed device is attached
- */
-static inline bool usb_port_low_speed(usb_port_status_t status) {
-	return usb_port_is_status(status, 9);
-}
-
-/**
- * set low speed device connected bit in port status
- * 
- * @param status
- * @param low_speed value of the bit
- */
-static inline void usb_port_set_low_speed(usb_port_status_t *status, bool low_speed) {
-	usb_port_status_set_bit(status, 9, low_speed);
-}
-
-//high speed device attached
-
-/**
- * high speed device on the port indicator
- *
- * @param status
- * @return true if high speed device is on port
- */
-static inline bool usb_port_high_speed(usb_port_status_t status) {
-	return usb_port_is_status(status, 10);
-}
-
-/**
- * set high speed device bit in port status
- *
- * @param status
- * @param high_speed value of the bit
- */
-static inline void usb_port_set_high_speed(usb_port_status_t *status, bool high_speed) {
-	usb_port_status_set_bit(status, 10, high_speed);
-}
-
-/**
- * speed getter for port status
- *
- * @param status
- * @return speed of usb device (for more see usb specification)
- */
-static inline usb_speed_t usb_port_speed(usb_port_status_t status) {
-	if (usb_port_low_speed(status))
-		return USB_SPEED_LOW;
-	if (usb_port_high_speed(status))
-		return USB_SPEED_HIGH;
-	return USB_SPEED_FULL;
-}
-
-
-
-#endif	/* HUB_PORT_STATUS_H */
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbhub/ports.c
===================================================================
--- uspace/drv/bus/usb/usbhub/ports.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,465 +1,0 @@
-/*
- * 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 drvusbhub
- * @{
- */
-/** @file
- * Hub ports functions.
- */
-
-#include <bool.h>
-#include <errno.h>
-#include <str_error.h>
-#include <inttypes.h>
-#include <fibril_synch.h>
-
-#include <usb/debug.h>
-
-#include "ports.h"
-#include "usbhub.h"
-#include "usbhub_private.h"
-#include "port_status.h"
-
-/** Information for fibril for device discovery. */
-struct add_device_phase1 {
-	usb_hub_info_t *hub;
-	size_t port;
-	usb_speed_t speed;
-};
-
-/**
- * count of port status changes that are not explicitly handled by
- * any function here and must be cleared by hand
- */
-static const unsigned int non_handled_changes_count = 2;
-
-/**
- * port status changes that are not explicitly handled by
- * any function here and must be cleared by hand
- */
-static const int non_handled_changes[] = {
-	USB_HUB_FEATURE_C_PORT_ENABLE,
-	USB_HUB_FEATURE_C_PORT_SUSPEND
-};
-
-static void usb_hub_removed_device(
-    usb_hub_info_t *hub, uint16_t port);
-
-static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status);
-
-static void usb_hub_port_over_current(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status);
-
-static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
-    usb_port_status_t *status);
-
-static int enable_port_callback(int port_no, void *arg);
-
-static int add_device_phase1_worker_fibril(void *arg);
-
-static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
-    usb_speed_t speed);
-
-/**
- * Process interrupts on given hub port
- *
- * Accepts connection, over current and port reset change.
- * @param hub hub representation
- * @param port port number, starting from 1
- */
-void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
-    uint16_t port) {
-	usb_log_debug("Interrupt at port %zu\n", (size_t) port);
-	//determine type of change
-	//usb_pipe_t *pipe = hub->control_pipe;
-
-	int opResult;
-
-	usb_port_status_t status;
-	opResult = get_port_status(&hub->usb_device->ctrl_pipe, port, &status);
-	if (opResult != EOK) {
-		usb_log_error("Failed to get port %zu status: %s.\n",
-		    (size_t) port, str_error(opResult));
-		return;
-	}
-	//connection change
-	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_CONNECTION)) {
-		bool device_connected = usb_port_is_status(status,
-		    USB_HUB_FEATURE_PORT_CONNECTION);
-		usb_log_debug("Connection change on port %zu: %s.\n",
-		    (size_t) port,
-		    device_connected ? "device attached" : "device removed");
-
-		if (device_connected) {
-			opResult = create_add_device_fibril(hub, port,
-			    usb_port_speed(status));
-			if (opResult != EOK) {
-				usb_log_error(
-				    "Cannot handle change on port %zu: %s.\n",
-				    (size_t) port, str_error(opResult));
-			}
-		} else {
-			usb_hub_removed_device(hub, port);
-		}
-	}
-	//over current
-	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT)) {
-		//check if it was not auto-resolved
-		usb_log_debug("Overcurrent change on port\n");
-		usb_hub_port_over_current(hub, port, status);
-	}
-	//port reset
-	if (usb_port_is_status(status, USB_HUB_FEATURE_C_PORT_RESET)) {
-		usb_hub_port_reset_completed(hub, port, status);
-	}
-	usb_log_debug("Port %d status 0x%08" PRIx32 "\n", (int) port, status);
-
-	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_C_PORT_CONNECTION, false);
-	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_C_PORT_RESET, false);
-	usb_port_status_set_bit(
-	    &status, USB_HUB_FEATURE_C_PORT_OVER_CURRENT, false);
-
-	//clearing not yet handled changes	
-	unsigned int feature_idx;
-	for (feature_idx = 0;
-	    feature_idx < non_handled_changes_count;
-	    ++feature_idx) {
-		unsigned int bit_idx = non_handled_changes[feature_idx];
-		if (status & (1 << bit_idx)) {
-			usb_log_info(
-			    "There was not yet handled change on port %d: %d"
-			    ";clearing it\n",
-			    port, bit_idx);
-			int opResult = usb_hub_clear_port_feature(
-			    hub->control_pipe,
-			    port, bit_idx);
-			if (opResult != EOK) {
-				usb_log_warning(
-				    "Could not clear port flag %d: %s\n",
-				    bit_idx, str_error(opResult)
-				    );
-			}
-			usb_port_status_set_bit(
-			    &status, bit_idx, false);
-		}
-	}
-	if (status >> 16) {
-		usb_log_info("There is still some unhandled change %X\n",
-		    status);
-	}
-}
-
-/**
- * routine called when a device on port has been removed
- *
- * If the device on port had default address, it releases default address.
- * Otherwise does not do anything, because DDF does not allow to remove device
- * from it`s device tree.
- * @param hub hub representation
- * @param port port number, starting from 1
- */
-static void usb_hub_removed_device(
-    usb_hub_info_t *hub, uint16_t port) {
-
-	int opResult = usb_hub_clear_port_feature(hub->control_pipe,
-	    port, USB_HUB_FEATURE_C_PORT_CONNECTION);
-	if (opResult != EOK) {
-		usb_log_warning("Could not clear port-change-connection flag\n");
-	}
-	/** \TODO remove device from device manager - not yet implemented in
-	 * devide manager
-	 */
-
-	//close address
-
-	usb_hub_port_t *the_port = hub->ports + port;
-
-	fibril_mutex_lock(&hub->port_mutex);
-
-	if (the_port->attached_device.address >= 0) {
-		usb_log_warning("Device unplug on `%s' (port %zu): " \
-		    "not implemented.\n", hub->usb_device->ddf_dev->name,
-		    (size_t) port);
-		the_port->attached_device.address = -1;
-		the_port->attached_device.handle = 0;
-	} else {
-		usb_log_warning("Device removed before being registered.\n");
-
-		/*
-		 * Device was removed before port reset completed.
-		 * We will announce a failed port reset to unblock the
-		 * port reset callback from new device wrapper.
-		 */
-		fibril_mutex_lock(&the_port->reset_mutex);
-		the_port->reset_completed = true;
-		the_port->reset_okay = false;
-		fibril_condvar_broadcast(&the_port->reset_cv);
-		fibril_mutex_unlock(&the_port->reset_mutex);
-	}
-
-	fibril_mutex_unlock(&hub->port_mutex);
-}
-
-/**
- * Process port reset change
- *
- * After this change port should be enabled, unless some problem occured.
- * This functions triggers second phase of enabling new device.
- * @param hub
- * @param port
- * @param status
- */
-static void usb_hub_port_reset_completed(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status) {
-	usb_log_debug("Port %zu reset complete.\n", (size_t) port);
-	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_ENABLE)) {
-		/* Finalize device adding. */
-		usb_hub_port_t *the_port = hub->ports + port;
-		fibril_mutex_lock(&the_port->reset_mutex);
-		the_port->reset_completed = true;
-		the_port->reset_okay = true;
-		fibril_condvar_broadcast(&the_port->reset_cv);
-		fibril_mutex_unlock(&the_port->reset_mutex);
-	} else {
-		usb_log_warning(
-		    "Port %zu reset complete but port not enabled.\n",
-		    (size_t) port);
-	}
-	/* Clear the port reset change. */
-	int rc = usb_hub_clear_port_feature(hub->control_pipe,
-	    port, USB_HUB_FEATURE_C_PORT_RESET);
-	if (rc != EOK) {
-		usb_log_error("Failed to clear port %d reset feature: %s.\n",
-		    port, str_error(rc));
-	}
-}
-
-/**
- * Process over current condition on port.
- *
- * Turn off the power on the port.
- *
- * @param hub hub representation
- * @param port port number, starting from 1
- */
-static void usb_hub_port_over_current(usb_hub_info_t *hub,
-    uint16_t port, uint32_t status) {
-	int opResult;
-	if (usb_port_is_status(status, USB_HUB_FEATURE_PORT_OVER_CURRENT)) {
-		opResult = usb_hub_clear_port_feature(hub->control_pipe,
-		    port, USB_HUB_FEATURE_PORT_POWER);
-		if (opResult != EOK) {
-			usb_log_error("Cannot power off port %d; %s\n",
-			    port, str_error(opResult));
-		}
-	} else {
-		opResult = usb_hub_set_port_feature(hub->control_pipe,
-		    port, USB_HUB_FEATURE_PORT_POWER);
-		if (opResult != EOK) {
-			usb_log_error("Cannot power on port %d; %s\n",
-			    port, str_error(opResult));
-		}
-	}
-}
-
-/** Retrieve port status.
- *
- * @param[in] ctrl_pipe Control pipe to use.
- * @param[in] port Port number (starting at 1).
- * @param[out] status Where to store the port status.
- * @return Error code.
- */
-static int get_port_status(usb_pipe_t *ctrl_pipe, size_t port,
-    usb_port_status_t *status) {
-	size_t recv_size;
-	usb_device_request_setup_packet_t request;
-	usb_port_status_t status_tmp;
-
-	usb_hub_set_port_status_request(&request, port);
-	int rc = usb_pipe_control_read(ctrl_pipe,
-	    &request, sizeof (usb_device_request_setup_packet_t),
-	    &status_tmp, sizeof (status_tmp), &recv_size);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	if (recv_size != sizeof (status_tmp)) {
-		return ELIMIT;
-	}
-
-	if (status != NULL) {
-		*status = status_tmp;
-	}
-
-	return EOK;
-}
-
-/** Callback for enabling a specific port.
- *
- * We wait on a CV until port is reseted.
- * That is announced via change on interrupt pipe.
- *
- * @param port_no Port number (starting at 1).
- * @param arg Custom argument, points to @c usb_hub_info_t.
- * @return Error code.
- */
-static int enable_port_callback(int port_no, void *arg) {
-	usb_hub_info_t *hub = arg;
-	int rc;
-	usb_device_request_setup_packet_t request;
-	usb_hub_port_t *my_port = hub->ports + port_no;
-
-	usb_hub_set_reset_port_request(&request, port_no);
-	rc = usb_pipe_control_write(hub->control_pipe,
-	    &request, sizeof (request), NULL, 0);
-	if (rc != EOK) {
-		usb_log_warning("Port reset failed: %s.\n", str_error(rc));
-		return rc;
-	}
-
-	/*
-	 * Wait until reset completes.
-	 */
-	fibril_mutex_lock(&my_port->reset_mutex);
-	while (!my_port->reset_completed) {
-		fibril_condvar_wait(&my_port->reset_cv, &my_port->reset_mutex);
-	}
-	fibril_mutex_unlock(&my_port->reset_mutex);
-
-	if (my_port->reset_okay) {
-		return EOK;
-	} else {
-		return ESTALL;
-	}
-}
-
-/** Fibril for adding a new device.
- *
- * Separate fibril is needed because the port reset completion is announced
- * via interrupt pipe and thus we cannot block here.
- *
- * @param arg Pointer to struct add_device_phase1.
- * @return 0 Always.
- */
-static int add_device_phase1_worker_fibril(void *arg) {
-	struct add_device_phase1 *data
-	    = (struct add_device_phase1 *) arg;
-
-	usb_address_t new_address;
-	devman_handle_t child_handle;
-
-	int rc = usb_hc_new_device_wrapper(data->hub->usb_device->ddf_dev,
-	    &data->hub->connection, data->speed,
-	    enable_port_callback, (int) data->port, data->hub,
-	    &new_address, &child_handle,
-	    NULL, NULL, NULL);
-
-	if (rc != EOK) {
-		usb_log_error("Failed registering device on port %zu: %s.\n",
-		    data->port, str_error(rc));
-		goto leave;
-	}
-
-	fibril_mutex_lock(&data->hub->port_mutex);
-	data->hub->ports[data->port].attached_device.handle = child_handle;
-	data->hub->ports[data->port].attached_device.address = new_address;
-	fibril_mutex_unlock(&data->hub->port_mutex);
-
-	usb_log_info("Detected new device on `%s' (port %zu), "
-	    "address %d (handle %" PRIun ").\n",
-	    data->hub->usb_device->ddf_dev->name, data->port,
-	    new_address, child_handle);
-
-leave:
-	free(arg);
-
-	fibril_mutex_lock(&data->hub->pending_ops_mutex);
-	assert(data->hub->pending_ops_count > 0);
-	data->hub->pending_ops_count--;
-	fibril_condvar_signal(&data->hub->pending_ops_cv);
-	fibril_mutex_unlock(&data->hub->pending_ops_mutex);
-
-
-	return EOK;
-}
-
-/** Start device adding when connection change is detected.
- *
- * This fires a new fibril to complete the device addition.
- *
- * @param hub Hub where the change occured.
- * @param port Port index (starting at 1).
- * @param speed Speed of the device.
- * @return Error code.
- */
-static int create_add_device_fibril(usb_hub_info_t *hub, size_t port,
-    usb_speed_t speed) {
-	struct add_device_phase1 *data
-	    = malloc(sizeof (struct add_device_phase1));
-	if (data == NULL) {
-		return ENOMEM;
-	}
-	data->hub = hub;
-	data->port = port;
-	data->speed = speed;
-
-	usb_hub_port_t *the_port = hub->ports + port;
-
-	fibril_mutex_lock(&the_port->reset_mutex);
-	the_port->reset_completed = false;
-	fibril_mutex_unlock(&the_port->reset_mutex);
-
-	int rc = usb_hub_clear_port_feature(hub->control_pipe, port,
-	    USB_HUB_FEATURE_C_PORT_CONNECTION);
-	if (rc != EOK) {
-		free(data);
-		usb_log_warning("Failed to clear port change flag: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-
-	fid_t fibril = fibril_create(add_device_phase1_worker_fibril, data);
-	if (fibril == 0) {
-		free(data);
-		return ENOMEM;
-	}
-	fibril_mutex_lock(&hub->pending_ops_mutex);
-	hub->pending_ops_count++;
-	fibril_mutex_unlock(&hub->pending_ops_mutex);
-	fibril_add_ready(fibril);
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbhub/ports.h
===================================================================
--- uspace/drv/bus/usb/usbhub/ports.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,80 +1,0 @@
-/*
- * 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 drvusbhub
- * @{
- */
-/** @file
- * Hub ports related functions.
- */
-#ifndef DRV_USBHUB_PORTS_H
-#define DRV_USBHUB_PORTS_H
-
-#include <usb/dev/driver.h>
-#include <usb/dev/hub.h>
-
-typedef struct usb_hub_info_t usb_hub_info_t;
-
-/** Information about single port on a hub. */
-typedef struct {
-	/** Mutex needed by CV for checking port reset. */
-	fibril_mutex_t reset_mutex;
-	/** CV for waiting to port reset completion. */
-	fibril_condvar_t reset_cv;
-	/** Whether port reset is completed.
-	 * Guarded by @c reset_mutex.
-	 */
-	bool reset_completed;
-	/** Whether to announce the port reset as successful. */
-	bool reset_okay;
-
-	/** Information about attached device. */
-	usb_hc_attached_device_t attached_device;
-} usb_hub_port_t;
-
-/** Initialize hub port information.
- *
- * @param port Port to be initialized.
- */
-static inline void usb_hub_port_init(usb_hub_port_t *port) {
-	port->attached_device.address = -1;
-	port->attached_device.handle = 0;
-	fibril_mutex_initialize(&port->reset_mutex);
-	fibril_condvar_initialize(&port->reset_cv);
-}
-
-
-void usb_hub_process_port_interrupt(usb_hub_info_t *hub,
-	uint16_t port);
-
-
-
-#endif
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbhub/status.h
===================================================================
--- uspace/drv/bus/usb/usbhub/status.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
+++ uspace/drv/bus/usb/usbhub/status.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2010 Matus Dekanek
+ * Copyright (c) 2011 Jan Vesely
+ * 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 drvusbhub
+ * @{
+ */
+
+#ifndef HUB_STATUS_H
+#define	HUB_STATUS_H
+
+#include <bool.h>
+#include <sys/types.h>
+#include <usb/dev/request.h>
+
+/**
+ * structure holding port status and changes flags.
+ * should not be accessed directly, use supplied getter/setter methods.
+ *
+ * For more information refer to table 11-15 in
+ * "Universal Serial Bus Specification Revision 1.1"
+ *
+ */
+typedef uint32_t usb_port_status_t;
+#define USB_HUB_PORT_STATUS_CONNECTION \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_CONNECTION)))
+#define USB_HUB_PORT_STATUS_ENABLED \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_ENABLE)))
+#define USB_HUB_PORT_STATUS_SUSPEND \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_SUSPEND)))
+#define USB_HUB_PORT_STATUS_OC \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_OVER_CURRENT)))
+#define USB_HUB_PORT_STATUS_RESET \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_RESET)))
+#define USB_HUB_PORT_STATUS_POWER \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_POWER)))
+#define USB_HUB_PORT_STATUS_LOW_SPEED \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_PORT_LOW_SPEED)))
+#define USB_HUB_PORT_STATUS_HIGH_SPEED \
+    (uint32_usb2host(1 << 10))
+
+#define USB_HUB_PORT_C_STATUS_CONNECTION \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_C_PORT_CONNECTION)))
+#define USB_HUB_PORT_C_STATUS_ENABLED \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_C_PORT_ENABLE)))
+#define USB_HUB_PORT_C_STATUS_SUSPEND \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_C_PORT_SUSPEND)))
+#define USB_HUB_PORT_C_STATUS_OC \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_C_PORT_OVER_CURRENT)))
+#define USB_HUB_PORT_C_STATUS_RESET \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_C_PORT_RESET)))
+
+/**
+ * structure holding hub status and changes flags.
+ *
+ * For more information refer to table 11.16.2.5 in
+ * "Universal Serial Bus Specification Revision 1.1"
+ *
+ */
+typedef uint32_t usb_hub_status_t;
+#define USB_HUB_STATUS_OVER_CURRENT \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_HUB_OVER_CURRENT)))
+#define USB_HUB_STATUS_LOCAL_POWER \
+    (uint32_usb2host(1 << (USB_HUB_FEATURE_HUB_LOCAL_POWER)))
+
+#define USB_HUB_STATUS_C_OVER_CURRENT \
+    (uint32_usb2host(1 << (16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)))
+#define USB_HUB_STATUS_C_LOCAL_POWER \
+    (uint32_usb2host(1 << (16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)))
+
+
+/**
+ * speed getter for port status
+ *
+ * @param status
+ * @return speed of usb device (for more see usb specification)
+ */
+static inline usb_speed_t usb_port_speed(usb_port_status_t status)
+{
+	if ((status & USB_HUB_PORT_STATUS_LOW_SPEED) != 0)
+		return USB_SPEED_LOW;
+	if ((status & USB_HUB_PORT_STATUS_HIGH_SPEED) != 0)
+		return USB_SPEED_HIGH;
+	return USB_SPEED_FULL;
+}
+
+#endif	/* HUB_STATUS_H */
+/**
+ * @}
+ */
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Matus Dekanek
+ * Copyright (c) 2011 Jan Vesely
  * All rights reserved.
  *
@@ -38,6 +39,10 @@
 #include <str_error.h>
 #include <inttypes.h>
-
-#include <usb_iface.h>
+#include <stdio.h>
+
+#include <usb/usb.h>
+#include <usb/debug.h>
+#include <usb/dev/pipes.h>
+#include <usb/classes/classes.h>
 #include <usb/ddfiface.h>
 #include <usb/descriptor.h>
@@ -46,72 +51,67 @@
 #include <usb/classes/hub.h>
 #include <usb/dev/poll.h>
-#include <stdio.h>
+#include <usb_iface.h>
 
 #include "usbhub.h"
-#include "usbhub_private.h"
-#include "port_status.h"
-#include <usb/usb.h>
-#include <usb/dev/pipes.h>
-#include <usb/classes/classes.h>
-
-
+#include "status.h"
+
+#define HUB_FNC_NAME "hub"
+
+/** Standard get hub global status request */
+static const usb_device_request_setup_packet_t get_hub_status_request = {
+	.request_type = USB_HUB_REQ_TYPE_GET_HUB_STATUS,
+	.request = USB_HUB_REQUEST_GET_STATUS,
+	.index = 0,
+	.value = 0,
+	.length = sizeof(usb_hub_status_t),
+};
+
+static int usb_set_first_configuration(usb_device_t *usb_device);
 static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev);
-
 static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info);
-
-static int usb_hub_set_configuration(usb_hub_info_t *hub_info);
-
-static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info);
-
-static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
+static void usb_hub_over_current(const usb_hub_info_t *hub_info,
     usb_hub_status_t status);
-
-static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
-    usb_hub_status_t status);
-
-static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info);
-
+static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info);
 static void usb_hub_polling_terminated_callback(usb_device_t *device,
     bool was_error, void *data);
 
-
-//*********************************************
-//
-//  hub driver code, initialization
-//
-//*********************************************
-
 /**
  * Initialize hub device driver fibril
  *
- * Creates hub representation and fibril that periodically checks hub`s status.
+ * Creates hub representation and fibril that periodically checks hub's status.
  * Hub representation is passed to the fibril.
  * @param usb_dev generic usb device information
  * @return error code
  */
-int usb_hub_add_device(usb_device_t *usb_dev) {
-	if (!usb_dev) return EINVAL;
+int usb_hub_add_device(usb_device_t *usb_dev)
+{
+	assert(usb_dev);
+	/* Create driver soft-state structure */
 	usb_hub_info_t *hub_info = usb_hub_info_create(usb_dev);
-	//create hc connection
+	if (hub_info == NULL) {
+		usb_log_error("Failed to create hun driver structure.\n");
+		return ENOMEM;
+	}
+
+	/* Create hc connection */
 	usb_log_debug("Initializing USB wire abstraction.\n");
 	int opResult = usb_hc_connection_initialize_from_device(
-	    &hub_info->connection,
-	    hub_info->usb_device->ddf_dev);
-	if (opResult != EOK) {
-		usb_log_error("Could not initialize connection to device, "
-		    " %s\n",
-		    str_error(opResult));
-		free(hub_info);
-		return opResult;
-	}
-
-	//set hub configuration
-	opResult = usb_hub_set_configuration(hub_info);
-	if (opResult != EOK) {
-		usb_log_error("Could not set hub configuration, %s\n",
-		    str_error(opResult));
-		free(hub_info);
-		return opResult;
-	}
+	    &hub_info->connection, hub_info->usb_device->ddf_dev);
+	if (opResult != EOK) {
+		usb_log_error("Could not initialize connection to device: %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+
+	/* Set hub's first configuration. (There should be only one) */
+	opResult = usb_set_first_configuration(usb_dev);
+	if (opResult != EOK) {
+		usb_log_error("Could not set hub configuration: %s\n",
+		    str_error(opResult));
+		free(hub_info);
+		return opResult;
+	}
+
 	//get port count and create attached_devs
 	opResult = usb_hub_process_hub_specific_info(hub_info);
@@ -123,19 +123,38 @@
 	}
 
-	usb_log_debug("Creating 'hub' function in DDF.\n");
+	usb_log_debug("Creating DDF function '" HUB_FNC_NAME "'.\n");
 	ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
-	    fun_exposed, "hub");
-	assert(hub_fun != NULL);
-	hub_fun->ops = NULL;
+	    fun_exposed, HUB_FNC_NAME);
+	if (hub_fun == NULL) {
+		usb_log_error("Failed to create hub function.\n");
+		free(hub_info);
+		return ENOMEM;
+	}
 
 	opResult = ddf_fun_bind(hub_fun);
-	assert(opResult == EOK);
-
-	opResult = usb_hub_start_hub_fibril(hub_info);
-	if (opResult != EOK)
-		free(hub_info);
-	return opResult;
-}
-
+	if (opResult != EOK) {
+		usb_log_error("Failed to bind hub function: %s.\n",
+		   str_error(opResult));
+		free(hub_info);
+		ddf_fun_destroy(hub_fun);
+		return opResult;
+	}
+
+	opResult = usb_device_auto_poll(hub_info->usb_device, 0,
+	    hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
+	    usb_hub_polling_terminated_callback, hub_info);
+	if (opResult != EOK) {
+		ddf_fun_destroy(hub_fun);
+		free(hub_info);
+		usb_log_error("Failed to create polling fibril: %s.\n",
+		    str_error(opResult));
+		return opResult;
+	}
+	usb_log_info("Controlling hub '%s' (%zu ports).\n",
+	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
+
+	return EOK;
+}
+/*----------------------------------------------------------------------------*/
 /** Callback for polling hub for changes.
  *
@@ -147,40 +166,32 @@
  */
 bool hub_port_changes_callback(usb_device_t *dev,
-    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
+    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)
+{
 	usb_log_debug("hub_port_changes_callback\n");
-	usb_hub_info_t *hub = (usb_hub_info_t *) arg;
-
-	/* FIXME: check that we received enough bytes. */
+	usb_hub_info_t *hub = arg;
+	assert(hub);
+
+	/* It is an error condition if we didn't receive enough data */
 	if (change_bitmap_size == 0) {
-		goto leave;
-	}
-
-	bool change;
-	change = ((uint8_t*) change_bitmap)[0] & 1;
+		return false;
+	}
+
+	/* Lowest bit indicates global change */
+	const bool change = change_bitmap[0] & 1;
 	if (change) {
-		usb_hub_process_global_interrupt(hub);
-	}
-
-	size_t port;
-	for (port = 1; port < hub->port_count + 1; port++) {
-		bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
+		usb_hub_global_interrupt(hub);
+	}
+
+	/* N + 1 bit indicates change on port N */
+	size_t port = 1;
+	for (; port < hub->port_count + 1; port++) {
+		const bool change = (change_bitmap[port / 8] >> (port % 8)) & 1;
 		if (change) {
-			usb_hub_process_port_interrupt(hub, port);
+			usb_hub_port_process_interrupt(&hub->ports[port], hub);
 		}
 	}
-leave:
-	/* FIXME: proper interval. */
-	async_usleep(1000 * 250);
-
 	return true;
 }
-
-
-//*********************************************
-//
-//  support functions
-//
-//*********************************************
-
+/*----------------------------------------------------------------------------*/
 /**
  * create usb_hub_info_t structure
@@ -190,45 +201,46 @@
  * @return basic usb_hub_info_t structure
  */
-static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev) {
-	usb_hub_info_t * result = malloc(sizeof (usb_hub_info_t));
-	if (!result) return NULL;
-	result->usb_device = usb_dev;
-	result->status_change_pipe = usb_dev->pipes[0].pipe;
-	result->control_pipe = &usb_dev->ctrl_pipe;
-	result->is_default_address_used = false;
-
-	result->ports = NULL;
-	result->port_count = (size_t) - 1;
-	fibril_mutex_initialize(&result->port_mutex);
-
-	fibril_mutex_initialize(&result->pending_ops_mutex);
-	fibril_condvar_initialize(&result->pending_ops_cv);
-	result->pending_ops_count = 0;
-	return result;
-}
-
+static usb_hub_info_t * usb_hub_info_create(usb_device_t *usb_dev)
+{
+	assert(usb_dev);
+	usb_hub_info_t *info = malloc(sizeof(usb_hub_info_t));
+	if (!info)
+	    return NULL;
+
+	info->usb_device = usb_dev;
+
+	info->ports = NULL;
+	info->port_count = -1;
+	fibril_mutex_initialize(&info->pending_ops_mutex);
+	fibril_condvar_initialize(&info->pending_ops_cv);
+	info->pending_ops_count = 0;
+
+	return info;
+}
+/*----------------------------------------------------------------------------*/
 /**
  * Load hub-specific information into hub_info structure and process if needed
  *
- * Particularly read port count and initialize structure holding port
- * information. If there are non-removable devices, start initializing them.
+ * Read port count and initialize structures holding per port information.
+ * If there are any non-removable devices, start initializing them.
  * This function is hub-specific and should be run only after the hub is
- * configured using usb_hub_set_configuration function.
+ * configured using usb_set_first_configuration function.
  * @param hub_info hub representation
  * @return error code
  */
-int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
-{
-	// get hub descriptor
+static int usb_hub_process_hub_specific_info(usb_hub_info_t *hub_info)
+{
+	assert(hub_info);
+
+	/* Get hub descriptor. */
 	usb_log_debug("Retrieving descriptor\n");
-	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
-	int opResult;
-
+	usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe;
+
+	usb_hub_descriptor_header_t descriptor;
 	size_t received_size;
-	opResult = usb_request_get_descriptor(hub_info->control_pipe,
+	int opResult = usb_request_get_descriptor(control_pipe,
 	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
-	    USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
-
+	    USB_DESCTYPE_HUB, 0, 0, &descriptor,
+	    sizeof(usb_hub_descriptor_t), &received_size);
 	if (opResult != EOK) {
 		usb_log_error("Failed to receive hub descriptor: %s.\n",
@@ -236,16 +248,9 @@
 		return opResult;
 	}
-	usb_log_debug2("Parsing descriptor\n");
-	usb_hub_descriptor_t descriptor;
-	opResult = usb_deserialize_hub_desriptor(
-	        serialized_descriptor, received_size, &descriptor);
-	if (opResult != EOK) {
-		usb_log_error("Could not parse descriptor: %s\n",
-		    str_error(opResult));
-		return opResult;
-	}
-	usb_log_debug("Setting port count to %d.\n", descriptor.ports_count);
-	hub_info->port_count = descriptor.ports_count;
-
+
+	usb_log_debug("Setting port count to %d.\n", descriptor.port_count);
+	hub_info->port_count = descriptor.port_count;
+
+	// TODO: +1 hack is no longer necessary
 	hub_info->ports =
 	    malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
@@ -256,19 +261,18 @@
 	size_t port;
 	for (port = 0; port < hub_info->port_count + 1; ++port) {
-		usb_hub_port_init(&hub_info->ports[port]);
+		usb_hub_port_init(&hub_info->ports[port], port, control_pipe);
 	}
 
 	const bool is_power_switched =
-	    !(descriptor.hub_characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
+	    !(descriptor.characteristics & HUB_CHAR_NO_POWER_SWITCH_FLAG);
 	if (is_power_switched) {
 		usb_log_debug("Hub power switched\n");
-		const bool per_port_power = descriptor.hub_characteristics
+		const bool per_port_power = descriptor.characteristics
 		    & HUB_CHAR_POWER_PER_PORT_FLAG;
 
 		for (port = 1; port <= hub_info->port_count; ++port) {
 			usb_log_debug("Powering port %zu.\n", port);
-			opResult = usb_hub_set_port_feature(
-			    hub_info->control_pipe,
-			    port, USB_HUB_FEATURE_PORT_POWER);
+			opResult = usb_hub_port_set_feature(
+			    &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
 			if (opResult != EOK) {
 				usb_log_error("Cannot power on port %zu: %s.\n",
@@ -283,85 +287,52 @@
 			}
 		}
-
 	} else {
-		usb_log_debug("Power not switched, not going to be powered\n");
+		usb_log_debug("Power not switched, ports always powered\n");
 	}
 	return EOK;
 }
-
-/**
- * Set configuration of hub
+/*----------------------------------------------------------------------------*/
+/**
+ * Set configuration of and USB device
  *
  * Check whether there is at least one configuration and sets the first one.
  * This function should be run prior to running any hub-specific action.
- * @param hub_info hub representation
+ * @param usb_device usb device representation
  * @return error code
  */
-static int usb_hub_set_configuration(usb_hub_info_t *hub_info) {
-	//device descriptor
-	usb_standard_device_descriptor_t *std_descriptor
-	    = &hub_info->usb_device->descriptors.device;
-	usb_log_debug("Hub has %d configurations\n",
-	    std_descriptor->configuration_count);
-	if (std_descriptor->configuration_count < 1) {
+static int usb_set_first_configuration(usb_device_t *usb_device)
+{
+	assert(usb_device);
+	/* Get number of possible configurations from device descriptor */
+	const size_t configuration_count =
+	    usb_device->descriptors.device.configuration_count;
+	usb_log_debug("Hub has %d configurations.\n", configuration_count);
+
+	if (configuration_count < 1) {
 		usb_log_error("There are no configurations available\n");
 		return EINVAL;
 	}
 
+	// TODO: Make sure that there is enough data and the cast is correct
 	usb_standard_configuration_descriptor_t *config_descriptor
 	    = (usb_standard_configuration_descriptor_t *)
-	    hub_info->usb_device->descriptors.configuration;
-
-	/* Set configuration. */
-	int opResult = usb_request_set_configuration(
-	    &hub_info->usb_device->ctrl_pipe,
-	    config_descriptor->configuration_number);
-
+	    usb_device->descriptors.configuration;
+
+	/* Set configuration. Use the configuration that was in
+	 * usb_device->descriptors.configuration i.e. The first one. */
+	const int opResult = usb_request_set_configuration(
+	    &usb_device->ctrl_pipe, config_descriptor->configuration_number);
 	if (opResult != EOK) {
 		usb_log_error("Failed to set hub configuration: %s.\n",
 		    str_error(opResult));
-		return opResult;
-	}
-	usb_log_debug("\tUsed configuration %d\n",
-	    config_descriptor->configuration_number);
-
-	return EOK;
-}
-
-/**
- * create and start fibril with hub control loop
- *
- * Before the fibril is started, the control pipe and host controller
- * connection of the hub is open.
- *
- * @param hub_info hub representing structure
- * @return error code
- */
-static int usb_hub_start_hub_fibril(usb_hub_info_t *hub_info) {
-	int rc;
-
-	rc = usb_device_auto_poll(hub_info->usb_device, 0,
-	    hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
-	    usb_hub_polling_terminated_callback, hub_info);
-	if (rc != EOK) {
-		usb_log_error("Failed to create polling fibril: %s.\n",
-		    str_error(rc));
-		free(hub_info);
-		return rc;
-	}
-
-	usb_log_info("Controlling hub `%s' (%zu ports).\n",
-	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
-	return EOK;
-}
-
-//*********************************************
-//
-//  change handling functions
-//
-//*********************************************
-
-/**
- * process hub over current change
+	} else {
+		usb_log_debug("\tUsed configuration %d\n",
+		    config_descriptor->configuration_number);
+	}
+	return opResult;
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process hub over current change
  *
  * This means either to power off the hub or power it on.
@@ -370,82 +341,57 @@
  * @return error code
  */
-static int usb_process_hub_over_current(usb_hub_info_t *hub_info,
-    usb_hub_status_t status) {
-	int opResult;
-	if (usb_hub_is_status(status, USB_HUB_FEATURE_HUB_OVER_CURRENT)) {
-		//poweroff all ports
-		unsigned int port;
+static void usb_hub_over_current(const usb_hub_info_t *hub_info,
+    usb_hub_status_t status)
+{
+	if (status & USB_HUB_STATUS_OVER_CURRENT) {
+		/* Hub should remove power from all ports if it detects OC */
+		usb_log_warning("Detected hub over-current condition, "
+		    "all ports should be powered off.");
+	} else {
+		/* Over-current condition is gone, it is safe to turn the
+		 * ports on. */
+		size_t port;
 		for (port = 1; port <= hub_info->port_count; ++port) {
-			opResult = usb_hub_clear_port_feature(
-			    hub_info->control_pipe, port,
-			    USB_HUB_FEATURE_PORT_POWER);
+			const int opResult = usb_hub_port_set_feature(
+			    &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
 			if (opResult != EOK) {
 				usb_log_warning(
-				    "Cannot power off port %d;  %s\n",
+				    "HUB OVER-CURRENT GONE: Cannot power on "
+				    "port %d;  %s\n",
 				    port, str_error(opResult));
 			}
 		}
-	} else {
-		//power all ports
-		unsigned int port;
-		for (port = 1; port <= hub_info->port_count; ++port) {
-			opResult = usb_hub_set_port_feature(
-			    hub_info->control_pipe, port,
-			    USB_HUB_FEATURE_PORT_POWER);
-			if (opResult != EOK) {
-				usb_log_warning(
-				    "Cannot power off port %d;  %s\n",
-				    port, str_error(opResult));
-			}
-		}
-	}
-	return opResult;
-}
-
-/**
- * process hub local power change
- *
- * This change is ignored.
+	}
+	const int opResult = usb_request_clear_feature(
+	    &hub_info->usb_device->ctrl_pipe, USB_REQUEST_TYPE_CLASS,
+	    USB_REQUEST_RECIPIENT_DEVICE,
+	    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
+	if (opResult != EOK) {
+		usb_log_error(
+		    "Failed to clear hub over-current change flag: %s.\n",
+		    str_error(opResult));
+	}
+}
+/*----------------------------------------------------------------------------*/
+/**
+ * Process hub interrupts.
+ *
+ * The change can be either in the over-current condition or local-power change.
  * @param hub_info hub instance
- * @param status hub status bitmask
- * @return error code
- */
-static int usb_process_hub_local_power_change(usb_hub_info_t *hub_info,
-    usb_hub_status_t status) {
-	int opResult = EOK;
-	opResult = usb_hub_clear_feature(hub_info->control_pipe,
-	    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
-	if (opResult != EOK) {
-		usb_log_error("Cannnot clear hub power change flag: "
-		    "%s\n",
-		    str_error(opResult));
-	}
-	return opResult;
-}
-
-/**
- * process hub interrupts
- *
- * The change can be either in the over-current condition or
- * local-power change.
- * @param hub_info hub instance
- */
-static void usb_hub_process_global_interrupt(usb_hub_info_t *hub_info) {
+ */
+static void usb_hub_global_interrupt(const usb_hub_info_t *hub_info)
+{
+	assert(hub_info);
+	assert(hub_info->usb_device);
 	usb_log_debug("Global interrupt on a hub\n");
-	usb_pipe_t *pipe = hub_info->control_pipe;
-	int opResult;
-
-	usb_port_status_t status;
+	usb_pipe_t *control_pipe = &hub_info->usb_device->ctrl_pipe;
+
+	usb_hub_status_t status;
 	size_t rcvd_size;
-	usb_device_request_setup_packet_t request;
-	//int opResult;
-	usb_hub_set_hub_status_request(&request);
-	//endpoint 0
-
-	opResult = usb_pipe_control_read(
-	    pipe,
-	    &request, sizeof (usb_device_request_setup_packet_t),
-	    &status, 4, &rcvd_size
-	    );
+	/* NOTE: We can't use standard USB GET_STATUS request, because
+	 * hubs reply is 4byte instead of 2 */
+	const int opResult = usb_pipe_control_read(control_pipe,
+	    &get_hub_status_request, sizeof(get_hub_status_request),
+	    &status, sizeof(usb_hub_status_t), &rcvd_size);
 	if (opResult != EOK) {
 		usb_log_error("Could not get hub status: %s\n",
@@ -453,19 +399,40 @@
 		return;
 	}
-	if (rcvd_size != sizeof (usb_port_status_t)) {
+	if (rcvd_size != sizeof(usb_hub_status_t)) {
 		usb_log_error("Received status has incorrect size\n");
 		return;
 	}
-	//port reset
-	if (
-	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_OVER_CURRENT)) {
-		usb_process_hub_over_current(hub_info, status);
-	}
-	if (
-	    usb_hub_is_status(status, 16 + USB_HUB_FEATURE_C_HUB_LOCAL_POWER)) {
-		usb_process_hub_local_power_change(hub_info, status);
-	}
-}
-
+
+	/* Handle status changes */
+	if (status & USB_HUB_STATUS_C_OVER_CURRENT) {
+		usb_hub_over_current(hub_info, status);
+	}
+
+	if (status & USB_HUB_STATUS_C_LOCAL_POWER) {
+		/* NOTE: Handling this is more complicated.
+		 * If the transition is from bus power to local power, all
+		 * is good and we may signal the parent hub that we don't
+		 * need the power.
+		 * If the transition is from local power to bus power
+		 * the hub should turn off all the ports and devices need
+		 * to be reinitialized taking into account the limited power
+		 * that is now available.
+		 * There is no support for power distribution in HelenOS,
+		 * (or other OSes/hub devices that I've seen) so this is not
+		 * implemented.
+		 * Just ACK the change.
+		 */
+		const int opResult = usb_request_clear_feature(
+		    control_pipe, USB_REQUEST_TYPE_CLASS,
+		    USB_REQUEST_RECIPIENT_DEVICE,
+		    USB_HUB_FEATURE_C_HUB_LOCAL_POWER, 0);
+		if (opResult != EOK) {
+			usb_log_error(
+			    "Failed to clear hub power change flag: %s.\n",
+			    str_error(opResult));
+		}
+	}
+}
+/*----------------------------------------------------------------------------*/
 /**
  * callback called from hub polling fibril when the fibril terminates
@@ -477,6 +444,7 @@
  */
 static void usb_hub_polling_terminated_callback(usb_device_t *device,
-    bool was_error, void *data) {
-	usb_hub_info_t * hub = data;
+    bool was_error, void *data)
+{
+	usb_hub_info_t *hub = data;
 	assert(hub);
 
@@ -492,15 +460,8 @@
 	 */
 	if (hub->pending_ops_count > 0) {
-		fibril_mutex_lock(&hub->port_mutex);
 		size_t port;
 		for (port = 0; port < hub->port_count; port++) {
-			usb_hub_port_t *the_port = hub->ports + port;
-			fibril_mutex_lock(&the_port->reset_mutex);
-			the_port->reset_completed = true;
-			the_port->reset_okay = false;
-			fibril_condvar_broadcast(&the_port->reset_cv);
-			fibril_mutex_unlock(&the_port->reset_mutex);
+			usb_hub_port_reset_fail(&hub->ports[port]);
 		}
-		fibril_mutex_unlock(&hub->port_mutex);
 	}
 	/* And now wait for them. */
@@ -516,8 +477,4 @@
 	free(hub);
 }
-
-
-
-
 /**
  * @}
Index: uspace/drv/bus/usb/usbhub/usbhub.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/drv/bus/usb/usbhub/usbhub.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2010 Vojtech Horky
+ * Copyright (c) 2011 Vojtech Horky
  * All rights reserved.
  *
@@ -26,5 +27,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 /** @addtogroup drvusbhub
  * @{
@@ -49,5 +49,5 @@
 #define NAME "usbhub"
 
-#include "ports.h"
+#include "port.h"
 
 /** Information about attached hub. */
@@ -56,37 +56,12 @@
 	size_t port_count;
 
-	/** attached device handles, for each port one */
+	/** Attached device handles, for each port one */
 	usb_hub_port_t *ports;
 
-	fibril_mutex_t port_mutex;
-
-	/** connection to hcd */
+	/** Connection to hcd */
 	usb_hc_connection_t connection;
 
-	/** default address is used indicator
-	 *
-	 * If default address is requested by this device, it cannot
-	 * be requested by the same hub again, otherwise a deadlock will occur.
-	 */
-	bool is_default_address_used;
-
-	/** convenience pointer to status change pipe
-	 *
-	 * Status change pipe is initialized in usb_device structure. This is
-	 * pointer into this structure, so that it does not have to be
-	 * searched again and again for the 'right pipe'.
-	 */
-	usb_pipe_t * status_change_pipe;
-
-	/** convenience pointer to control pipe
-	 *
-	 * Control pipe is initialized in usb_device structure. This is
-	 * pointer into this structure, so that it does not have to be
-	 * searched again and again for the 'right pipe'.
-	 */
-	usb_pipe_t * control_pipe;
-
-	/** generic usb device data*/
-	usb_device_t * usb_device;
+	/** Generic usb device data*/
+	usb_device_t *usb_device;
 
 	/** Number of pending operations on the mutex to prevent shooting
@@ -101,5 +76,4 @@
 	/** Condition variable for pending_ops_count. */
 	fibril_condvar_t pending_ops_cv;
-
 };
 
Index: uspace/drv/bus/usb/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub_private.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,181 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-/** @file
- * @brief Hub driver private definitions
- */
-
-#ifndef USBHUB_PRIVATE_H
-#define	USBHUB_PRIVATE_H
-
-#include "usbhub.h"
-
-#include <adt/list.h>
-#include <bool.h>
-#include <ddf/driver.h>
-#include <fibril_synch.h>
-
-#include <usb/classes/hub.h>
-#include <usb/usb.h>
-#include <usb/debug.h>
-#include <usb/dev/request.h>
-
-//************
-//
-// convenience define for malloc
-//
-//************
-
-
-usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
-
-/**
- * Set the device request to be a get hub descriptor request.
- * @warning the size is allways set to USB_HUB_MAX_DESCRIPTOR_SIZE
- * @param request
- * @param addr
- */
-static inline void usb_hub_set_descriptor_request(
-    usb_device_request_setup_packet_t * request
-    ) {
-	request->index = 0;
-	request->request_type = USB_HUB_REQ_TYPE_GET_DESCRIPTOR;
-	request->request = USB_HUB_REQUEST_GET_DESCRIPTOR;
-	request->value_high = USB_DESCTYPE_HUB;
-	request->value_low = 0;
-	request->length = USB_HUB_MAX_DESCRIPTOR_SIZE;
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param hc Host controller telephone
- * @param address Hub address
- * @param port_index Port
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_clear_port_feature(usb_pipe_t *pipe,
-    int port_index,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
-		.request = USB_DEVREQ_CLEAR_FEATURE,
-		.length = 0,
-		.index = port_index
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param hc Host controller telephone
- * @param address Hub address
- * @param port_index Port
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_set_port_feature(usb_pipe_t *pipe,
-    int port_index,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
-		.request = USB_DEVREQ_SET_FEATURE,
-		.length = 0,
-		.index = port_index
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param pipe pipe to hub control endpoint
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_clear_feature(usb_pipe_t *pipe,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
-		.request = USB_DEVREQ_CLEAR_FEATURE,
-		.length = 0,
-		.index = 0
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-/**
- * Clear feature on hub port.
- *
- * @param pipe pipe to hub control endpoint
- * @param feature Feature selector
- * @return Operation result
- */
-static inline int usb_hub_set_feature(usb_pipe_t *pipe,
-    usb_hub_class_feature_t feature) {
-
-	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_HUB_FEATURE,
-		.request = USB_DEVREQ_SET_FEATURE,
-		.length = 0,
-		.index = 0
-	};
-	clear_request.value = feature;
-	return usb_pipe_control_write(pipe, &clear_request,
-	    sizeof (clear_request), NULL, 0);
-}
-
-
-void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor);
-
-void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
-    void * serialized_descriptor);
-
-int usb_deserialize_hub_desriptor(
-    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor);
-
-
-#endif	/* USBHUB_PRIVATE_H */
-
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbhub/utils.c
===================================================================
--- uspace/drv/bus/usb/usbhub/utils.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,155 +1,0 @@
-/*
- * Copyright (c) 2010 Matus Dekanek
- * 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 drvusbhub
- * @{
- */
-/** @file
- * @brief various utilities
- */
-#include <ddf/driver.h>
-#include <bool.h>
-#include <errno.h>
-
-#include <usbhc_iface.h>
-#include <usb/descriptor.h>
-#include <usb/classes/hub.h>
-
-#include "usbhub.h"
-#include "usbhub_private.h"
-#include "port_status.h"
-
-
-size_t USB_HUB_MAX_DESCRIPTOR_SIZE = 71;
-
-//*********************************************
-//
-//  various utils
-//
-//*********************************************
-
-//hub descriptor utils
-
-/**
- * create uint8_t array with serialized descriptor
- *
- * @param descriptor
- * @return newly created serializd descriptor pointer
- */
-void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t *descriptor) {
-	//base size
-	size_t size = 7;
-	//variable size according to port count
-	size_t var_size = (descriptor->ports_count + 7) / 8;
-	size += 2 * var_size;
-	uint8_t * result = malloc(size);
-	//size
-	if (result)
-		usb_serialize_hub_descriptor(descriptor, result);
-	return result;
-}
-
-/**
- * serialize descriptor into given buffer
- *
- * The buffer size is not checked.
- * @param descriptor
- * @param serialized_descriptor
- */
-void usb_serialize_hub_descriptor(usb_hub_descriptor_t *descriptor,
-    void * serialized_descriptor) {
-	//base size
-	uint8_t * sdescriptor = serialized_descriptor;
-	size_t size = 7;
-	//variable size according to port count
-	size_t var_size = (descriptor->ports_count + 7) / 8;
-	size += 2 * var_size;
-	//size
-	sdescriptor[0] = size;
-	//descriptor type
-	sdescriptor[1] = USB_DESCTYPE_HUB;
-	sdescriptor[2] = descriptor->ports_count;
-	/// @fixme handling of endianness??
-	sdescriptor[3] = descriptor->hub_characteristics / 256;
-	sdescriptor[4] = descriptor->hub_characteristics % 256;
-	sdescriptor[5] = descriptor->pwr_on_2_good_time;
-	sdescriptor[6] = descriptor->current_requirement;
-
-	size_t i;
-	for (i = 0; i < var_size; ++i) {
-		sdescriptor[7 + i] = descriptor->devices_removable[i];
-	}
-	for (i = 0; i < var_size; ++i) {
-		sdescriptor[7 + var_size + i] = 255;
-	}
-}
-
-/*----------------------------------------------------------------------------*/
-/**
- * Deserialize descriptor into given pointer
- *
- * @param serialized_descriptor
- * @param descriptor
- * @return
- */
-int usb_deserialize_hub_desriptor(
-    void *serialized_descriptor, size_t size, usb_hub_descriptor_t *descriptor)
-{
-	uint8_t * sdescriptor = serialized_descriptor;
-
-	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
-		usb_log_error("Trying to deserialize wrong descriptor %x\n",
-		    sdescriptor[1]);
-		return EINVAL;
-	}
-	if (size < 7) {
-		usb_log_error("Serialized descriptor too small.\n");
-		return EOVERFLOW;
-	}
-
-	descriptor->ports_count = sdescriptor[2];
-	descriptor->hub_characteristics = sdescriptor[3] + 256 * sdescriptor[4];
-	descriptor->pwr_on_2_good_time = sdescriptor[5];
-	descriptor->current_requirement = sdescriptor[6];
-	const size_t var_size = (descriptor->ports_count + 7) / 8;
-	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
-
-	if (size < (7 + var_size)) {
-		usb_log_error("Serialized descriptor too small.\n");
-		return EOVERFLOW;
-	}
-	size_t i = 0;
-	for (; i < var_size; ++i) {
-		descriptor->devices_removable[i] = sdescriptor[7 + i];
-	}
-	return EOK;
-}
-/*----------------------------------------------------------------------------*/
-/**
- * @}
- */
Index: uspace/drv/bus/usb/usbmast/scsi.h
===================================================================
--- uspace/drv/bus/usb/usbmast/scsi.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * 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 drvusbmast
- * @{
- */
-/** @file
- * SCSI related structures.
- */
-
-#ifndef USB_USBMAST_SCSI_H_
-#define USB_USBMAST_SCSI_H_
-
-#include <sys/types.h>
-#include <usb/usb.h>
-
-typedef struct {
-	uint8_t op_code;
-	uint8_t lun_evpd;
-	uint8_t page_code;
-	uint16_t alloc_length;
-	uint8_t ctrl;
-} __attribute__((packed)) scsi_cmd_inquiry_t;
-
-#endif
-
-/**
- * @}
- */
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -72,5 +72,9 @@
 	uint8_t port_count;
 	/** Characteristics bitmask. */
-	uint16_t characteristics;
+	uint8_t characteristics;
+#define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
+#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
+	/* Unused part of characteristics field */
+	uint8_t characteristics_reserved;
 	/** Time from power-on to stabilization of current on the port. */
 	uint8_t power_good_time;
@@ -92,5 +96,5 @@
 
     /** Number of downstream ports that this hub supports */
-    uint8_t ports_count;
+    uint8_t port_count;
 
     /**
@@ -119,6 +123,4 @@
      */
     uint16_t hub_characteristics;
-#define HUB_CHAR_POWER_PER_PORT_FLAG  (1 << 0)
-#define HUB_CHAR_NO_POWER_SWITCH_FLAG (1 << 1)
 
     /**
@@ -214,11 +216,6 @@
  *	Maximum size of usb hub descriptor in bytes
  */
-extern size_t USB_HUB_MAX_DESCRIPTOR_SIZE;
-
-
-
-
-
-
+/* 7 (basic size) + 2*32 (port bitmasks) */
+#define USB_HUB_MAX_DESCRIPTOR_SIZE 71
 
 #endif
Index: uspace/lib/usbdev/include/usb/dev/pipes.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/pipes.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/lib/usbdev/include/usb/dev/pipes.h	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -183,5 +183,5 @@
 int usb_pipe_write(usb_pipe_t *, void *, size_t);
 
-int usb_pipe_control_read(usb_pipe_t *, void *, size_t,
+int usb_pipe_control_read(usb_pipe_t *, const void *, size_t,
     void *, size_t, size_t *);
 int usb_pipe_control_write(usb_pipe_t *, void *, size_t,
Index: uspace/lib/usbdev/src/pipesio.c
===================================================================
--- uspace/lib/usbdev/src/pipesio.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/lib/usbdev/src/pipesio.c	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -328,5 +328,5 @@
  */
 static int usb_pipe_control_read_no_check(usb_pipe_t *pipe,
-    void *setup_buffer, size_t setup_buffer_size,
+    const void *setup_buffer, size_t setup_buffer_size,
     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
 {
@@ -411,5 +411,5 @@
  */
 int usb_pipe_control_read(usb_pipe_t *pipe,
-    void *setup_buffer, size_t setup_buffer_size,
+    const void *setup_buffer, size_t setup_buffer_size,
     void *data_buffer, size_t data_buffer_size, size_t *data_transfered_size)
 {
Index: uspace/srv/hid/input/include/sun.h
===================================================================
--- uspace/srv/hid/input/include/sun.h	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup kbdgen generic
- * @brief Sun keyboard virtual port driver.
- * @ingroup kbd
- * @{
- */
-/** @file
- */
-
-#ifndef KBD_SUN_H_
-#define KBD_SUN_H_
-
-extern int ns16550_port_init(void);
-extern int z8530_port_init(void);
-
-#endif
-
-/**
- * @}
- */
Index: uspace/srv/hid/input/port/dummy.c
===================================================================
--- uspace/srv/hid/input/port/dummy.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,59 +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>
-
-int kbd_port_init(void)
-{
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: uspace/srv/hid/input/port/sgcn.c
===================================================================
--- uspace/srv/hid/input/port/sgcn.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,188 +1,0 @@
-/*
- * Copyright (c) 2008 Pavel Rimsky
- * 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
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief SGCN (Serengeti Console) keyboard port driver.
- */
-
-#include <as.h>
-#include <ddi.h>
-#include <async.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sysinfo.h>
-#include <stdio.h>
-#include <thread.h>
-#include <bool.h>
-#include <errno.h>
-
-#define POLL_INTERVAL  10000
-
-/**
- * SGCN buffer header. It is placed at the very beginning of the SGCN
- * buffer.
- */
-typedef struct {
-	/** hard-wired to "CON" */
-	char magic[4];
-	
-	/** we don't need this */
-	char unused[8];
-	
-	/** offset within the SGCN buffer of the input buffer start */
-	uint32_t in_begin;
-	
-	/** offset within the SGCN buffer of the input buffer end */
-	uint32_t in_end;
-	
-	/** offset within the SGCN buffer of the input buffer read pointer */
-	uint32_t in_rdptr;
-	
-	/** offset within the SGCN buffer of the input buffer write pointer */
-	uint32_t in_wrptr;
-} __attribute__ ((packed)) sgcn_buffer_header_t;
-
-/*
- * Returns a pointer to the object of a given type which is placed at the given
- * offset from the console buffer beginning.
- */
-#define SGCN_BUFFER(type, offset) \
-		((type *) (sram_virt_addr + sram_buffer_offset + (offset)))
-
-/** Returns a pointer to the console buffer header. */
-#define SGCN_BUFFER_HEADER	(SGCN_BUFFER(sgcn_buffer_header_t, 0))
-
-/**
- * Virtual address mapped to SRAM.
- */
-static uintptr_t sram_virt_addr;
-
-/**
- * SGCN buffer offset within SGCN.
- */
-static uintptr_t sram_buffer_offset;
-
-/* polling thread */
-static void sgcn_thread_impl(void *arg);
-
-static volatile bool polling_disabled = false;
-
-/**
- * Initializes the SGCN driver.
- * Maps the physical memory (SRAM) and creates the polling thread. 
- */
-int kbd_port_init(void)
-{
-	sysarg_t sram_paddr;
-	if (sysinfo_get_value("sram.address.physical", &sram_paddr) != EOK)
-		return -1;
-	
-	sysarg_t sram_size;
-	if (sysinfo_get_value("sram.area.size", &sram_size) != EOK)
-		return -1;
-	
-	if (sysinfo_get_value("sram.buffer.offset", &sram_buffer_offset) != EOK)
-		sram_buffer_offset = 0;
-	
-	sram_virt_addr = (uintptr_t) as_get_mappable_page(sram_size);
-	
-	if (physmem_map((void *) sram_paddr, (void *) sram_virt_addr,
-	    sram_size / PAGE_SIZE, AS_AREA_READ | AS_AREA_WRITE) != 0) {
-		printf("SGCN: uspace driver could not map physical memory.");
-		return -1;
-	}
-	
-	thread_id_t tid;
-	int rc = thread_create(sgcn_thread_impl, NULL, "kbd_poll", &tid);
-	if (rc != 0)
-		return rc;
-	
-	return 0;
-}
-
-void kbd_port_yield(void)
-{
-	polling_disabled = true;
-}
-
-void kbd_port_reclaim(void)
-{
-	polling_disabled = false;
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/**
- * Handler of the "key pressed" event. Reads codes of all the pressed keys from
- * the buffer. 
- */
-static void sgcn_key_pressed(void)
-{
-	char c;
-	
-	uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
-	uint32_t end = SGCN_BUFFER_HEADER->in_end;
-	uint32_t size = end - begin;
-	
-	volatile char *buf_ptr = (volatile char *)
-		SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-	volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
-	volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
-	
-	while (*in_rdptr_ptr != *in_wrptr_ptr) {
-		c = *buf_ptr;
-		*in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
-		buf_ptr = (volatile char *)
-			SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
-		kbd_push_scancode(c);
-	}
-}
-
-/**
- * Thread to poll SGCN for keypresses.
- */
-static void sgcn_thread_impl(void *arg)
-{
-	(void) arg;
-
-	while (1) {
-		if (polling_disabled == false)
-			sgcn_key_pressed();
-		usleep(POLL_INTERVAL);
-	}
-}
-
-/** @}
- */
Index: uspace/srv/hid/input/port/sun.c
===================================================================
--- uspace/srv/hid/input/port/sun.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2009 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.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Sun keyboard virtual port driver.
- */
-
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sysinfo.h>
-#include <errno.h>
-#include <bool.h>
-
-/** Sun keyboard virtual port driver.
- *
- * This is a virtual port driver which can use
- * both ns16550_port_init and z8530_port_init
- * according to the information passed from the
- * kernel. This is just a temporal hack.
- *
- */
-int kbd_port_init(void)
-{
-	sysarg_t z8530;
-	if (sysinfo_get_value("kbd.type.z8530", &z8530) != EOK)
-		z8530 = false;
-	
-	sysarg_t ns16550;
-	if (sysinfo_get_value("kbd.type.ns16550", &ns16550) != EOK)
-		ns16550 = false;
-	
-	if (z8530) {
-		if (z8530_port_init() == 0)
-			return 0;
-	}
-	
-	if (ns16550) {
-		if (ns16550_port_init() == 0)
-			return 0;
-	}
-	
-	return -1;
-}
-
-void kbd_port_yield(void)
-{
-}
-
-void kbd_port_reclaim(void)
-{
-}
-
-void kbd_port_write(uint8_t data)
-{
-	(void) data;
-}
-
-/** @}
-*/
Index: uspace/srv/hid/input/port/z8530.c
===================================================================
--- uspace/srv/hid/input/port/z8530.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ 	(revision )
@@ -1,117 +1,0 @@
-/*
- * Copyright (c) 2006 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.
- */
-
-/** @addtogroup kbd_port
- * @ingroup  kbd
- * @{
- */
-/** @file
- * @brief Z8530 keyboard port driver.
- */
-
-#include <ipc/irc.h>
-#include <async.h>
-#include <async_obsolete.h>
-#include <sysinfo.h>
-#include <kbd.h>
-#include <kbd_port.h>
-#include <sun.h>
-#include <sys/types.h>
-#include <ddi.h>
-#include <errno.h>
-
-#define CHAN_A_STATUS  4
-#define CHAN_A_DATA    6
-
-#define RR0_RCA  1
-
-static irq_cmd_t z8530_cmds[] = {
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 1
-	},
-	{
-		.cmd = CMD_BTEST,
-		.value = RR0_RCA,
-		.srcarg = 1,
-		.dstarg = 3
-	},
-	{
-		.cmd = CMD_PREDICATE,
-		.value = 2,
-		.srcarg = 3
-	},
-	{
-		.cmd = CMD_PIO_READ_8,
-		.addr = (void *) 0,     /* Will be patched in run-time */
-		.dstarg = 2
-	},
-	{
-		.cmd = CMD_ACCEPT
-	}
-};
-	
-irq_code_t z8530_kbd = {
-	sizeof(z8530_cmds) / sizeof(irq_cmd_t),
-	z8530_cmds
-};
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call);
-
-int z8530_port_init(void)
-{
-	sysarg_t kaddr;
-	if (sysinfo_get_value("kbd.address.kernel", &kaddr) != EOK)
-		return -1;
-	
-	sysarg_t inr;
-	if (sysinfo_get_value("kbd.inr", &inr) != EOK)
-		return -1;
-	
-	z8530_cmds[0].addr = (void *) kaddr + CHAN_A_STATUS;
-	z8530_cmds[3].addr = (void *) kaddr + CHAN_A_DATA;
-	
-	async_set_interrupt_received(z8530_irq_handler);
-	register_irq(inr, device_assign_devno(), inr, &z8530_kbd);
-	
-	return 0;
-}
-
-static void z8530_irq_handler(ipc_callid_t iid, ipc_call_t *call)
-{
-	int scan_code = IPC_GET_ARG2(*call);
-	kbd_push_scancode(scan_code);
-	
-	if (irc_service)
-		async_obsolete_msg_1(irc_phone, IRC_CLEAR_INTERRUPT,
-		    IPC_GET_IMETHOD(*call));
-}
-
-/** @}
- */
Index: uspace/srv/hw/irc/apic/apic.c
===================================================================
--- uspace/srv/hw/irc/apic/apic.c	(revision 36cb22f7989de9b9af7abf32cfcc1439f618fb10)
+++ uspace/srv/hw/irc/apic/apic.c	(revision 747a1e7105749fffdce7496f06dd8b00b733a1e0)
@@ -206,7 +206,10 @@
 	}
 
-	if (pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE,
-	    (void **) &io_apic) != EOK)
+	int rc = pio_enable((void *) IO_APIC_BASE, IO_APIC_SIZE,
+		(void **) &io_apic);
+	if (rc != EOK) {
+		printf("%s: Failed to enable PIO for APIC: %d\n", NAME, rc);
 		return false;	
+	}
 	
 	async_set_client_connection(apic_connection);
