Index: uspace/drv/ohci/root_hub.c
===================================================================
--- uspace/drv/ohci/root_hub.c	(revision 8fd4ba0febd30b06d14b441e12b5134169bf5f21)
+++ uspace/drv/ohci/root_hub.c	(revision ff76509a4cdd6b4965cdb4d458fedb849ef76ba2)
@@ -198,5 +198,8 @@
 static int process_ctrl_request(rh_t *instance, usb_transfer_batch_t *request);
 
-
+static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
+    void * change_buffer, size_t buffe_size);
+
+static bool is_zeros(void * buffer, size_t size);
 
 
@@ -213,5 +216,5 @@
 	// set port power mode to no-power-switching
 	instance->registers->rh_desc_a |= RHDA_NPS_FLAG;
-
+	instance->unfinished_interrupt_transfer = NULL;
 	usb_log_info("OHCI root hub with %d ports.\n", instance->port_count);
 	return EOK;
@@ -236,13 +239,23 @@
 		usb_log_info("Root hub got INTERRUPT packet\n");
 		void * buffer;
+		size_t buffer_size;
 		create_interrupt_mask(instance, &buffer,
-			&(request->transfered_size));
-		memcpy(request->data_buffer, buffer,
-			request->transfered_size);
+			&buffer_size);
+		if(is_zeros(buffer,buffer_size)){
+			usb_log_debug("no changes..");
+			instance->unfinished_interrupt_transfer=
+			    request;
+			//will be finished later
+		}else{
+			usb_log_debug("processing changes..");
+			process_interrupt(instance, request,
+			    buffer, buffer_size);
+		}
+		free(buffer);
 		opResult = EOK;
 	} else {
 		opResult = EINVAL;
-	}
-	usb_transfer_batch_finish_error(request, opResult);
+		usb_transfer_batch_finish_error(request, opResult);
+	}
 	return EOK;
 }
@@ -252,7 +265,16 @@
 
 void rh_interrupt(rh_t *instance) {
-	usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
-		"interrupts, am I?\n");
-	/* TODO: implement? */
+	//usb_log_info("Whoa whoa wait, I`m not supposed to receive any "
+	//	"interrupts, am I?\n");
+	if(!instance->unfinished_interrupt_transfer){
+		return;
+	}
+	size_t size;
+	void * buffer;
+	create_interrupt_mask(instance, &buffer,
+			&size);
+	process_interrupt(instance,instance->unfinished_interrupt_transfer,
+	    buffer,size);
+	free(buffer);
 }
 /*----------------------------------------------------------------------------*/
@@ -859,4 +881,51 @@
 	return opResult;
 }
+/*----------------------------------------------------------------------------*/
+
+/**
+ * process hanging interrupt request
+ *
+ * If an interrupt transfer has been received and there was no change,
+ * the driver stores the transfer information and waits for change to occcur.
+ * This routine is called when that happens and it finalizes the interrupt
+ * transfer.
+ *
+ * @param instance hub instance
+ * @param request batch request to be processed
+ * @param change_buffer chages on hub
+ * @param buffer_size size of change buffer
+ *
+ * @return
+ */
+static int process_interrupt(rh_t *instance, usb_transfer_batch_t * request,
+    void * change_buffer, size_t buffe_size){
+	create_interrupt_mask(instance, &change_buffer,
+	    &(request->transfered_size));
+	memcpy(request->data_buffer, change_buffer,request->transfered_size);
+	instance->unfinished_interrupt_transfer = NULL;
+	usb_transfer_batch_finish_error(request, EOK);
+	return EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+/**
+ * return whether the buffer is full of zeros
+ *
+ * Convenience function.
+ * @param buffer
+ * @param size
+ * @return
+ */
+static bool is_zeros(void * buffer, size_t size){
+	if(!buffer) return true;
+	if(!size) return true;
+	size_t i;
+	for(i=0;i<size;++i){
+		if(((char*)buffer)[i])
+			return false;
+	}
+	return true;
+}
 
 /**
Index: uspace/drv/ohci/root_hub.h
===================================================================
--- uspace/drv/ohci/root_hub.h	(revision 8fd4ba0febd30b06d14b441e12b5134169bf5f21)
+++ uspace/drv/ohci/root_hub.h	(revision ff76509a4cdd6b4965cdb4d458fedb849ef76ba2)
@@ -54,4 +54,6 @@
 	/** hubs descriptors */
 	usb_device_descriptors_t descriptors;
+	/** interrupt transfer waiting for an actual interrupt to occur */
+	usb_transfer_batch_t * unfinished_interrupt_transfer;
 } rh_t;
 
Index: uspace/drv/usbhub/usbhub.c
===================================================================
--- uspace/drv/usbhub/usbhub.c	(revision 8fd4ba0febd30b06d14b441e12b5134169bf5f21)
+++ uspace/drv/usbhub/usbhub.c	(revision ff76509a4cdd6b4965cdb4d458fedb849ef76ba2)
@@ -105,5 +105,5 @@
 	}
 
-	usb_pipe_start_session(hub_info->control_pipe);
+	//usb_pipe_start_session(hub_info->control_pipe);
 	//set hub configuration
 	opResult = usb_hub_set_configuration(hub_info);
