Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 15b0432cf41987c321bca72fea786ffababd3b61)
+++ uspace/drv/usbhub/usbhub.c	(revision ad4562c21a6aaf832290f2af3b3d56a515bc3437)
@@ -33,5 +33,5 @@
  */
 
-#include <driver.h>
+#include <ddf/driver.h>
 #include <bool.h>
 #include <errno.h>
@@ -44,4 +44,5 @@
 #include <usb/request.h>
 #include <usb/classes/hub.h>
+#include <stdio.h>
 
 #include "usbhub.h"
@@ -52,15 +53,29 @@
 #include "usb/classes/classes.h"
 
-static device_ops_t hub_device_ops = {
+static ddf_dev_ops_t hub_device_ops = {
 	.interfaces[USB_DEV_IFACE] = &usb_iface_hub_impl
 };
 
-/** Hub status-change endpoint description */
+/** Hub status-change endpoint description
+ *
+ * For more see usb hub specification in 11.15.1 of
+ */
 static usb_endpoint_description_t status_change_endpoint_description = {
 	.transfer_type = USB_TRANSFER_INTERRUPT,
 	.direction = USB_DIRECTION_IN,
 	.interface_class = USB_CLASS_HUB,
+	.interface_subclass = 0,
+	.interface_protocol = 0,
 	.flags = 0
 };
+
+int usb_hub_control_loop(void * hub_info_param){
+	usb_hub_info_t * hub_info = (usb_hub_info_t*)hub_info_param;
+	while(true){
+		usb_hub_check_hub_changes(hub_info);
+		async_usleep(1000 * 1000 );/// \TODO proper number once
+	}
+	return 0;
+}
 
 
@@ -79,4 +94,5 @@
  */
 static int usb_hub_init_communication(usb_hub_info_t * hub){
+	usb_log_debug("Initializing hub USB communication (hub->device->handle=%zu).\n", hub->device->handle);
 	int opResult;
 	opResult = usb_device_connection_initialize_from_device(
@@ -88,4 +104,5 @@
 		return opResult;
 	}
+	usb_log_debug("Initializing USB wire abstraction.\n");
 	opResult = usb_hc_connection_initialize_from_device(&hub->connection,
 			hub->device);
@@ -95,4 +112,5 @@
 		return opResult;
 	}
+	usb_log_debug("Initializing default control pipe.\n");
 	opResult = usb_endpoint_pipe_initialize_default_control(&hub->endpoints.control,
             &hub->device_connection);
@@ -132,5 +150,5 @@
 
 	//configuration descriptor
-	/// \TODO check other configurations
+	/// \TODO check other configurations?
 	usb_standard_configuration_descriptor_t config_descriptor;
 	opResult = usb_request_get_bare_configuration_descriptor(
@@ -176,8 +194,4 @@
 	}
 
-	/**
-	 * Initialize the interrupt in endpoint.
-	 * \TODO this code should be checked...
-	 */
 	usb_endpoint_mapping_t endpoint_mapping[1] = {
 		{
@@ -207,11 +221,4 @@
 	return EOK;
 	
-
-	// Initialize the interrupt(=status change) endpoint.
-	/*usb_endpoint_pipe_initialize(
-		&result->endpoints->status_change,
-		&result->device_connection, );USB_TRANSFER_INTERRUPT
-	USB_DIRECTION_IN*/
-
 }
 
@@ -222,5 +229,5 @@
  * @return pointer to created structure or NULL in case of error
  */
-usb_hub_info_t * usb_create_hub_info(device_t * device) {
+usb_hub_info_t * usb_create_hub_info(ddf_dev_t * device) {
 	usb_hub_info_t* result = usb_new(usb_hub_info_t);
 	result->device = device;
@@ -246,6 +253,7 @@
 	usb_endpoint_pipe_start_session(&result->endpoints.control);
 	opResult = usb_request_get_descriptor(&result->endpoints.control,
-			USB_REQUEST_TYPE_CLASS,
-			USB_DESCTYPE_HUB, 0, 0, serialized_descriptor,
+			USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_DEVICE,
+			USB_DESCTYPE_HUB,
+			0, 0, serialized_descriptor,
 			USB_HUB_MAX_DESCRIPTOR_SIZE, &received_size);
 	usb_endpoint_pipe_end_session(&result->endpoints.control);
@@ -264,5 +272,4 @@
 	}
 
-	
 	dprintf(USB_LOG_LEVEL_INFO, "setting port count to %d",descriptor->ports_count);
 	result->port_count = descriptor->ports_count;
@@ -291,8 +298,9 @@
  * @return
  */
-int usb_add_hub_device(device_t *dev) {
+int usb_add_hub_device(ddf_dev_t *dev) {
 	dprintf(USB_LOG_LEVEL_INFO, "add_hub_device(handle=%d)", (int) dev->handle);
 
-	dev->ops = &hub_device_ops;
+	//dev->ops = &hub_device_ops;
+	(void) hub_device_ops;
 
 	usb_hub_info_t * hub_info = usb_create_hub_info(dev);
@@ -325,11 +333,31 @@
 
 	//add the hub to list
+	//is this needed now?
 	fibril_mutex_lock(&usb_hub_list_lock);
 	usb_lst_append(&usb_hub_list, hub_info);
 	fibril_mutex_unlock(&usb_hub_list_lock);
-
 	dprintf(USB_LOG_LEVEL_DEBUG, "hub info added to list");
+
+	dprintf(USB_LOG_LEVEL_DEBUG, "adding to ddf");
+	ddf_fun_t *hub_fun = ddf_fun_create(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);
+
+	fid_t fid = fibril_create(usb_hub_control_loop, hub_info);
+	if (fid == 0) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				": failed to start monitoring fibril for new hub");
+		return ENOMEM;
+	}
+	fibril_add_ready(fid);
+
+	dprintf(USB_LOG_LEVEL_DEBUG, "hub fibril created");
 	//(void)hub_info;
-	usb_hub_check_hub_changes();
+	//usb_hub_check_hub_changes();
 	
 	dprintf(USB_LOG_LEVEL_INFO, "hub dev added");
@@ -364,7 +392,8 @@
 	//opResult = usb_drv_reserve_default_address(hc);
 	opResult = usb_hc_reserve_default_address(&hub->connection, USB_SPEED_LOW);
-
-	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_WARNING, "cannot assign default address, it is probably used");
+	
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_WARNING, 
+				"cannot assign default address, it is probably used %d",opResult);
 		return;
 	}
