Index: uspace/drv/bus/usb/usbhub/port.c
===================================================================
--- uspace/drv/bus/usb/usbhub/port.c	(revision 4559d89ac561755592cea26674efa0c2600702c1)
+++ uspace/drv/bus/usb/usbhub/port.c	(revision 0212751b83cd89c71fbf30d67cdb8bd0aa594cd2)
@@ -128,14 +128,15 @@
  * @param port port number, starting from 1
  */
-void usb_hub_port_process_interrupt(usb_hub_info_t *hub, size_t port)
-{
-	usb_log_debug("Interrupt at port %zu\n", port);
+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(&hub->ports[port], &status);
+	const int opResult = get_port_status(port, &status);
 	if (opResult != EOK) {
 		usb_log_error("Failed to get port %zu status: %s.\n",
-		    port, str_error(opResult));
+		    port->port_number, str_error(opResult));
 		return;
 	}
@@ -143,28 +144,26 @@
 	/* Connection change */
 	if (status & USB_HUB_PORT_C_STATUS_CONNECTION) {
-		const bool device_connected =
+		const bool connected =
 		    (status & USB_HUB_PORT_STATUS_CONNECTION) != 0;
 		usb_log_debug("Connection change on port %zu: device %s.\n",
-		    port, device_connected ? "attached" : "removed");
+		    port->port_number, connected ? "attached" : "removed");
 		/* ACK the change */
-		const int opResult =
-		    usb_hub_port_clear_feature(&hub->ports[port],
-		        USB_HUB_FEATURE_C_PORT_CONNECTION);
+		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 (device_connected) {
-			const int opResult = create_add_device_fibril(hub, port,
-			    usb_port_speed(status));
+			usb_log_warning("Failed to clear port-change-connection"
+			    " flag: %s.\n", str_error(opResult));
+		}
+
+		if (connected) {
+			const int opResult = create_add_device_fibril(hub,
+			    port->port_number, usb_port_speed(status));
 			if (opResult != EOK) {
 				usb_log_error(
 				    "Cannot handle change on port %zu: %s.\n",
-				    port, str_error(opResult));
+				    port->port_number, str_error(opResult));
 			}
 		} else {
-			usb_hub_port_removed_device(&hub->ports[port]);
+			usb_hub_port_removed_device(port);
 		}
 	}
@@ -172,6 +171,12 @@
 	/* Enable change, ports are automatically disabled on errors. */
 	if (status & USB_HUB_PORT_C_STATUS_ENABLED) {
-		// TODO: Remove device that was connected
-		// TODO: Clear feature C_PORT_ENABLE
+		usb_hub_port_removed_device(port);
+		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));
+		}
 
 	}
@@ -180,6 +185,13 @@
 	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);
-		// TODO: Clear feature C_PORT_SUSPEND
+		    "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));
+		}
 	}
 
@@ -190,18 +202,30 @@
 		 * Hub device is responsible for putting port in power off
 		 * mode. USB system software is responsible for powering port
-		 * back on when the over-curent condition is gone */
+		 * 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)) {
-			// TODO: Power port on, this will cause connect
-			// change and device initialization.
-		}
-		// TODO: Ack over-power change.
+			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(&hub->ports[port], status);
-	}
-
-	usb_log_debug("Port %zu status 0x%08" PRIx32 "\n", port, status);
+		usb_hub_port_reset_completed(port, status);
+	}
+
+	usb_log_debug("Port %zu status 0x%08" PRIx32 "\n",
+	    port->port_number, status);
 }
 
Index: uspace/drv/bus/usb/usbhub/port.h
===================================================================
--- uspace/drv/bus/usb/usbhub/port.h	(revision 4559d89ac561755592cea26674efa0c2600702c1)
+++ uspace/drv/bus/usb/usbhub/port.h	(revision 0212751b83cd89c71fbf30d67cdb8bd0aa594cd2)
@@ -79,5 +79,5 @@
 
 void usb_hub_port_reset_fail(usb_hub_port_t *port);
-void usb_hub_port_process_interrupt(usb_hub_info_t *hub, size_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);
Index: uspace/drv/bus/usb/usbhub/usbhub.c
===================================================================
--- uspace/drv/bus/usb/usbhub/usbhub.c	(revision 4559d89ac561755592cea26674efa0c2600702c1)
+++ uspace/drv/bus/usb/usbhub/usbhub.c	(revision 0212751b83cd89c71fbf30d67cdb8bd0aa594cd2)
@@ -170,8 +170,9 @@
 	usb_log_debug("hub_port_changes_callback\n");
 	usb_hub_info_t *hub = arg;
-
-	/* FIXME: check that we received enough bytes. */
+	assert(hub);
+
+	/* It is an error condition if we didn't receive enough data */
 	if (change_bitmap_size == 0) {
-		goto leave;
+		return false;
 	}
 
@@ -187,12 +188,7 @@
 		const bool change = (change_bitmap[port / 8] >> (port % 8)) & 1;
 		if (change) {
-			usb_hub_port_process_interrupt(hub, port);
+			usb_hub_port_process_interrupt(&hub->ports[port], hub);
 		}
 	}
-leave:
-	/* FIXME: proper interval. */
-	// TODO Interval should be handled by USB HC scheduler not here
-	async_usleep(1000 * 250);
-
 	return true;
 }
@@ -256,5 +252,5 @@
 	hub_info->port_count = descriptor.port_count;
 
-	// TODO Why +1 ?
+	// TODO: +1 hack is no longer necessary
 	hub_info->ports =
 	    malloc(sizeof(usb_hub_port_t) * (hub_info->port_count + 1));
@@ -349,20 +345,7 @@
 {
 	if (status & USB_HUB_STATUS_OVER_CURRENT) {
-		/* Over-current detected on one or all ports,
-		 * switch them all off to prevent damage. */
-		//TODO Consider ganged power switching here.
-		//TODO Hub should have turned the ports off already,
-		//this is redundant.
-		size_t port;
-		for (port = 1; port <= hub_info->port_count; ++port) {
-			const int opResult = usb_hub_port_clear_feature(
-			    &hub_info->ports[port], USB_HUB_FEATURE_PORT_POWER);
-			if (opResult != EOK) {
-				usb_log_warning(
-				    "HUB OVER-CURRENT: Cannot power off port"
-				    " %d:  %s\n",
-				    port, str_error(opResult));
-			}
-		}
+		/* 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
@@ -379,4 +362,13 @@
 			}
 		}
+	}
+	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));
 	}
 }
