Index: uspace/lib/usbvirt/ctrlpipe.c
===================================================================
--- uspace/lib/usbvirt/ctrlpipe.c	(revision a498728e70bc9545710819930b0cb80b9dc78718)
+++ uspace/lib/usbvirt/ctrlpipe.c	(revision 954ea70e3458816f21ae5183cb92e63c3a8875e8)
@@ -45,4 +45,6 @@
 	((value & GET_MIDBITS_MASK(size, shift)) >> shift)
 
+usb_address_t dev_new_address = -1;
+
 static int request_get_type(uint8_t request_type)
 {
@@ -63,11 +65,13 @@
 	int type = request_get_type(request->request_type);
 	
+	int rc = EOK;
+	
 	switch (type) {
 		case REQUEST_TYPE_STANDARD:
-			return handle_std_request(request, remaining_data);
+			rc = handle_std_request(request, remaining_data);
 			break;
 		case REQUEST_TYPE_CLASS:
 			if (DEVICE_HAS_OP(device, on_class_device_request)) {
-				return device->ops->on_class_device_request(device,
+				rc = device->ops->on_class_device_request(device,
 				    request, remaining_data);
 			}
@@ -77,5 +81,22 @@
 	}
 	
-	return EOK;
+	device->send_data(device, 0, NULL, 0);
+	
+	if (dev_new_address != -1) {
+		/*
+		 * TODO: handle when this request is invalid (e.g.
+		 * setting address when in configured state).
+		 */
+		if (dev_new_address == 0) {
+			device->state = USBVIRT_STATE_DEFAULT;
+		} else {
+			device->state = USBVIRT_STATE_ADDRESS;
+		}
+		device->address = dev_new_address;
+		
+		dev_new_address = -1;
+	}
+	
+	return rc;
 }
 
Index: uspace/lib/usbvirt/ids.h
===================================================================
--- uspace/lib/usbvirt/ids.h	(revision a498728e70bc9545710819930b0cb80b9dc78718)
+++ uspace/lib/usbvirt/ids.h	(revision 954ea70e3458816f21ae5183cb92e63c3a8875e8)
@@ -44,4 +44,11 @@
 int usbvirt_disconnect(void);
 
+typedef enum {
+	USBVIRT_TRANSACTION_SETUP,
+	USBVIRT_TRANSACTION_IN,
+	USBVIRT_TRANSACTION_OUT
+} usbvirt_transaction_type_t;
+
+
 #endif
 /**
Index: uspace/lib/usbvirt/main.c
===================================================================
--- uspace/lib/usbvirt/main.c	(revision a498728e70bc9545710819930b0cb80b9dc78718)
+++ uspace/lib/usbvirt/main.c	(revision 954ea70e3458816f21ae5183cb92e63c3a8875e8)
@@ -122,5 +122,5 @@
 		return EINVAL;
 	}
-	if ((buffer == NULL) || (size == 0)) {
+	if ((buffer == NULL) && (size != 0)) {
 		return EINVAL;
 	}
@@ -131,14 +131,17 @@
 	int rc;
 	
-	req = async_send_2(phone,
+	req = async_send_3(phone,
 	    IPC_M_USBVIRT_DATA_FROM_DEVICE,
 	    dev->address,
 	    endpoint,
+	    size,
 	    &answer_data);
 	
-	rc = async_data_write_start(phone, buffer, size);
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
+	if (size > 0) {
+		rc = async_data_write_start(phone, buffer, size);
+		if (rc != EOK) {
+			async_wait_for(req, NULL);
+			return rc;
+		}
 	}
 	
Index: uspace/lib/usbvirt/private.h
===================================================================
--- uspace/lib/usbvirt/private.h	(revision a498728e70bc9545710819930b0cb80b9dc78718)
+++ uspace/lib/usbvirt/private.h	(revision 954ea70e3458816f21ae5183cb92e63c3a8875e8)
@@ -58,4 +58,6 @@
 int handle_std_request(usb_device_request_setup_packet_t *request, uint8_t *data);
 
+extern usb_address_t dev_new_address;
+
 #endif
 /**
Index: uspace/lib/usbvirt/stdreq.c
===================================================================
--- uspace/lib/usbvirt/stdreq.c	(revision a498728e70bc9545710819930b0cb80b9dc78718)
+++ uspace/lib/usbvirt/stdreq.c	(revision 954ea70e3458816f21ae5183cb92e63c3a8875e8)
@@ -117,15 +117,5 @@
 	}
 	
-	/*
-	 * TODO: handle when this request is invalid (e.g.
-	 * setting address when in configured state).
-	 */
-	if (new_address == 0) {
-		device->state = USBVIRT_STATE_DEFAULT;
-	} else {
-		device->state = USBVIRT_STATE_ADDRESS;
-	}
-	
-	device->address = new_address;
+	dev_new_address = new_address;
 	
 	return EOK;