@@ -377,5 +406,6 @@
 			);
 	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_ERROR, "something went wrong when reseting a port");
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"something went wrong when reseting a port %d",opResult);
 		//usb_hub_release_default_address(hc);
 		usb_hc_release_default_address(&hub->connection);
@@ -390,5 +420,5 @@
  */
 static void usb_hub_finalize_add_device( usb_hub_info_t * hub,
-		uint16_t port) {
+		uint16_t port, bool isLowSpeed) {
 
 	int opResult;
@@ -413,7 +443,5 @@
 			&new_device_connection);
 	/// \TODO get highspeed info
-
-
-
+	usb_speed_t speed = isLowSpeed?USB_SPEED_LOW:USB_SPEED_FULL;
 
 
@@ -421,5 +449,5 @@
 	usb_address_t new_device_address = usb_hc_request_address(
 			&hub->connection,
-			USB_SPEED_LOW/// \TODO fullspeed??
+			speed/// \TODO fullspeed??
 			);
 	if (new_device_address < 0) {
@@ -432,8 +460,10 @@
 	//opResult = usb_drv_req_set_address(hc, USB_ADDRESS_DEFAULT,
 	//    new_device_address);
+	usb_endpoint_pipe_start_session(&new_device_pipe);
 	opResult = usb_request_set_address(&new_device_pipe,new_device_address);
-
-	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_ERROR, "could not set address for new device");
+	usb_endpoint_pipe_end_session(&new_device_pipe);
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"could not set address for new device %d",opResult);
 		usb_hc_release_default_address(&hub->connection);
 		return;