@@ -122,8 +122,8 @@
 		return opResult;
 	}
-	usb_pipe_end_session(hub_info->control_pipe);
-
-	/// \TODO what is this?
-	usb_log_debug("Creating `hub' function.\n");
+	//usb_pipe_end_session(hub_info->control_pipe);
+
+
+	usb_log_debug("Creating 'hub' function in DDF.\n");
 	ddf_fun_t *hub_fun = ddf_fun_create(hub_info->usb_device->ddf_dev,
 	    fun_exposed, "hub");
@@ -153,4 +153,5 @@
 bool hub_port_changes_callback(usb_device_t *dev,
     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;
 
@@ -217,5 +218,6 @@
 	// get hub descriptor
 	usb_log_debug("creating serialized descriptor\n");
-	void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
+	//void * serialized_descriptor = malloc(USB_HUB_MAX_DESCRIPTOR_SIZE);
+	uint8_t serialized_descriptor[USB_HUB_MAX_DESCRIPTOR_SIZE];
 	usb_hub_descriptor_t * descriptor;
 	int opResult;
@@ -235,12 +237,17 @@
 	}
 	usb_log_debug2("deserializing descriptor\n");
-	descriptor = usb_deserialize_hub_desriptor(serialized_descriptor);
+	descriptor = usb_create_deserialized_hub_desriptor(
+	    serialized_descriptor);
 	if (descriptor == NULL) {
 		usb_log_warning("could not deserialize descriptor \n");
-		return opResult;
+		return ENOMEM;
 	}
 	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
+	bool is_power_switched =
+	    ((descriptor->hub_characteristics & 1) ==0);
+	bool has_individual_port_powering =
+	    ((descriptor->hub_characteristics & 1) !=0);
 	hub_info->ports = malloc(
 	    sizeof (usb_hub_port_t) * (hub_info->port_count + 1));
@@ -249,15 +256,31 @@
 		usb_hub_port_init(&hub_info->ports[port]);
 	}
-	for (port = 0; port < hub_info->port_count; port++) {
-		opResult = usb_hub_set_port_feature(hub_info->control_pipe,
-		    port+1, USB_HUB_FEATURE_PORT_POWER);
-		if (opResult != EOK) {
-			usb_log_error("cannot power on port %d;  %d\n",
-			    port+1, opResult);
-		}
+	if(is_power_switched){
+		usb_log_debug("is_power_switched\n");
+		if(has_individual_port_powering){
+			usb_log_debug("has_individual_port_powering\n");
+			for (port = 0; port < hub_info->port_count; port++) {
+				opResult = usb_hub_set_port_feature(hub_info->control_pipe,
+				    port+1, USB_HUB_FEATURE_PORT_POWER);
+				if (opResult != EOK) {
+					usb_log_error("cannot power on port %d;  %d\n",
+					    port+1, opResult);
+				}
+			}
+		}else{
+			usb_log_debug("!has_individual_port_powering\n");
+			opResult = usb_hub_set_feature(hub_info->control_pipe,
+			    USB_HUB_FEATURE_C_HUB_LOCAL_POWER);
+			if (opResult != EOK) {
+				usb_log_error("cannot power hub;  %d\n",
+				  opResult);
+			}
+		}
+	}else{
+		usb_log_debug("!is_power_switched\n");
 	}
 	usb_log_debug2("freeing data\n");
-	free(serialized_descriptor);
-	free(descriptor->devices_removable);
+	//free(serialized_descriptor);
+	//free(descriptor->devices_removable);
 	free(descriptor);
 	return EOK;
@@ -321,13 +344,7 @@
 	 * auto destruction, this could work better.
 	 */
-	int rc = usb_pipe_start_session(hub_info->control_pipe);
+	int rc = usb_hc_connection_open(&hub_info->connection);
 	if (rc != EOK) {
-		usb_log_error("Failed to start session on control pipe: %s.\n",
-		    str_error(rc));
-		return rc;
-	}
-	rc = usb_hc_connection_open(&hub_info->connection);
-	if (rc != EOK) {
-		usb_pipe_end_session(hub_info->control_pipe);
+		//usb_pipe_end_session(hub_info->control_pipe);
 		usb_log_error("Failed to open connection to HC: %s.\n",
 		    str_error(rc));
Index: uspace/drv/usbhub/usbhub_private.h
===================================================================
--- uspace/drv/usbhub/usbhub_private.h	(revision 8fd4ba0febd30b06d14b441e12b5134169bf5f21)
+++ uspace/drv/usbhub/usbhub_private.h	(revision ff76509a4cdd6b4965cdb4d458fedb849ef76ba2)
@@ -113,5 +113,5 @@
 
 	usb_device_request_setup_packet_t clear_request = {
-		.request_type = USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE,
+		.request_type = USB_HUB_REQ_TYPE_SET_PORT_FEATURE,
 		.request = USB_DEVREQ_SET_FEATURE,
 		.length = 0,
@@ -166,22 +166,15 @@
 }
 
-/**
- * create uint8_t array with serialized descriptor
- *
- * @param descriptor
- * @return newly created serializd descriptor pointer
- */
-void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor);
 
-/**
- * create deserialized desriptor structure out of serialized descriptor
- *
- * The serialized descriptor must be proper usb hub descriptor,
- * otherwise an eerror might occur.
- *
- * @param sdescriptor serialized descriptor
- * @return newly created deserialized descriptor pointer
- */
-usb_hub_descriptor_t * usb_deserialize_hub_desriptor(void * sdescriptor);
+void * usb_create_serialized_hub_descriptor(usb_hub_descriptor_t * descriptor);
+
+void usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor,
+    void * serialized_descriptor);
+
+usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
+    void * serialized_descriptor);
+
+void usb_deserialize_hub_desriptor(void * serialized_descriptor,
+    usb_hub_descriptor_t * descriptor);
 
 
Index: uspace/drv/usbhub/utils.c
===================================================================
--- uspace/drv/usbhub/utils.c	(revision 8fd4ba0febd30b06d14b441e12b5134169bf5f21)
+++ uspace/drv/usbhub/utils.c	(revision ff76509a4cdd6b4965cdb4d458fedb849ef76ba2)
@@ -56,5 +56,11 @@
 //hub descriptor utils
 
