Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/ohci/root_hub.c	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -115,6 +115,5 @@
 
 static const uint32_t hub_set_feature_valid_mask =
-	(1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT) |
-(1 << USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
+	(1 << USB_HUB_FEATURE_C_HUB_OVER_CURRENT);
 
 
@@ -587,6 +586,4 @@
 	if (!((1 << feature) & hub_set_feature_valid_mask))
 		return EINVAL;
-	if(feature == USB_HUB_FEATURE_C_HUB_LOCAL_POWER)
-		feature = USB_HUB_FEATURE_C_HUB_LOCAL_POWER << 16;
 	instance->registers->rh_status =
 		(instance->registers->rh_status | (1 << feature))
Index: uspace/drv/usbhub/Makefile
===================================================================
--- uspace/drv/usbhub/Makefile	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/usbhub/Makefile	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -34,7 +34,7 @@
 SOURCES = \
 	main.c \
+	ports.c \
 	utils.c \
-	usbhub.c \
-	ports.c
+	usbhub.c
 
 include $(USPACE_PREFIX)/Makefile.common
Index: uspace/drv/usbhub/port_status.h
===================================================================
--- uspace/drv/usbhub/port_status.h	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/usbhub/port_status.h	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -49,14 +49,4 @@
 
 /**
- * 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
@@ -64,6 +54,6 @@
  */
 static inline void usb_hub_set_port_status_request(
-	usb_device_request_setup_packet_t * request, uint16_t port
-	) {
+usb_device_request_setup_packet_t * request, uint16_t port
+){
 	request->index = port;
 	request->request_type = USB_HUB_REQ_TYPE_GET_PORT_STATUS;
@@ -73,18 +63,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;
-}
 
 /**
@@ -94,11 +70,12 @@
  */
 static inline usb_device_request_setup_packet_t *
-usb_hub_create_port_status_request(uint16_t port) {
+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);
+		usb_new(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
@@ -108,7 +85,7 @@
  */
 static inline void usb_hub_set_enable_port_feature_request(
-	usb_device_request_setup_packet_t * request, uint16_t port,
-	uint16_t feature_selector
-	) {
+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;
@@ -125,7 +102,7 @@
  */
 static inline void usb_hub_set_disable_port_feature_request(
-	usb_device_request_setup_packet_t * request, uint16_t port,
-	uint16_t feature_selector
-	) {
+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;
@@ -141,6 +118,6 @@
  */
 static inline void usb_hub_set_enable_port_request(
-	usb_device_request_setup_packet_t * request, uint16_t port
-	) {
+usb_device_request_setup_packet_t * request, uint16_t port
+){
 	request->index = port;
 	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
@@ -156,8 +133,8 @@
  */
 static inline usb_device_request_setup_packet_t *
-usb_hub_create_enable_port_request(uint16_t port) {
+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);
+		usb_new(usb_device_request_setup_packet_t);
+	usb_hub_set_enable_port_request(result,port);
 	return result;
 }
@@ -169,6 +146,6 @@
  */
 static inline void usb_hub_set_disable_port_request(
-	usb_device_request_setup_packet_t * request, uint16_t port
-	) {
+usb_device_request_setup_packet_t * request, uint16_t port
+){
 	request->index = port;
 	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
@@ -184,8 +161,8 @@
  */
 static inline usb_device_request_setup_packet_t *
-usb_hub_create_disable_port_request(uint16_t port) {
+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);
+		usb_new(usb_device_request_setup_packet_t);
+	usb_hub_set_disable_port_request(result,port);
 	return result;
 }
@@ -197,6 +174,6 @@
  */
 static inline void usb_hub_set_reset_port_request(
-	usb_device_request_setup_packet_t * request, uint16_t port
-	) {
+usb_device_request_setup_packet_t * request, uint16_t port
+){
 	request->index = port;
 	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
@@ -212,8 +189,8 @@
  */
 static inline usb_device_request_setup_packet_t *
-usb_hub_create_reset_port_request(uint16_t port) {
+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);
+		usb_new(usb_device_request_setup_packet_t);
+	usb_hub_set_reset_port_request(result,port);
 	return result;
 }
@@ -225,6 +202,6 @@
  */
 static inline void usb_hub_set_power_port_request(
-	usb_device_request_setup_packet_t * request, uint16_t port
-	) {
+usb_device_request_setup_packet_t * request, uint16_t port
+){
 	request->index = port;
 	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
@@ -240,6 +217,6 @@
  */
 static inline void usb_hub_unset_power_port_request(
-	usb_device_request_setup_packet_t * request, uint16_t port
-	) {
+usb_device_request_setup_packet_t * request, uint16_t port
+){
 	request->index = port;
 	request->request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE;
@@ -249,433 +226,146 @@
 }
 
-/**
- * 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))));
-}
-
-
-#if 0
-/**
- * connection status geter for port status
- * 
- * @param status
- * @return true if there is something connected
- */
-static inline bool usb_port_dev_connected(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 0);
-}
-
-/**
- * set device connected bit in port status
- *
- * @param status
- * @param connected value of the bit
- */
-static inline void usb_port_set_dev_connected(usb_port_status_t * status, bool connected) {
-	usb_port_set_bit(status, 0, connected);
+
+/** get i`th bit of port status */
+static inline bool usb_port_get_bit(usb_port_status_t * status, int idx)
+{
+	return (((*status)>>(idx))%2);
+}
+
+/** set i`th bit of port status */
+static inline void usb_port_set_bit(
+	usb_port_status_t * status, int idx, bool value)
+{
+	(*status) = value?
+		               ((*status)|(1<<(idx))):
+		               ((*status)&(~(1<<(idx))));
+}
+
+//device connnected on port
+static inline bool usb_port_dev_connected(usb_port_status_t * status){
+	return usb_port_get_bit(status,0);
+}
+
+static inline void usb_port_set_dev_connected(usb_port_status_t * status,bool connected){
+	usb_port_set_bit(status,0,connected);
 }
 
 //port enabled
-
-/**
- * port enabled getter for port status
- * 
- * @param status
- * @return true if the port is enabled
- */
-static inline bool usb_port_enabled(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 1);
-}
-
-/**
- * set port enabled bit in port status
- *
- * @param status
- * @param enabled value of the bit
- */
-static inline void usb_port_set_enabled(usb_port_status_t * status, bool enabled) {
-	usb_port_set_bit(status, 1, enabled);
+static inline bool usb_port_enabled(usb_port_status_t * status){
+	return usb_port_get_bit(status,1);
+}
+
+static inline void usb_port_set_enabled(usb_port_status_t * status,bool enabled){
+	usb_port_set_bit(status,1,enabled);
 }
 
 //port suspended
-/**
- * port suspended getter for port status
- *
- * @param status
- * @return true if port is suspended
- */
-static inline bool usb_port_suspended(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 2);
-}
-
-/**
- * set port suspended bit in port status
- *
- * @param status
- * @param suspended value of the bit
- */
-static inline void usb_port_set_suspended(usb_port_status_t * status, bool suspended) {
-	usb_port_set_bit(status, 2, suspended);
+static inline bool usb_port_suspended(usb_port_status_t * status){
+	return usb_port_get_bit(status,2);
+}
+
+static inline void usb_port_set_suspended(usb_port_status_t * status,bool suspended){
+	usb_port_set_bit(status,2,suspended);
 }
 
 //over currect
-/**
- * over current condition indicator getter for port status
- *
- * @param status
- * @return true if there is opver-current condition on the hub
- */
-static inline bool usb_port_over_current(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 3);
-}
-
-/**
- * set over current indicator bit in port status
- *
- * @param status
- * @param value value of the bit
- */
-static inline void usb_port_set_over_current(usb_port_status_t * status, bool value) {
-	usb_port_set_bit(status, 3, value);
+static inline bool usb_port_over_current(usb_port_status_t * status){
+	return usb_port_get_bit(status,3);
+}
+
+static inline void usb_port_set_over_current(usb_port_status_t * status,bool value){
+	usb_port_set_bit(status,3,value);
 }
 
 //port reset
-/**
- * port reset indicator getter for port status
- * 
- * @param status
- * @return true if port is reset
- */
-static inline bool usb_port_reset(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 4);
-}
-
-/**
- * set port reset bit in port status
- *
- * @param status
- * @param value value of the bit
- */
-static inline void usb_port_set_reset(usb_port_status_t * status, bool value) {
-	usb_port_set_bit(status, 4, value);
+static inline bool usb_port_reset(usb_port_status_t * status){
+	return usb_port_get_bit(status,4);
+}
+
+static inline void usb_port_set_reset(usb_port_status_t * status,bool value){
+	usb_port_set_bit(status,4,value);
 }
 
 //powered
-/**
- * power state getter for port status
- *
- * @param status
- * @return true if port is powered
- */
-static inline bool usb_port_powered(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 8);
-}
-
-/**
- * set port powered bit in port status
- *
- * @param status
- * @param powered value of the bit
- */
-static inline void usb_port_set_powered(usb_port_status_t * status, bool powered) {
-	usb_port_set_bit(status, 8, powered);
-}
-
-#endif
+static inline bool usb_port_powered(usb_port_status_t * status){
+	return usb_port_get_bit(status,8);
+}
+
+static inline void usb_port_set_powered(usb_port_status_t * status,bool powered){
+	usb_port_set_bit(status,8,powered);
+}
 
 //low speed device attached
-/**
- * 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))
+static inline bool usb_port_low_speed(usb_port_status_t * status){
+	return usb_port_get_bit(status,9);
+}
+
+static inline void usb_port_set_low_speed(usb_port_status_t * status,bool low_speed){
+	usb_port_set_bit(status,9,low_speed);
+}
+
+//low speed device attached
+static inline bool usb_port_high_speed(usb_port_status_t * status){
+	return usb_port_get_bit(status,10);
+}
+
+static inline void usb_port_set_high_speed(usb_port_status_t * status,bool high_speed){
+	usb_port_set_bit(status,10,high_speed);
+}
+
+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))
+	if(usb_port_high_speed(status))
 		return USB_SPEED_HIGH;
 	return USB_SPEED_FULL;
 }
 
-#if 0
+
 //connect change
-/**
- * port connect change indicator
- *
- * @param status
- * @return true if connection has changed
- */
-static inline bool usb_port_connect_change(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 16);
-}
-
-/**
- * set connection change bit in port status
- * @param status
- * @param change value of the bit
- */
-static inline void usb_port_set_connect_change(usb_port_status_t * status, bool change) {
-	usb_port_set_bit(status, 16, change);
+static inline bool usb_port_connect_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,16);
+}
+
+static inline void usb_port_set_connect_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,16,change);
 }
 
 //port enable change