@@ -450,8 +480,10 @@
 	//??
     opResult = usb_device_register_child_in_devman(new_device_address,
-            hub->connection.hc_handle, hub->device, &child_handle);
-
-	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_ERROR, "could not start driver for new device");
+            hub->connection.hc_handle, hub->device, &child_handle,
+            NULL, NULL, NULL);
+
+	if (opResult != EOK) {
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"could not start driver for new device %d",opResult);
 		return;
 	}
@@ -464,5 +496,6 @@
 			&hub->attached_devs[port]);
 	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_ERROR, "could not assign address of device in hcd");
+		dprintf(USB_LOG_LEVEL_ERROR, 
+				"could not assign address of device in hcd %d",opResult);
 		return;
 	}
@@ -506,4 +539,24 @@
 }
 
+
+/**
+ *Process over current condition on port.
+ * 
+ * Turn off the power on the port.
+ *
+ * @param hub
+ * @param port
+ */
+static void usb_hub_over_current( usb_hub_info_t * hub,
+		uint16_t port){
+	int opResult;
+	opResult = usb_hub_clear_port_feature(&hub->endpoints.control,
+	    port, USB_HUB_FEATURE_PORT_POWER);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "cannot power off port %d;  %d",
+				port, opResult);
+	}
+}
+
 /**
  * Process interrupts on given hub port
@@ -517,15 +570,6 @@
 	//determine type of change
 	usb_endpoint_pipe_t *pipe = &hub->endpoints.control;
-	int opResult = usb_endpoint_pipe_start_session(pipe);
 	
-	if(opResult != EOK){
-		dprintf(USB_LOG_LEVEL_ERROR, "cannot open pipe %d", opResult);
-	}
-
-	/*
-	usb_target_t target;
-	target.address=address;
-	target.endpoint=0;
-	*/
+	int opResult;
 
 	usb_port_status_t status;
@@ -542,9 +586,9 @@
 			);
 	if (opResult != EOK) {
-		dprintf(USB_LOG_LEVEL_ERROR, "ERROR: could not get port status");
+		dprintf(USB_LOG_LEVEL_ERROR, "could not get port status");
 		return;
 	}
 	if (rcvd_size != sizeof (usb_port_status_t)) {
-		dprintf(USB_LOG_LEVEL_ERROR, "ERROR: received status has incorrect size");
+		dprintf(USB_LOG_LEVEL_ERROR, "received status has incorrect size");
 		return;
 	}
@@ -561,11 +605,21 @@
 		}
 	}
+	//over current
+	if (usb_port_overcurrent_change(&status)) {
+		//check if it was not auto-resolved
+		if(usb_port_over_current(&status)){
+			usb_hub_over_current(hub,port);
+		}else{
+			dprintf(USB_LOG_LEVEL_INFO,
+				"over current condition was auto-resolved on port %d",port);
+		}
+	}
 	//port reset
 	if (usb_port_reset_completed(&status)) {
 		dprintf(USB_LOG_LEVEL_INFO, "port reset complete");
 		if (usb_port_enabled(&status)) {
-			usb_hub_finalize_add_device(hub, port);
+			usb_hub_finalize_add_device(hub, port, usb_port_low_speed(&status));
 		} else {
-			dprintf(USB_LOG_LEVEL_WARNING, "ERROR: port reset, but port still not enabled");
+			dprintf(USB_LOG_LEVEL_WARNING, "port reset, but port still not enabled");
 		}
 	}
@@ -580,92 +634,71 @@
 	}
 	/// \TODO handle other changes
