Index: uspace/lib/usbvirt/device.h
===================================================================
--- uspace/lib/usbvirt/device.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/lib/usbvirt/device.h	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -106,5 +106,14 @@
 } usbvirt_descriptors_t;
 
+/** Possible states of virtual USB device.
+ * Notice that these are not 1:1 mappings to those in USB specification.
+ */
+typedef enum {
+	USBVIRT_STATE_DEFAULT,
+	USBVIRT_STATE_ADDRESS,
+	USBVIRT_STATE_CONFIGURED
+} usbvirt_device_state_t;
 
+/** Virtual USB device. */
 typedef struct usbvirt_device {
 	/** Callback device operations. */
@@ -126,4 +135,8 @@
 	usbvirt_descriptors_t *descriptors;
 	
+	/** Current device state. */
+	usbvirt_device_state_t state;
+	/** Device address. */
+	usb_address_t address;
 	
 	/* Private attributes. */
Index: uspace/lib/usbvirt/main.c
===================================================================
--- uspace/lib/usbvirt/main.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/lib/usbvirt/main.c	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -50,5 +50,11 @@
 static void handle_data_to_device(ipc_callid_t iid, ipc_call_t icall)
 {
-	usb_endpoint_t endpoint = IPC_GET_ARG1(icall);
+	usb_address_t address = IPC_GET_ARG1(icall);
+	usb_endpoint_t endpoint = IPC_GET_ARG2(icall);
+	
+	if (address != device->address) {
+		ipc_answer_0(iid, EADDRNOTAVAIL);
+		return;
+	}
 	
 	size_t len;
@@ -95,4 +101,11 @@
 }
 
+static void device_init(usbvirt_device_t *dev)
+{
+	dev->send_data = usbvirt_data_to_host;
+	dev->state = USBVIRT_STATE_DEFAULT;
+	dev->address = 0;
+}
+
 int usbvirt_data_to_host(struct usbvirt_device *dev,
     usb_endpoint_t endpoint, void *buffer, size_t size)
@@ -112,6 +125,7 @@
 	int rc;
 	
-	req = async_send_1(phone,
+	req = async_send_2(phone,
 	    IPC_M_USBVIRT_DATA_FROM_DEVICE,
+	    dev->address,
 	    endpoint,
 	    &answer_data);
@@ -174,5 +188,5 @@
 	
 	dev->vhcd_phone_ = hcd_phone;
-	dev->send_data = usbvirt_data_to_host;
+	device_init(dev);
 	
 	device = dev;
Index: uspace/lib/usbvirt/stdreq.c
===================================================================
--- uspace/lib/usbvirt/stdreq.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/lib/usbvirt/stdreq.c	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -118,6 +118,15 @@
 	
 	/*
-	 * TODO: inform the HC that device has new address assigned.
+	 * 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;
+	
 	return EOK;
 }
Index: uspace/srv/hw/bus/usb/hcd/virtual/conndev.c
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/conndev.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/srv/hw/bus/usb/hcd/virtual/conndev.c	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -46,8 +46,7 @@
     virtdev_connection_t *dev)
 {
-	usb_endpoint_t endpoint = IPC_GET_ARG1(icall);
 	usb_target_t target = {
-		.address = dev->address,
-		.endpoint = endpoint
+		.address = IPC_GET_ARG1(icall),
+		.endpoint = IPC_GET_ARG2(icall)
 	};
 	
@@ -80,6 +79,6 @@
 	assert(dev != NULL);
 	
-	dprintf("phone%#x: virtual device %d connected [%d]",
-	    phone_hash, dev->id, dev->address);
+	dprintf("phone%#x: virtual device %d connected",
+	    phone_hash, dev->id);
 	
 	while (true) {
@@ -93,6 +92,6 @@
 				ipc_hangup(dev->phone);
 				ipc_answer_0(callid, EOK);
-				dprintf("phone%#x: device %d [%d] hang-up",
-				    phone_hash, dev->id, dev->address);
+				dprintf("phone%#x: device %d hang-up",
+				    phone_hash, dev->id);
 				return;
 			
Index: uspace/srv/hw/bus/usb/hcd/virtual/devices.c
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/devices.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/srv/hw/bus/usb/hcd/virtual/devices.c	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -44,4 +44,5 @@
 
 #include <usbvirt/ids.h>
+#include <usbvirt/hub.h>
 
 #include "devices.h"
@@ -63,6 +64,5 @@
 	switch (id) {
 		case USBVIRT_DEV_KEYBOARD_ID:
-			dev = virtdev_add_device(
-			    USBVIRT_DEV_KEYBOARD_ADDRESS, phone);
+			dev = virtdev_add_device(phone);
 			break;
 		default:
@@ -84,22 +84,4 @@
 }
 
-/** Find virtual device by its USB address.
- *
- * @retval NULL No virtual device at given address.
- */
-virtdev_connection_t *virtdev_find_by_address(usb_address_t address)
-{
-	link_t *pos;
-	list_foreach(pos, &devices) {
-		virtdev_connection_t *dev
-		    = list_get_instance(pos, virtdev_connection_t, link);
-		if (dev->address == address) {
-			return dev;
-		}
-	}
-	
-	return NULL;
-}
-
 /** Create virtual device.
  *
@@ -109,19 +91,9 @@
  * @retval NULL Out of memory or address already occupied.
  */
-virtdev_connection_t *virtdev_add_device(usb_address_t address, int phone)
+virtdev_connection_t *virtdev_add_device(int phone)
 {
-	link_t *pos;
-	list_foreach(pos, &devices) {
-		virtdev_connection_t *dev
-		    = list_get_instance(pos, virtdev_connection_t, link);
-		if (dev->address == address) {
-			return NULL;
-		}
-	}
-	
 	virtdev_connection_t *dev = (virtdev_connection_t *)
 	    malloc(sizeof(virtdev_connection_t));
 	dev->phone = phone;
-	dev->address = address;
 	list_append(&dev->link, &devices);
 	
@@ -137,4 +109,44 @@
 }
 
+/** Send data to all connected devices.
+ *
+ * @param transaction Transaction to be sent over the bus.
+ */
+usb_transaction_outcome_t virtdev_send_to_all(transaction_t *transaction)
+{
+	link_t *pos;
+	list_foreach(pos, &devices) {
+		virtdev_connection_t *dev
+		    = list_get_instance(pos, virtdev_connection_t, link);
+		
+		ipc_call_t answer_data;
+		ipcarg_t answer_rc;
+		aid_t req;
+		int rc;
+		
+		req = async_send_3(dev->phone,
+		    IPC_M_USBVIRT_DATA_TO_DEVICE,
+		    transaction->target.address,
+		    transaction->target.endpoint,
+		    transaction->type,
+		    &answer_data);
+		
+		rc = async_data_write_start(dev->phone,
+		    transaction->buffer, transaction->len);
+		if (rc != EOK) {
+			async_wait_for(req, NULL);
+		} else {
+			async_wait_for(req, &answer_rc);
+			rc = (int)answer_rc;
+		}
+	}
+	
+	/*
+	 * TODO: maybe screw some transactions to get more
+	 * real-life image.
+	 */
+	return USB_OUTCOME_OK;
+}
+
 /**
  * @}
Index: uspace/srv/hw/bus/usb/hcd/virtual/devices.h
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/devices.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/srv/hw/bus/usb/hcd/virtual/devices.h	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -39,8 +39,8 @@
 #include <usb/hcd.h>
 
+#include "hc.h"
+
 /** Connected virtual device. */
 typedef struct {
-	/** Assigned USB address. */
-	usb_address_t address;
 	/** Phone used when sending data to device. */
 	int phone;
@@ -52,7 +52,7 @@
 
 virtdev_connection_t *virtdev_recognise(int, int);
-virtdev_connection_t *virtdev_find_by_address(usb_address_t);
-virtdev_connection_t *virtdev_add_device(usb_address_t, int);
+virtdev_connection_t *virtdev_add_device(int);
 void virtdev_destroy_device(virtdev_connection_t *);
+usb_transaction_outcome_t virtdev_send_to_all(transaction_t *);
 
 #endif
Index: uspace/srv/hw/bus/usb/hcd/virtual/hc.c
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/hc.c	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/srv/hw/bus/usb/hcd/virtual/hc.c	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -68,24 +68,4 @@
 static link_t transaction_from_device_list;
 
-/** Pending transaction details. */
-typedef struct {
-	/** Linked-list link. */
-	link_t link;
-	/** Device address. */
-	usb_target_t target;
-	/** Direction of the transaction. */
-	usb_direction_t direction;
-	/** Transfer type. */
-	usb_transfer_type_t type;
-	/** Transaction data buffer. */
-	void * buffer;
-	/** Transaction data length. */
-	size_t len;
-	/** Callback after transaction is done. */
-	hc_transaction_done_callback_t callback;
-	/** Argument to the callback. */
-	void * callback_arg;
-} transaction_t;
-
 #define TRANSACTION_FORMAT "T[%d:%d %s %s (%d)]"
 #define TRANSACTION_PRINTF(t) \
@@ -136,43 +116,11 @@
 		}
 		
-		link_t * first_transaction_link = transaction_to_device_list.next;
-		transaction_t * transaction
+		link_t *first_transaction_link = transaction_to_device_list.next;
+		transaction_t *transaction
 		    = transaction_get_instance(first_transaction_link);
 		list_remove(first_transaction_link);
 		
-		virtdev_connection_t *dev = virtdev_find_by_address(
-		    transaction->target.address);
-		usb_transaction_outcome_t outcome = USB_OUTCOME_OK;
-		
-		if (dev != NULL) {
-			dprintf("sending data to device at %d.%d (phone %d)",
-			    dev->address, transaction->target.endpoint,
-			    dev->phone);
-			ipc_call_t answer_data;
-			ipcarg_t answer_rc;
-			aid_t req;
-			int rc;
-			
-			req = async_send_2(dev->phone,
-			    IPC_M_USBVIRT_DATA_TO_DEVICE,
-			    transaction->target.endpoint,
-			    transaction->type,
-			    &answer_data);
-			
-			rc = async_data_write_start(dev->phone,
-			    transaction->buffer, transaction->len);
-			if (rc != EOK) {
-				async_wait_for(req, NULL);
-			} else {
-				async_wait_for(req, &answer_rc);
-				rc = (int)answer_rc;
-			}
-			
-			if (rc != EOK) {
-				outcome = USB_OUTCOME_BABBLE;
-			}
-		} else {
-			outcome = USB_OUTCOME_CRCERROR;
-		}
+		usb_transaction_outcome_t outcome;
+		outcome = virtdev_send_to_all(transaction);
 		
 		process_transaction_with_outcome(transaction, outcome);
Index: uspace/srv/hw/bus/usb/hcd/virtual/hc.h
===================================================================
--- uspace/srv/hw/bus/usb/hcd/virtual/hc.h	(revision 73301a04b2f378b64dab507cd0acf088ce3fc9c3)
+++ uspace/srv/hw/bus/usb/hcd/virtual/hc.h	(revision 47e3a8e044a8e6b9decaf6c981da8d4cc6ece6c6)
@@ -48,4 +48,24 @@
     usb_transaction_outcome_t outcome, void *arg);
 
+/** Pending transaction details. */
+typedef struct {
+	/** Linked-list link. */
+	link_t link;
+	/** Device address. */
+	usb_target_t target;
+	/** Direction of the transaction. */
+	usb_direction_t direction;
+	/** Transfer type. */
+	usb_transfer_type_t type;
+	/** Transaction data buffer. */
+	void * buffer;
+	/** Transaction data length. */
+	size_t len;
+	/** Callback after transaction is done. */
+	hc_transaction_done_callback_t callback;
+	/** Argument to the callback. */
+	void * callback_arg;
+} transaction_t;
+
 void hc_manager(void);
 