-void * usb_serialize_hub_descriptor(usb_hub_descriptor_t * descriptor) {
+/**
+ * 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;
@@ -64,25 +70,55 @@
 	uint8_t * result = malloc(size);
 	//size
-	result[0] = 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
-	result[1] = USB_DESCTYPE_HUB;
-	result[2] = descriptor->ports_count;
+	sdescriptor[1] = USB_DESCTYPE_HUB;
+	sdescriptor[2] = descriptor->ports_count;
 	/// @fixme handling of endianness??
-	result[3] = descriptor->hub_characteristics / 256;
-	result[4] = descriptor->hub_characteristics % 256;
-	result[5] = descriptor->pwr_on_2_good_time;
-	result[6] = descriptor->current_requirement;
+	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) {
-		result[7 + i] = descriptor->devices_removable[i];
+		sdescriptor[7 + i] = descriptor->devices_removable[i];
 	}
 	for (i = 0; i < var_size; ++i) {
-		result[7 + var_size + i] = 255;
+		sdescriptor[7 + var_size + i] = 255;
 	}
-	return result;
 }
 
-usb_hub_descriptor_t * usb_deserialize_hub_desriptor(
+
+/**
+ * create deserialized desriptor structure out of serialized descriptor
+ *
+ * The serialized descriptor must be proper usb hub descriptor,
+ * otherwise an eerror might occur.
+ *
+ * @param sdescriptor serialized descriptor
+ * @return newly created deserialized descriptor pointer
+ */
+usb_hub_descriptor_t * usb_create_deserialized_hub_desriptor(
 void * serialized_descriptor) {
 	uint8_t * sdescriptor = serialized_descriptor;
@@ -95,22 +131,32 @@
 
 	usb_hub_descriptor_t * result = malloc(sizeof(usb_hub_descriptor_t));
-	
+	if(result)
+		usb_deserialize_hub_desriptor(serialized_descriptor,result);
+	return result;
+}
 
-	result->ports_count = sdescriptor[2];
+/**
+ * deserialize descriptor into given pointer
+ * 
+ * @param serialized_descriptor
+ * @param descriptor
+ * @return
+ */
+void usb_deserialize_hub_desriptor(
+void * serialized_descriptor, usb_hub_descriptor_t * descriptor) {
+	uint8_t * sdescriptor = serialized_descriptor;
+	descriptor->ports_count = sdescriptor[2];
 	/// @fixme handling of endianness??
-	result->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
-	result->pwr_on_2_good_time = sdescriptor[5];
-	result->current_requirement = sdescriptor[6];
-	size_t var_size = (result->ports_count+7) / 8;
-	result->devices_removable = (uint8_t*) malloc(var_size);
+	descriptor->hub_characteristics = sdescriptor[4] + 256 * sdescriptor[3];
+	descriptor->pwr_on_2_good_time = sdescriptor[5];
+	descriptor->current_requirement = sdescriptor[6];
+	size_t var_size = (descriptor->ports_count+7) / 8;
+	//descriptor->devices_removable = (uint8_t*) malloc(var_size);
 
 	size_t i;
 	for (i = 0; i < var_size; ++i) {
-		result->devices_removable[i] = sdescriptor[7 + i];
+		descriptor->devices_removable[i] = sdescriptor[7 + i];
 	}
-	return result;
 }
-
-
 
 /**
Index: uspace/lib/usb/include/usb/classes/hub.h
===================================================================
--- uspace/lib/usb/include/usb/classes/hub.h	(revision 8fd4ba0febd30b06d14b441e12b5134169bf5f21)
+++ uspace/lib/usb/include/usb/classes/hub.h	(revision ff76509a4cdd6b4965cdb4d458fedb849ef76ba2)
@@ -152,5 +152,5 @@
             maximum of 255 ports).
      */
-    uint8_t * devices_removable;
+    uint8_t devices_removable[32];
 
     /**