-/**
- * port enable change for port status
- *
- * @param status
- * @return true if the port has been enabled/disabled
- */
-static inline bool usb_port_enabled_change(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 17);
-}
-
-/**
- * set port enable change bit in port status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_port_set_enabled_change(usb_port_status_t * status, bool change) {
-	usb_port_set_bit(status, 17, change);
+static inline bool usb_port_enabled_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,17);
+}
+
+static inline void usb_port_set_enabled_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,17,change);
 }
 
 //suspend change
-/**
- * port suspend change for port status
- * 
- * @param status
- * @return ture if suspend status has changed
- */
-static inline bool usb_port_suspend_change(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 18);
-}
-
-/**
- * set port suspend change bit in port status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_port_set_suspend_change(usb_port_status_t * status, bool change) {
-	usb_port_set_bit(status, 18, change);
+static inline bool usb_port_suspend_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,18);
+}
+
+static inline void usb_port_set_suspend_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,18,change);
 }
 
 //over current change
-/**
- * over current change indicator
- * 
- * @param status
- * @return true if over-current condition on port has changed
- */
-static inline bool usb_port_overcurrent_change(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 19);
-}
-
-/**
- * set port over current change bit in port status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_port_set_overcurrent_change(usb_port_status_t * status, bool change) {
-	usb_port_set_bit(status, 19, change);
+static inline bool usb_port_overcurrent_change(usb_port_status_t * status){
+	return usb_port_get_bit(status,19);
+}
+
+static inline void usb_port_set_overcurrent_change(usb_port_status_t * status,bool change){
+	usb_port_set_bit(status,19,change);
 }
 
 //reset change
-/**
- * port reset change indicator
- * @param status
- * @return true if port has been reset
- */
-static inline bool usb_port_reset_completed(usb_port_status_t * status) {
-	return usb_port_get_bit(status, 20);
-}
-
-/**
- * set port reset completed bit in port status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_port_set_reset_completed(usb_port_status_t * status, bool completed) {
-	usb_port_set_bit(status, 20, completed);
-}
-
-//local power status
-/**
- * local power lost indicator for hub status
- * 
- * @param status
- * @return true if hub is not powered
- */
-static inline bool usb_hub_local_power_lost(usb_hub_status_t * status) {
-	return usb_hub_get_bit(status, 0);
-}
-
-/**
- * set hub power lost bit in hub status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_hub_set_local_power_lost(usb_port_status_t * status,
-	bool power_lost) {
-	usb_hub_set_bit(status, 0, power_lost);
-}
-
-//over current ocndition
-/**
- * hub over-current indicator
- *
- * @param status
- * @return true if over-current condition occurred on hub
- */
-static inline bool usb_hub_over_current(usb_hub_status_t * status) {
-	return usb_hub_get_bit(status, 1);
-}
-
-/**
- * set hub over current bit in hub status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_hub_set_over_current(usb_port_status_t * status,
-	bool over_current) {
-	usb_hub_set_bit(status, 1, over_current);
-}
-
-//local power change
-/**
- * hub power change indicator
- *
- * @param status
- * @return true if local power status has been changed - power has been
- * dropped or re-established
- */
-static inline bool usb_hub_local_power_change(usb_hub_status_t * status) {
-	return usb_hub_get_bit(status, 16);
-}
-
-/**
- * set hub power change bit in hub status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_hub_set_local_power_change(usb_port_status_t * status,
-	bool change) {
-	usb_hub_set_bit(status, 16, change);
-}
-
-//local power status
-/**
- * hub over-current condition change indicator
- *
- * @param status
- * @return true if over-current condition has changed
- */
-static inline bool usb_hub_over_current_change(usb_hub_status_t * status) {
-	return usb_hub_get_bit(status, 17);
-}
-
-/**
- * set hub over current change bit in hub status
- *
- * @param status
- * @param change value of the bit
- */
-static inline void usb_hub_set_over_current_change(usb_port_status_t * status,
-	bool change) {
-	usb_hub_set_bit(status, 17, change);
-}
-#endif
+static inline bool usb_port_reset_completed(usb_port_status_t * status){
+	return usb_port_get_bit(status,20);
+}
+
+static inline void usb_port_set_reset_completed(usb_port_status_t * status,bool completed){
+	usb_port_set_bit(status,20,completed);
+}
+
 
 
Index: uspace/drv/usbhub/ports.c
===================================================================
--- uspace/drv/usbhub/ports.c	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
+++ uspace/drv/usbhub/ports.c	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -0,0 +1,331 @@
+/*
+ * 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 "port_status.h"
+#include <inttypes.h>
+#include <errno.h>
+#include <str_error.h>
+#include <usb/request.h>
+#include <usb/debug.h>
+
+/** 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;
+}
+
+/** Information for fibril for device discovery. */
+struct add_device_phase1 {
+	usb_hub_info_t *hub;
+	size_t port;
+	usb_speed_t speed;
+};
+
+/** 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 = (usb_hub_info_t *) 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);
+
+	/* Clear the port reset change. */
+	rc = usb_hub_clear_port_feature(hub->control_pipe,
+	    port_no, USB_HUB_FEATURE_C_PORT_RESET);
+	if (rc != EOK) {
+		usb_log_error("Failed to clear port %d reset feature: %s.\n",
+		    port_no, str_error(rc));
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** 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;
+	}
+
+	data->hub->ports[data->port].attached_device.handle = child_handle;
+	data->hub->ports[data->port].attached_device.address = new_address;
+
+	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);
+
+	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 add_device_phase1_new_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_add_ready(fibril);
+
+	return EOK;
+}
+
+/** Process change on a single port.
+ *
+ * @param hub Hub to which the port belongs.
+ * @param port Port index (starting at 1).
+ */
+static void process_port_change(usb_hub_info_t *hub, size_t port)
+{
+	int rc;
+
+	usb_port_status_t port_status;
+
+	rc = get_port_status(&hub->usb_device->ctrl_pipe, port, &port_status);
+	if (rc != EOK) {
+		usb_log_error("Failed to get port %zu status: %s.\n",
+		    port, str_error(rc));
+		return;
+	}
+
+	/*
+	 * Check exact nature of the change.
+	 */
+	usb_log_debug("Port %zu change status: %x.\n", port,
+	    (unsigned int) port_status);
+
+	if (usb_port_connect_change(&port_status)) {
+		bool device_connected = usb_port_dev_connected(&port_status);
+		usb_log_debug("Connection change on port %zu: %s.\n", port,
+		    device_connected ? "device attached" : "device removed");
+
+		if (device_connected) {
+			rc = add_device_phase1_new_fibril(hub, port,
+			    usb_port_speed(&port_status));
+			if (rc != EOK) {
+				usb_log_error(
+				    "Cannot handle change on port %zu: %s.\n",
+				    str_error(rc));
+			}
+		} else {
+			usb_hub_removed_device(hub, port);
+		}
+	}
+
+	if (usb_port_overcurrent_change(&port_status)) {
+		if (usb_port_over_current(&port_status)) {
+			usb_log_warning("Overcurrent on port %zu.\n", port);
+			usb_hub_over_current(hub, port);
+		} else {
+			usb_log_debug("Overcurrent on port %zu autoresolved.\n",
+			    port);
+		}
+	}
+
+	if (usb_port_reset_completed(&port_status)) {
+		usb_log_debug("Port %zu reset complete.\n", port);
+		if (usb_port_enabled(&port_status)) {
+			/* Finalize device adding. */
+			usb_hub_port_t *the_port = hub->ports + port;
+			fibril_mutex_lock(&the_port->reset_mutex);
+			the_port->reset_completed = 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",
+			    port);
+		}
+	}
+
+	usb_port_set_connect_change(&port_status, false);
+	usb_port_set_reset(&port_status, false);
+	usb_port_set_reset_completed(&port_status, false);
+	usb_port_set_dev_connected(&port_status, false);
+	if (port_status >> 16) {
+		usb_log_warning("Unsupported change on port %zu: %x.\n",
+		    port, (unsigned int) port_status);
+	}
+}
+
+
+/** Callback for polling hub for port changes.
+ *
+ * @param dev Device where the change occured.
+ * @param change_bitmap Bitmap of changed ports.
+ * @param change_bitmap_size Size of the bitmap in bytes.
+ * @param arg Custom argument, points to @c usb_hub_info_t.
+ * @return Whether to continue polling.
+ */
+bool hub_port_changes_callback(usb_device_t *dev,
+    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg)
+{
+	usb_hub_info_t *hub = (usb_hub_info_t *) arg;
+
+	/* FIXME: check that we received enough bytes. */
+	if (change_bitmap_size == 0) {
+		goto leave;
+	}
+
+	size_t port;
+	for (port = 1; port < hub->port_count + 1; port++) {
+		bool change = (change_bitmap[port / 8] >> (port % 8)) % 2;
+		if (change) {
+			process_port_change(hub, port);
+		}
+	}
+
+
+leave:
+	/* FIXME: proper interval. */
+	async_usleep(1000 * 1000 * 10 );
+
+	return true;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/drv/usbhub/ports.h
===================================================================
--- uspace/drv/usbhub/ports.h	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
+++ uspace/drv/usbhub/ports.h	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -0,0 +1,80 @@
+/*
+ * 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 <ipc/devman.h>
+#include <usb/usb.h>
+#include <ddf/driver.h>
+#include <fibril_synch.h>
+
+#include <usb/hub.h>
+
+#include <usb/pipes.h>
+#include <usb/devdrv.h>
+
+/** 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;
+
+	/** 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);
+}
+
+bool hub_port_changes_callback(usb_device_t *, uint8_t *, size_t, void *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/usbhub/usbhub.c	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -37,5 +37,4 @@
 #include <errno.h>
 #include <str_error.h>
-#include <inttypes.h>
 
 #include <usb_iface.h>
@@ -54,23 +53,7 @@
 #include "usb/classes/classes.h"
 
-
-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,
-    usb_hub_status_t status);
-
-static int usb_process_hub_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);
-
-
-/// \TODO malloc checking
+static int usb_hub_trigger_connecting_non_removable_devices(
+		usb_hub_info_t * hub, usb_hub_descriptor_t * descriptor);
+
 
 //*********************************************
@@ -81,129 +64,4 @@
 
 /**
- * Initialize hub device driver fibril
- *
- * 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;
-	usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
-	//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, "
-		    "errno %d\n",
-		    opResult);
-		free(hub_info);
-		return opResult;
-	}
-
-	usb_pipe_start_session(hub_info->control_pipe);
-	//set hub configuration
-	opResult = usb_hub_set_configuration(hub_info);
-	if (opResult != EOK) {
-		usb_log_error("could not set hub configuration, errno %d\n",
-		    opResult);
-		free(hub_info);
-		return opResult;
-	}
-	//get port count and create attached_devs
-	opResult = usb_hub_process_hub_specific_info(hub_info);
-	if (opResult != EOK) {
-		usb_log_error("could process hub specific info, errno %d\n",
-		    opResult);
-		free(hub_info);
-		return opResult;
-	}
-	usb_pipe_end_session(hub_info->control_pipe);
-
-	/// \TODO what is this?
-	usb_log_debug("Creating `hub' function.\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;
-
-	opResult = ddf_fun_bind(hub_fun);
-	assert(opResult == EOK);
-	opResult = ddf_fun_add_to_class(hub_fun, "hub");
-	assert(opResult == EOK);
-
-	opResult = usb_hub_start_hub_fibril(hub_info);
-	if(opResult!=EOK)
-		free(hub_info);
-	return opResult;
-}
-
-
-/** Callback for polling hub for changes.
- *
- * @param dev Device where the change occured.
- * @param change_bitmap Bitmap of changed ports.
- * @param change_bitmap_size Size of the bitmap in bytes.
- * @param arg Custom argument, points to @c usb_hub_info_t.
- * @return Whether to continue polling.
- */
-bool hub_port_changes_callback(usb_device_t *dev,
-    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg) {
-	usb_hub_info_t *hub = (usb_hub_info_t *) arg;
-
-	/* FIXME: check that we received enough bytes. */
-	if (change_bitmap_size == 0) {
-		goto leave;
-	}
-
-	bool change;
-	change = ((uint8_t*) 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;
-		if (change) {
-			usb_hub_process_interrupt(hub, port);
-		}
-	}
-leave:
-	/* FIXME: proper interval. */
-	async_usleep(1000 * 1000 * 10);
-
-	return true;
-}
-
-/**
- * release default address used by given hub
- *
- * Also unsets hub->is_default_address_used. Convenience wrapper function.
- * @note hub->connection MUST be open for communication
- * @param hub hub representation
- * @return error code
- */
-int usb_hub_release_default_address(usb_hub_info_t * hub) {
-	int opResult = usb_hc_release_default_address(&hub->connection);
-	if (opResult != EOK) {
-		usb_log_error("could not release default address, errno %d\n",
-		    opResult);
-		return opResult;
-	}
-	hub->is_default_address_used = false;
-	return EOK;
-}
-
-
-//*********************************************
-//
-//  support functions
-//
-//*********************************************
-
-/**
  * create usb_hub_info_t structure
  *
@@ -213,6 +71,6 @@
  */
 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;
+	usb_hub_info_t * result = usb_new(usb_hub_info_t);
+	if(!result) return NULL;
 	result->usb_device = usb_dev;
 	result->status_change_pipe = usb_dev->pipes[0].pipe;
@@ -232,21 +90,29 @@
  * @return error code
  */
-static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info) {
+static int usb_hub_process_hub_specific_info(usb_hub_info_t * hub_info){
 	// get hub descriptor
 	usb_log_debug("creating serialized descriptor\n");
 	void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
 	usb_hub_descriptor_t * descriptor;
-	int opResult;
-
+
+	/* this was one fix of some bug, should not be needed anymore
+	 * these lines allow to reset hub once more, it can be used as
+	 * brute-force initialization for non-removable devices
+	int opResult = usb_request_set_configuration(&result->endpoints.control, 1);
+	if(opResult!=EOK){
+		usb_log_error("could not set default configuration, errno %d",opResult);
+		return opResult;
+	}
+	 */
 	size_t received_size;
-	opResult = usb_request_get_descriptor(hub_info->control_pipe,
-	    USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
-	    USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
-	    USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
+	int opResult = usb_request_get_descriptor(&hub_info->usb_device->ctrl_pipe,
+			USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
+			USB_DESCTYPE_HUB,
+			0, 0, serialized_descriptor,
+			USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
 
 	if (opResult != EOK) {
-		usb_log_error("failed when receiving hub descriptor, "
-		    "badcode = %d\n",
-		    opResult);
+		usb_log_error("failed when receiving hub descriptor, badcode = %d\n",
+				opResult);
 		free(serialized_descriptor);
 		return opResult;
@@ -254,17 +120,17 @@
 	usb_log_debug2("deserializing descriptor\n");
 	descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
-	if (descriptor == NULL) {
+	if(descriptor==NULL){
 		usb_log_warning("could not deserialize descriptor \n");
 		return opResult;
 	}
-	usb_log_debug("setting port count to %d\n", descriptor->ports_count);
+	usb_log_debug("setting port count to %d\n",descriptor->ports_count);
 	hub_info->port_count = descriptor->ports_count;
-	/// \TODO this is not semantically correct
-	hub_info->ports = malloc(
-	    sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
+	hub_info->ports = malloc(sizeof(usb_hub_port_t) * (hub_info->port_count+1));
 	size_t port;
 	for (port = 0; port < hub_info->port_count + 1; port++) {
 		usb_hub_port_init(&hub_info->ports[port]);
 	}
+	//handle non-removable devices
+	usb_hub_trigger_connecting_non_removable_devices(hub_info, descriptor);
 	usb_log_debug2("freeing data\n");
 	free(serialized_descriptor);
@@ -273,5 +139,4 @@
 	return EOK;
 }
-
 /**
  * Set configuration of hub
@@ -282,5 +147,5 @@
  * @return error code
  */
-static int usb_hub_set_configuration(usb_hub_info_t * hub_info) {
+static int usb_hub_set_configuration(usb_hub_info_t * hub_info){
 	//device descriptor
 	usb_standard_device_descriptor_t *std_descriptor
@@ -288,5 +153,5 @@
 	usb_log_debug("hub has %d configurations\n",
 	    std_descriptor->configuration_count);
-	if (std_descriptor->configuration_count < 1) {
+	if(std_descriptor->configuration_count<1){
 		usb_log_error("there are no configurations available\n");
 		return EINVAL;
@@ -308,5 +173,5 @@
 	}
 	usb_log_debug("\tused configuration %d\n",
-	    config_descriptor->configuration_number);
+			config_descriptor->configuration_number);
 
 	return EOK;
@@ -314,13 +179,56 @@
 
 /**
- * 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
+ * Initialize hub device driver fibril
+ *
+ * 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
  */
-static int usb_hub_start_hub_fibril(usb_hub_info_t * hub_info){
+int usb_hub_add_device(usb_device_t * usb_dev){
+	if(!usb_dev) return EINVAL;
+	usb_hub_info_t * hub_info = usb_hub_info_create(usb_dev);
+	//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, errno %d\n",
+				opResult);
+		free(hub_info);
+		return opResult;
+	}
+	
+	usb_pipe_start_session(hub_info->control_pipe);
+	//set hub configuration
+	opResult = usb_hub_set_configuration(hub_info);
+	if(opResult!=EOK){
+		usb_log_error("could not set hub configuration, errno %d\n",opResult);
+		free(hub_info);
+		return opResult;
+	}
+	//get port count and create attached_devs
+	opResult = usb_hub_process_hub_specific_info(hub_info);
+	if(opResult!=EOK){
+		usb_log_error("could not set hub configuration, errno %d\n",opResult);
+		free(hub_info);
+		return opResult;
+	}
+	usb_pipe_end_session(hub_info->control_pipe);
+
+
+	/// \TODO what is this?
+	usb_log_debug("Creating `hub' function.\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;
+
+	int rc = ddf_fun_bind(hub_fun);
+	assert(rc == EOK);
+	rc = ddf_fun_add_to_class(hub_fun, "hub");
+	assert(rc == EOK);
+
 	/*
 	 * The processing will require opened control pipe and connection
@@ -331,20 +239,20 @@
 	 * auto destruction, this could work better.
 	 */
-	int rc = usb_pipe_start_session(hub_info->control_pipe);
+	rc = usb_pipe_start_session(&usb_dev->ctrl_pipe);
 	if (rc != EOK) {
 		usb_log_error("Failed to start session on control pipe: %s.\n",
 		    str_error(rc));
-		return rc;
+		goto leave;
 	}
 	rc = usb_hc_connection_open(&hub_info->connection);
 	if (rc != EOK) {
-		usb_pipe_end_session(hub_info->control_pipe);
+		usb_pipe_end_session(&usb_dev->ctrl_pipe);
 		usb_log_error("Failed to open connection to HC: %s.\n",
 		    str_error(rc));
-		return rc;
+		goto leave;
 	}
 
 	rc = usb_device_auto_poll(hub_info->usb_device, 0,
-	    hub_port_changes_callback, ((hub_info->port_count + 1) / 8) + 1,
+	    hub_port_changes_callback, ((hub_info->port_count+1) / 8) + 1,
 	    NULL, hub_info);
 	if (rc != EOK) {
@@ -358,119 +266,197 @@
 	    hub_info->usb_device->ddf_dev->name, hub_info->port_count);
 	return EOK;
-}
+
+leave:
+	free(hub_info);
+
+	return rc;
+}
+
 
 //*********************************************
 //
-//  change handling functions
+//  hub driver code, main loop and port handling
 //
 //*********************************************
 
-
-/**
- * process hub over current change
- *
- * This means either to power off the hub or power it on.
- * @param hub_info hub instance
- * @param status hub status bitmask
+/**
+ * triggers actions to connect non0removable devices
+ *
+ * This will trigger operations leading to activated non-removable device.
+ * Control pipe of the hub must be open fo communication.
+ * @param hub hub representation
+ * @param descriptor usb hub descriptor
  * @return error code
  */
-static int usb_process_hub_over_current(usb_hub_info_t * hub_info,
-    usb_hub_status_t status) {
+static int usb_hub_trigger_connecting_non_removable_devices(usb_hub_info_t * hub,
+		usb_hub_descriptor_t * descriptor)
+{
+	usb_log_info("attaching non-removable devices(if any)\n");
+	usb_device_request_setup_packet_t request;
 	int opResult;
-	if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_OVER_CURRENT)){
-		opResult = usb_hub_clear_feature(hub_info->control_pipe,
-		    USB_HUB_FEATURE_HUB_LOCAL_POWER);
-		if (opResult != EOK) {
-			usb_log_error("cannot power off hub: %d\n",
-			    opResult);
-		}
-	} else {
-		opResult = usb_hub_set_feature(hub_info->control_pipe,
-		    USB_HUB_FEATURE_HUB_LOCAL_POWER);
-		if (opResult != EOK) {
-			usb_log_error("cannot power on hub: %d\n",
-			    opResult);
-		}
-	}
-	return opResult;
-}
-
-/**
- * process hub power change
- *
- * If the power has been lost, reestablish it.
- * If it was reestablished, re-power all ports.
- * @param hub_info hub instance
- * @param status hub status bitmask
- * @return error code
- */
-static int usb_process_hub_power_change(usb_hub_info_t * hub_info,
-    usb_hub_status_t status) {
-	int opResult;
-	if (usb_hub_is_status(status,USB_HUB_FEATURE_HUB_LOCAL_POWER)) {
-		//restart power on hub
-		opResult = usb_hub_set_feature(hub_info->control_pipe,
-		    USB_HUB_FEATURE_HUB_LOCAL_POWER);
-		if (opResult != EOK) {
-			usb_log_error("cannot power on hub: %d\n",
-			    opResult);
-		}
-	} else {//power reestablished on hub- restart ports
-		size_t port;
-		for (port = 0; port < hub_info->port_count; ++port) {
-			opResult = usb_hub_set_port_feature(
-			    hub_info->control_pipe,
-			    port, USB_HUB_FEATURE_PORT_POWER);
+	size_t rcvd_size;
+	usb_port_status_t status;
+	uint8_t * non_removable_dev_bitmap = descriptor->devices_removable;
+	int port;
+	for(port=1;port<=descriptor->ports_count;++port){
+		bool is_non_removable =
+				((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
+		if(is_non_removable){
+			usb_log_debug("non-removable device on port %d\n",port);
+			usb_hub_set_port_status_request(&request, port);
+			opResult = usb_pipe_control_read(
+					hub->control_pipe,
+					&request, sizeof(usb_device_request_setup_packet_t),
+					&status, 4, &rcvd_size
+					);
 			if (opResult != EOK) {
-				usb_log_error("cannot power on port %d;  %d\n",
-				    port, opResult);
+				usb_log_error("could not get port status of port %d errno:%d\n",
+						port, opResult);
+				return opResult;
+			}
+			//set the status change bit, so it will be noticed in driver loop
+			if(usb_port_dev_connected(&status)){
+				usb_hub_set_disable_port_feature_request(&request, port,
+						USB_HUB_FEATURE_PORT_CONNECTION);
+				opResult = usb_pipe_control_read(
+						hub->control_pipe,
+						&request, sizeof(usb_device_request_setup_packet_t),
+						&status, 4, &rcvd_size
+						);
+				if (opResult != EOK) {
+					usb_log_warning(
+							"could not clear port connection on port %d errno:%d\n",
+							port, opResult);
+				}
+				usb_log_debug("cleared port connection\n");
+				usb_hub_set_enable_port_feature_request(&request, port,
+						USB_HUB_FEATURE_PORT_ENABLE);
+				opResult = usb_pipe_control_read(
+						hub->control_pipe,
+						&request, sizeof(usb_device_request_setup_packet_t),
+						&status, 4, &rcvd_size
+						);
+				if (opResult != EOK) {
+					usb_log_warning(
+							"could not set port enabled on port %d errno:%d\n",
+							port, opResult);
+				}
+				usb_log_debug("port set to enabled - should lead to connection change\n");
 			}
 		}
 	}
-	return opResult;
-}
-
-/**
- * process hub interrupts
- *
- * The change can be either in the over-current condition or
- * local-power lost condition.
- * @param hub_info hub instance
- */
-static void usb_hub_process_global_interrupt(usb_hub_info_t * hub_info) {
-	usb_log_debug("global interrupt on a hub\n");
-	usb_pipe_t *pipe = hub_info->control_pipe;
+	/// \TODO this is just a debug code
+	for(port=1;port<=descriptor->ports_count;++port){
+		bool is_non_removable =
+				((non_removable_dev_bitmap[port/8]) >> (port%8)) %2;
+		if(is_non_removable){
+			usb_log_debug("port %d is non-removable\n",port);
+			usb_port_status_t status;
+			size_t rcvd_size;
+			usb_device_request_setup_packet_t request;
+			//int opResult;
+			usb_hub_set_port_status_request(&request, port);
+			//endpoint 0
+			opResult = usb_pipe_control_read(
+					hub->control_pipe,
+					&request, sizeof(usb_device_request_setup_packet_t),
+					&status, 4, &rcvd_size
+					);
+			if (opResult != EOK) {
+				usb_log_error("could not get port status %d\n",opResult);
+			}
+			if (rcvd_size != sizeof (usb_port_status_t)) {
+				usb_log_error("received status has incorrect size\n");
+			}
+			//something connected/disconnected
+			if (usb_port_connect_change(&status)) {
+				usb_log_debug("some connection changed\n");
+			}
+			usb_log_debug("status: %s\n",usb_debug_str_buffer(
+					(uint8_t *)&status,4,4));
+		}
+	}
+	return EOK;
+}
+
+
+/**
+ * release default address used by given hub
+ *
+ * Also unsets hub->is_default_address_used. Convenience wrapper function.
+ * @note hub->connection MUST be open for communication
+ * @param hub hub representation
+ * @return error code
+ */
+static int usb_hub_release_default_address(usb_hub_info_t * hub){
+	int opResult = usb_hc_release_default_address(&hub->connection);
+	if(opResult!=EOK){
+		usb_log_error("could not release default address, errno %d\n",opResult);
+		return opResult;
+	}
+	hub->is_default_address_used = false;
+	return EOK;
+}
+
+/**
+ * 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
+ */
+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
+	if(hub->ports[port].attached_device.address >= 0){
+		/*uncomment this code to use it when DDF allows device removal
+		opResult = usb_hc_unregister_device(
+				&hub->connection, hub->attached_devs[port].address);
+		if(opResult != EOK) {
+			dprintf(USB_LOG_LEVEL_WARNING, "could not release address of " \
+			    "removed device: %d", opResult);
+		}
+		hub->attached_devs[port].address = 0;
+		hub->attached_devs[port].handle = 0;
+		 */
+	}else{
+		usb_log_warning("this is strange, disconnected device had no address\n");
+		//device was disconnected before it`s port was reset - return default address
+		usb_hub_release_default_address(hub);
+	}
+}
+
+
+/**
+ * Process over current condition on port.
+ * 
+ * Turn off the power on the port.
+ *
+ * @param hub hub representation
+ * @param port port number, starting from 1
+ */
+void usb_hub_over_current( usb_hub_info_t * hub,
+		uint16_t port){
 	int opResult;
-
-	usb_port_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
-	    );
-	if (opResult != EOK) {
-		usb_log_error("could not get hub status\n");
-		return;
-	}
-	if (rcvd_size != sizeof (usb_port_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_power_change(hub_info, status);
-	}
-}
+	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;  %d\n",
+				port, opResult);
+	}
+}
+
 
 /**
Index: uspace/drv/usbhub/usbhub.h
===================================================================
--- uspace/drv/usbhub/usbhub.h	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/usbhub/usbhub.h	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -37,15 +37,13 @@
 
 #include <ipc/devman.h>
+#include <usb/usb.h>
 #include <ddf/driver.h>
 
+#define NAME "usbhub"
+
 #include <usb/hub.h>
-#include <usb/classes/hub.h>
 
 #include <usb/pipes.h>
 #include <usb/devdrv.h>
-
-#include <fibril_synch.h>
-
-#define NAME "usbhub"
 
 #include "ports.h"
@@ -54,11 +52,11 @@
 
 /** Information about attached hub. */
-typedef struct usb_hub_info_t{
+typedef struct {
 	/** Number of ports. */
 	size_t port_count;
 
-	/** attached device handles, for each port one */
+	/** Ports. */
 	usb_hub_port_t *ports;
-
+	
 	/** connection to hcd */
 	usb_hc_connection_t connection;
@@ -91,12 +89,22 @@
 } usb_hub_info_t;
 
-//int usb_hub_control_loop(void * hub_info_param);
+/**
+ * function running the hub-controlling loop.
+ * @param hub_info_param hub info pointer
+ */
+int usb_hub_control_loop(void * hub_info_param);
+
+/**
+ * Check changes on specified hub
+ * @param hub_info_param pointer to usb_hub_info_t structure
+ * @return error code if there is problem when initializing communication with
+ * hub, EOK otherwise
+ */
+int usb_hub_check_hub_changes(usb_hub_info_t * hub_info_param);
+
+void usb_hub_removed_device(usb_hub_info_t *, uint16_t);
+void usb_hub_over_current(usb_hub_info_t *, uint16_t);
 
 int usb_hub_add_device(usb_device_t * usb_dev);
-
-bool hub_port_changes_callback(usb_device_t *dev,
-    uint8_t *change_bitmap, size_t change_bitmap_size, void *arg);
-
-int usb_hub_release_default_address(usb_hub_info_t * hub);
 
 #endif
Index: uspace/drv/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/usbhub/usbhub_private.h	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/usbhub/usbhub_private.h	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -54,6 +54,16 @@
 //
 //************
+#define usb_new(type) (type*)malloc(sizeof(type))
 
 
+/**
+ * Create hub structure instance
+ *
+ * Set the address and port count information most importantly.
+ *
+ * @param device
+ * @param hc host controller phone
+ * @return
+ */
 usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device);
 
@@ -100,71 +110,4 @@
 
 /**
- * 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_CLEAR_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);
-}
-
-/**
  * create uint8_t array with serialized descriptor
  *
Index: uspace/drv/usbhub/utils.c
===================================================================
--- uspace/drv/usbhub/utils.c	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/drv/usbhub/utils.c	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -60,7 +60,7 @@
 	size_t size = 7;
 	//variable size according to port count
-	size_t var_size = (descriptor->ports_count+7)/8;
+	size_t var_size = descriptor->ports_count / 8 + ((descriptor->ports_count % 8 > 0) ? 1 : 0);
 	size += 2 * var_size;
-	uint8_t * result = malloc(size);
+	uint8_t * result = (uint8_t*) malloc(size);
 	//size
 	result[0] = size;
@@ -84,15 +84,13 @@
 }
 
-usb_hub_descriptor_t * usb_deserialize_hub_desriptor(
-void * serialized_descriptor) {
-	uint8_t * sdescriptor = serialized_descriptor;
+usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * serialized_descriptor) {
+	uint8_t * sdescriptor = (uint8_t*) serialized_descriptor;
 
 	if (sdescriptor[1] != USB_DESCTYPE_HUB) {
-		usb_log_warning("trying to deserialize wrong descriptor %x\n",
-		    sdescriptor[1]);
+		usb_log_warning("trying to deserialize wrong descriptor %x\n",sdescriptor[1]);
 		return NULL;
 	}
 
-	usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));
+	usb_hub_descriptor_t * result = usb_new(usb_hub_descriptor_t);
 	
 
@@ -102,5 +100,6 @@
 	result->pwr_on_2_good_time = sdescriptor[5];
 	result->current_requirement = sdescriptor[6];
-	size_t var_size = (result->ports_count+7) / 8;
+	size_t var_size = result->ports_count / 8 + ((result->ports_count % 8 > 0)
+			? 1 : 0);
 	result->devices_removable = (uint8_t*) malloc(var_size);
 
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision a43f1d1803f452027e7beaecba090ca3e630eb93)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision 97e7e8a70330c256968bd5e7f1b93f1af20ea83f)
@@ -43,6 +43,4 @@
  */
 typedef enum {
-	USB_HUB_FEATURE_HUB_LOCAL_POWER = 0,
-	USB_HUB_FEATURE_HUB_OVER_CURRENT = 1,
 	USB_HUB_FEATURE_C_HUB_LOCAL_POWER = 0,
 	USB_HUB_FEATURE_C_HUB_OVER_CURRENT = 1,
@@ -61,5 +59,4 @@
 	/* USB_HUB_FEATURE_ = , */
 } usb_hub_class_feature_t;
-
 
 /** Header of standard hub descriptor without the "variadic" part. */