-	/// \TODO debug log for various situations
-	usb_endpoint_pipe_end_session(pipe);
-
-
-}
-
-/**
- * Check changes on all known hubs.
- */
-void usb_hub_check_hub_changes(void) {
+}
+
+/**
+ * Check changes on particular hub
+ * @param hub_info_param
+ */
+void usb_hub_check_hub_changes(usb_hub_info_t * hub_info){
+	int opResult;
+	opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
+	if(opResult != EOK){
+		dprintf(USB_LOG_LEVEL_ERROR,
+				"could not initialize communication for hub; %d", opResult);
+		return;
+	}
+
+	size_t port_count = hub_info->port_count;
+
+	/// FIXME: count properly
+	size_t byte_length = ((port_count+1) / 8) + 1;
+		void *change_bitmap = malloc(byte_length);
+	size_t actual_size;
+
 	/*
-	 * Iterate through all hubs.
+	 * Send the request.
 	 */
-	usb_general_list_t * lst_item;
-	fibril_mutex_lock(&usb_hub_list_lock);
-	for (lst_item = usb_hub_list.next;
-			lst_item != &usb_hub_list;
-			lst_item = lst_item->next) {
-		fibril_mutex_unlock(&usb_hub_list_lock);
-		usb_hub_info_t * hub_info = ((usb_hub_info_t*)lst_item->data);
-		int opResult;
-
-		opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.status_change);
-		if(opResult != EOK){
-			continue;
+	opResult = usb_endpoint_pipe_read(
+			&hub_info->endpoints.status_change,
+			change_bitmap, byte_length, &actual_size
+			);
+
+	if (opResult != EOK) {
+		free(change_bitmap);
+		dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+		return;
+	}
+	unsigned int port;
+	opResult = usb_endpoint_pipe_start_session(&hub_info->endpoints.control);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "could not start control pipe session %d",
+				opResult);
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+		return;
+	}
+	opResult = usb_hc_connection_open(&hub_info->connection);
+	if(opResult!=EOK){
+		dprintf(USB_LOG_LEVEL_ERROR, "could not start host controller session %d",
+				opResult);
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
+		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+		return;
+	}
+
+	///todo, opresult check, pre obe konekce
+	for (port = 1; port < port_count+1; ++port) {
+		bool interrupt =
+				(((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
+		if (interrupt) {
+			usb_hub_process_interrupt(
+			        hub_info, port);
 		}
-		/*
-		 * Check status change pipe of this hub.
-		 */
-		/*
-		usb_target_t target;
-		target.address = hub_info->address;
-		target.endpoint = 1;/// \TODO get from endpoint descriptor
-		dprintf(USB_LOG_LEVEL_INFO, "checking changes for hub at addr %d",
-		    target.address);
-		*/
-		size_t port_count = hub_info->port_count;
-
-		/*
-		 * Connect to respective HC.
-		 *
-		int hc = usb_drv_hc_connect_auto(hub_info->device, 0);
-		if (hc < 0) {
-			continue;
-		}*/
-
-		/// FIXME: count properly
-		size_t byte_length = ((port_count+1) / 8) + 1;
-
-		void *change_bitmap = malloc(byte_length);
-		size_t actual_size;
-		//usb_handle_t handle;
-
-		/*
-		 * Send the request.
-		 */
-		opResult = usb_endpoint_pipe_read(
-				&hub_info->endpoints.status_change,
-				change_bitmap, byte_length, &actual_size
-				);
-
-		//usb_drv_async_wait_for(handle);
-
-		if (opResult != EOK) {
-			free(change_bitmap);
-			dprintf(USB_LOG_LEVEL_WARNING, "something went wrong while getting status of hub");
-			continue;
-		}
-		unsigned int port;
-		for (port = 1; port < port_count+1; ++port) {
-			bool interrupt =
-					(((uint8_t*) change_bitmap)[port / 8] >> (port % 8)) % 2;
-			if (interrupt) {
-				usb_hub_process_interrupt(
-				        hub_info, port);
-			}
-		}
-		usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
-		free(change_bitmap);
-		
-
-		//async_hangup(hc);
-		fibril_mutex_lock(&usb_hub_list_lock);
-	}
-	fibril_mutex_unlock(&usb_hub_list_lock);
-}
-
-
+	}
+	usb_hc_connection_close(&hub_info->connection);
+	usb_endpoint_pipe_end_session(&hub_info->endpoints.control);
+	usb_endpoint_pipe_end_session(&hub_info->endpoints.status_change);
+	free(change_bitmap);
+}
 
 
