Index: uspace/drv/bus/usb/usbdiag/device.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/device.c	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/drv/bus/usb/usbdiag/device.c	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -46,16 +46,6 @@
 
 static usbdiag_iface_t diag_interface = {
-	.burst_intr_in = usbdiag_burst_test_intr_in,
-	.burst_intr_out = usbdiag_burst_test_intr_out,
-	.burst_bulk_in = usbdiag_burst_test_bulk_in,
-	.burst_bulk_out = usbdiag_burst_test_bulk_out,
-	.burst_isoch_in = usbdiag_burst_test_isoch_in,
-	.burst_isoch_out = usbdiag_burst_test_isoch_out,
-	.data_intr_in = usbdiag_data_test_intr_in,
-	.data_intr_out = usbdiag_data_test_intr_out,
-	.data_bulk_in = usbdiag_data_test_bulk_in,
-	.data_bulk_out = usbdiag_data_test_bulk_out,
-	.data_isoch_in = usbdiag_data_test_isoch_in,
-	.data_isoch_out = usbdiag_data_test_isoch_out
+	.test_in = usbdiag_dev_test_in,
+	.test_out = usbdiag_dev_test_out,
 };
 
@@ -86,10 +76,16 @@
 	} while (0);
 
-	_MAP_EP(dev->intr_in, INTR_IN);
-	_MAP_EP(dev->intr_out, INTR_OUT);
-	_MAP_EP(dev->bulk_in, BULK_IN);
-	_MAP_EP(dev->bulk_out, BULK_OUT);
-	_MAP_EP(dev->isoch_in, ISOCH_IN);
-	_MAP_EP(dev->isoch_out, ISOCH_OUT);
+	_MAP_EP(dev->burst_intr_in, BURST_INTR_IN);
+	_MAP_EP(dev->burst_intr_out, BURST_INTR_OUT);
+	_MAP_EP(dev->burst_bulk_in, BURST_BULK_IN);
+	_MAP_EP(dev->burst_bulk_out, BURST_BULK_OUT);
+	_MAP_EP(dev->burst_isoch_in, BURST_ISOCH_IN);
+	_MAP_EP(dev->burst_isoch_out, BURST_ISOCH_OUT);
+	_MAP_EP(dev->data_intr_in, DATA_INTR_IN);
+	_MAP_EP(dev->data_intr_out, DATA_INTR_OUT);
+	_MAP_EP(dev->data_bulk_in, DATA_BULK_IN);
+	_MAP_EP(dev->data_bulk_out, DATA_BULK_OUT);
+	_MAP_EP(dev->data_isoch_in, DATA_ISOCH_IN);
+	_MAP_EP(dev->data_isoch_out, DATA_ISOCH_OUT);
 
 #undef _MAP_EP
Index: uspace/drv/bus/usb/usbdiag/device.h
===================================================================
--- uspace/drv/bus/usb/usbdiag/device.h	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/drv/bus/usb/usbdiag/device.h	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -40,10 +40,17 @@
 #include <usb/dev/driver.h>
 
-#define USBDIAG_EP_INTR_IN    1
-#define USBDIAG_EP_INTR_OUT   2
-#define USBDIAG_EP_BULK_IN    3
-#define USBDIAG_EP_BULK_OUT   4
-#define USBDIAG_EP_ISOCH_IN   5
-#define USBDIAG_EP_ISOCH_OUT  6
+#define USBDIAG_EP_BURST_INTR_IN    1
+#define USBDIAG_EP_BURST_INTR_OUT   2
+#define USBDIAG_EP_BURST_BULK_IN    3
+#define USBDIAG_EP_BURST_BULK_OUT   4
+#define USBDIAG_EP_BURST_ISOCH_IN   5
+#define USBDIAG_EP_BURST_ISOCH_OUT  6
+
+#define USBDIAG_EP_DATA_INTR_IN     7
+#define USBDIAG_EP_DATA_INTR_OUT    8
+#define USBDIAG_EP_DATA_BULK_IN     9
+#define USBDIAG_EP_DATA_BULK_OUT   10
+#define USBDIAG_EP_DATA_ISOCH_IN   11
+#define USBDIAG_EP_DATA_ISOCH_OUT  12
 
 /**
@@ -53,10 +60,19 @@
 	usb_device_t *usb_dev;
 	ddf_fun_t *fun;
-	usb_pipe_t *intr_in;
-	usb_pipe_t *intr_out;
-	usb_pipe_t *bulk_in;
-	usb_pipe_t *bulk_out;
-	usb_pipe_t *isoch_in;
-	usb_pipe_t *isoch_out;
+
+	usb_pipe_t *burst_intr_in;
+	usb_pipe_t *burst_intr_out;
+	usb_pipe_t *burst_bulk_in;
+	usb_pipe_t *burst_bulk_out;
+	usb_pipe_t *burst_isoch_in;
+	usb_pipe_t *burst_isoch_out;
+
+	usb_pipe_t *data_intr_in;
+	usb_pipe_t *data_intr_out;
+	usb_pipe_t *data_bulk_in;
+	usb_pipe_t *data_bulk_out;
+	usb_pipe_t *data_isoch_in;
+	usb_pipe_t *data_isoch_out;
+
 } usbdiag_dev_t;
 
Index: uspace/drv/bus/usb/usbdiag/main.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/main.c	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/drv/bus/usb/usbdiag/main.c	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -139,45 +139,93 @@
 }
 
-static const usb_endpoint_description_t intr_in_ep = {
-	.transfer_type = USB_TRANSFER_INTERRUPT,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_DIAGNOSTIC,
-	.interface_subclass = 0x00,
-	.interface_protocol = 0x01,
-	.flags = 0
-};
-static const usb_endpoint_description_t intr_out_ep = {
-	.transfer_type = USB_TRANSFER_INTERRUPT,
-	.direction = USB_DIRECTION_OUT,
-	.interface_class = USB_CLASS_DIAGNOSTIC,
-	.interface_subclass = 0x00,
-	.interface_protocol = 0x01,
-	.flags = 0
-};
-static const usb_endpoint_description_t bulk_in_ep = {
-	.transfer_type = USB_TRANSFER_BULK,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_DIAGNOSTIC,
-	.interface_subclass = 0x00,
-	.interface_protocol = 0x01,
-	.flags = 0
-};
-static const usb_endpoint_description_t bulk_out_ep = {
-	.transfer_type = USB_TRANSFER_BULK,
-	.direction = USB_DIRECTION_OUT,
-	.interface_class = USB_CLASS_DIAGNOSTIC,
-	.interface_subclass = 0x00,
-	.interface_protocol = 0x01,
-	.flags = 0
-};
-static const usb_endpoint_description_t isoch_in_ep = {
-	.transfer_type = USB_TRANSFER_ISOCHRONOUS,
-	.direction = USB_DIRECTION_IN,
-	.interface_class = USB_CLASS_DIAGNOSTIC,
-	.interface_subclass = 0x00,
-	.interface_protocol = 0x01,
-	.flags = 0
-};
-static const usb_endpoint_description_t isoch_out_ep = {
+static const usb_endpoint_description_t burst_intr_in_ep = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t burst_intr_out_ep = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t burst_bulk_in_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t burst_bulk_out_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t burst_isoch_in_ep = {
+	.transfer_type = USB_TRANSFER_ISOCHRONOUS,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t burst_isoch_out_ep = {
+	.transfer_type = USB_TRANSFER_ISOCHRONOUS,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t data_intr_in_ep = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t data_intr_out_ep = {
+	.transfer_type = USB_TRANSFER_INTERRUPT,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t data_bulk_in_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t data_bulk_out_ep = {
+	.transfer_type = USB_TRANSFER_BULK,
+	.direction = USB_DIRECTION_OUT,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t data_isoch_in_ep = {
+	.transfer_type = USB_TRANSFER_ISOCHRONOUS,
+	.direction = USB_DIRECTION_IN,
+	.interface_class = USB_CLASS_DIAGNOSTIC,
+	.interface_subclass = 0x00,
+	.interface_protocol = 0x01,
+	.flags = 0
+};
+static const usb_endpoint_description_t data_isoch_out_ep = {
 	.transfer_type = USB_TRANSFER_ISOCHRONOUS,
 	.direction = USB_DIRECTION_OUT,
@@ -189,10 +237,16 @@
 
 static const usb_endpoint_description_t *diag_endpoints[] = {
-	[USBDIAG_EP_INTR_IN] = &intr_in_ep,
-	[USBDIAG_EP_INTR_OUT] = &intr_out_ep,
-	[USBDIAG_EP_BULK_IN] = &bulk_in_ep,
-	[USBDIAG_EP_BULK_OUT] = &bulk_out_ep,
-	[USBDIAG_EP_ISOCH_IN] = &isoch_in_ep,
-	[USBDIAG_EP_ISOCH_OUT] = &isoch_out_ep,
+	[USBDIAG_EP_BURST_INTR_IN] = &burst_intr_in_ep,
+	[USBDIAG_EP_BURST_INTR_OUT] = &burst_intr_out_ep,
+	[USBDIAG_EP_BURST_BULK_IN] = &burst_bulk_in_ep,
+	[USBDIAG_EP_BURST_BULK_OUT] = &burst_bulk_out_ep,
+	[USBDIAG_EP_BURST_ISOCH_IN] = &burst_isoch_in_ep,
+	[USBDIAG_EP_BURST_ISOCH_OUT] = &burst_isoch_out_ep,
+	[USBDIAG_EP_DATA_INTR_IN] = &data_intr_in_ep,
+	[USBDIAG_EP_DATA_INTR_OUT] = &data_intr_out_ep,
+	[USBDIAG_EP_DATA_BULK_IN] = &data_bulk_in_ep,
+	[USBDIAG_EP_DATA_BULK_OUT] = &data_bulk_out_ep,
+	[USBDIAG_EP_DATA_ISOCH_IN] = &data_isoch_in_ep,
+	[USBDIAG_EP_DATA_ISOCH_OUT] = &data_isoch_out_ep,
 	NULL
 };
Index: uspace/drv/bus/usb/usbdiag/tests.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/tests.c	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/drv/bus/usb/usbdiag/tests.c	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -44,8 +44,19 @@
 #define NAME "usbdiag"
 
-static int burst_in_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
+static const uint32_t test_data_src = 0xDEADBEEF;
+
+static int test_in(usb_pipe_t *pipe, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
 {
 	if (!pipe)
 		return EBADMEM;
+
+	bool validate = params->validate_data;
+	size_t size = params->transfer_size;
+	if (!size)
+		size = pipe->desc.max_transfer_size;
+
+	const uint32_t test_data = uint32_host2usb(test_data_src);
+	if (validate && size % sizeof(test_data))
+		return EINVAL;
 
 	char *buffer = (char *) malloc(size);
@@ -55,11 +66,19 @@
 	// TODO: Are we sure that no other test is running on this endpoint?
 
-	usb_log_info("Performing %s IN burst test.", usb_str_transfer_type(pipe->desc.transfer_type));
+	usb_log_info("Performing %s IN test with duration %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), params->min_duration);
 
 	int rc = EOK;
-	struct timeval start_time;
+	uint32_t transfer_count = 0;
+
+	struct timeval start_time, final_time, stop_time;
 	gettimeofday(&start_time, NULL);
-
-	for (int i = 0; i < cycles; ++i) {
+	gettimeofday(&stop_time, NULL);
+
+	tv_add_diff(&stop_time, params->min_duration * 1000);
+	gettimeofday(&final_time, NULL);
+
+	while (!tv_gt(&final_time, &stop_time)) {
+		++transfer_count;
+
 		// Read device's response.
 		size_t remaining = size;
@@ -83,24 +102,51 @@
 		if (rc)
 			break;
-	}
-
-	struct timeval final_time;
-	gettimeofday(&final_time, NULL);
+
+		if (validate) {
+			for (size_t i = 0; i < size; i += sizeof(test_data)) {
+				if (*(uint32_t *)(buffer + i) != test_data) {
+					usb_log_error("Read of %s IN endpoint returned "
+						"invald data at address %zu.",
+						usb_str_transfer_type(pipe->desc.transfer_type), i);
+					rc = EINVAL;
+					break;
+				}
+			}
+
+			if (rc)
+				break;
+		}
+
+		gettimeofday(&final_time, NULL);
+	}
+
 	usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
 	    ((final_time.tv_sec - start_time.tv_sec) * 1000);
 
-	usb_log_info("Burst test on %s IN endpoint completed in %lu ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
+	usb_log_info("Test on %s IN endpoint completed in %lu ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
+
+	results->act_duration = in_duration;
+	results->transfer_count = transfer_count;
+	results->transfer_size = size;
 
 	free(buffer);
-	if (duration)
-		*duration = in_duration;
 
 	return rc;
 }
 
-static int burst_out_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
+static int test_out(usb_pipe_t *pipe, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
 {
 	if (!pipe)
 		return EBADMEM;
+
+	bool validate = params->validate_data;
+	size_t size = params->transfer_size;
+	if (!size)
+		size = pipe->desc.max_transfer_size;
+
+	const uint32_t test_data = uint32_host2usb(test_data_src);
+
+	if (validate && size % sizeof(test_data))
+		return EINVAL;
 
 	char *buffer = (char *) malloc(size);
@@ -108,15 +154,27 @@
 		return ENOMEM;
 
-	memset(buffer, 42, size);
+	if (validate) {
+		for (size_t i = 0; i < size; i += sizeof(test_data)) {
+			memcpy(buffer + i, &test_data, sizeof(test_data));
+		}
+	}
 
 	// TODO: Are we sure that no other test is running on this endpoint?
 
-	usb_log_info("Performing %s OUT burst test.", usb_str_transfer_type(pipe->desc.transfer_type));
+	usb_log_info("Performing %s OUT test.", usb_str_transfer_type(pipe->desc.transfer_type));
 
 	int rc = EOK;
-	struct timeval start_time;
+	uint32_t transfer_count = 0;
+
+	struct timeval start_time, final_time, stop_time;
 	gettimeofday(&start_time, NULL);
-
-	for (int i = 0; i < cycles; ++i) {
+	gettimeofday(&stop_time, NULL);
+
+	tv_add_diff(&stop_time, params->min_duration * 1000);
+	gettimeofday(&final_time, NULL);
+
+	while (!tv_gt(&final_time, &stop_time)) {
+		++transfer_count;
+
 		// Write buffer to device.
 		if ((rc = usb_pipe_write(pipe, buffer, size))) {
@@ -124,144 +182,23 @@
 			break;
 		}
-	}
-
-	struct timeval final_time;
-	gettimeofday(&final_time, NULL);
+
+		gettimeofday(&final_time, NULL);
+	}
+
 	usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
 	    ((final_time.tv_sec - start_time.tv_sec) * 1000);
 
-	usb_log_info("Burst test on %s OUT endpoint completed in %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
+	usb_log_info("Test on %s OUT endpoint completed in %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
+
+	results->act_duration = in_duration;
+	results->transfer_count = transfer_count;
+	results->transfer_size = size;
 
 	free(buffer);
-	if (duration)
-		*duration = in_duration;
 
 	return rc;
 }
 
-static const uint32_t test_data_src = 0xDEADBEEF;
-
-static int data_in_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!pipe)
-		return EBADMEM;
-
-	const uint32_t test_data = uint32_host2usb(test_data_src);
-
-	if (size % sizeof(test_data))
-		return EINVAL;
-
-	char *buffer = (char *) malloc(size);
-	if (!buffer)
-		return ENOMEM;
-
-	// TODO: Are we sure that no other test is running on this endpoint?
-
-	usb_log_info("Performing %s IN data test.", usb_str_transfer_type(pipe->desc.transfer_type));
-
-	int rc = EOK;
-	struct timeval start_time;
-	gettimeofday(&start_time, NULL);
-
-	for (int i = 0; i < cycles; ++i) {
-		// Read device's response.
-		size_t remaining = size;
-		size_t transferred;
-
-		while (remaining > 0) {
-			if ((rc = usb_pipe_read(pipe, buffer + size - remaining, remaining, &transferred))) {
-				usb_log_error("Read of %s IN endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
-				break;
-			}
-
-			if (transferred > remaining) {
-				usb_log_error("Read of %s IN endpoint returned more data than expected.", usb_str_transfer_type(pipe->desc.transfer_type));
-				rc = EINVAL;
-				break;
-			}
-
-			remaining -= transferred;
-		}
-
-		if (rc)
-			break;
-
-		for (size_t i = 0; i < size; i += sizeof(test_data)) {
-			if (*(uint32_t *)(buffer + i) != test_data) {
-				usb_log_error("Read of %s IN endpoint returned "
-				    "invald data at address %zu.",
-				    usb_str_transfer_type(pipe->desc.transfer_type), i);
-				rc = EINVAL;
-				break;
-			}
-		}
-
-		if (rc)
-			break;
-	}
-
-	struct timeval final_time;
-	gettimeofday(&final_time, NULL);
-	usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
-	    ((final_time.tv_sec - start_time.tv_sec) * 1000);
-
-	usb_log_info("Data test on %s IN endpoint completed in %lu ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
-
-	free(buffer);
-	if (duration)
-		*duration = in_duration;
-
-	return rc;
-}
-
-static int data_out_test(usb_pipe_t *pipe, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!pipe)
-		return EBADMEM;
-
-	const uint32_t test_data = uint32_host2usb(test_data_src);
-
-	if (size % sizeof(test_data))
-		return EINVAL;
-
-	char *buffer = (char *) malloc(size);
-	if (!buffer)
-		return ENOMEM;
-
-	for (size_t i = 0; i < size; i += sizeof(test_data)) {
-		memcpy(buffer + i, &test_data, sizeof(test_data));
-	}
-
-	// TODO: Are we sure that no other test is running on this endpoint?
-
-	usb_log_info("Performing %s OUT data test.", usb_str_transfer_type(pipe->desc.transfer_type));
-
-	int rc = EOK;
-	struct timeval start_time;
-	gettimeofday(&start_time, NULL);
-
-	for (int i = 0; i < cycles; ++i) {
-		// Write buffer to device.
-		if ((rc = usb_pipe_write(pipe, buffer, size))) {
-			usb_log_error("Write to %s OUT endpoint failed with error: %s", usb_str_transfer_type(pipe->desc.transfer_type), str_error(rc));
-			break;
-		}
-	}
-
-	struct timeval final_time;
-	gettimeofday(&final_time, NULL);
-	usbdiag_dur_t in_duration = ((final_time.tv_usec - start_time.tv_usec) / 1000) +
-	    ((final_time.tv_sec - start_time.tv_sec) * 1000);
-
-	usb_log_info("Data test on %s OUT endpoint completed in %ld ms.", usb_str_transfer_type(pipe->desc.transfer_type), in_duration);
-
-	free(buffer);
-	if (duration)
-		*duration = in_duration;
-
-	return rc;
-}
-
-int usbdiag_burst_test_intr_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
+int usbdiag_dev_test_in(ddf_fun_t *fun, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
 {
 	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
@@ -269,8 +206,24 @@
 		return EBADMEM;
 
-	return burst_in_test(dev->intr_in, cycles, size, duration);
-}
-
-int usbdiag_burst_test_intr_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
+	usb_pipe_t *pipe;
+
+	switch (params->transfer_type) {
+	case USB_TRANSFER_INTERRUPT:
+		pipe = params->validate_data ? dev->data_intr_in : dev->burst_intr_in;
+		break;
+	case USB_TRANSFER_BULK:
+		pipe = params->validate_data ? dev->data_bulk_in : dev->burst_bulk_in;
+		break;
+	case USB_TRANSFER_ISOCHRONOUS:
+		pipe = params->validate_data ? dev->data_isoch_in : dev->burst_isoch_in;
+		break;
+	default:
+		return ENOTSUP;
+	}
+
+	return test_in(pipe, params, results);
+}
+
+int usbdiag_dev_test_out(ddf_fun_t *fun, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
 {
 	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
@@ -278,95 +231,21 @@
 		return EBADMEM;
 
-	return burst_out_test(dev->intr_out, cycles, size, duration);
-}
-
-int usbdiag_burst_test_bulk_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return burst_in_test(dev->bulk_in, cycles, size, duration);
-}
-
-int usbdiag_burst_test_bulk_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return burst_out_test(dev->bulk_out, cycles, size, duration);
-}
-
-int usbdiag_burst_test_isoch_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return burst_in_test(dev->isoch_in, cycles, size, duration);
-}
-
-int usbdiag_burst_test_isoch_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return burst_out_test(dev->isoch_out, cycles, size, duration);
-}
-
-int usbdiag_data_test_intr_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return data_in_test(dev->intr_in, cycles, size, duration);
-}
-
-int usbdiag_data_test_intr_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return data_out_test(dev->intr_out, cycles, size, duration);
-}
-
-int usbdiag_data_test_bulk_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return data_in_test(dev->bulk_in, cycles, size, duration);
-}
-
-int usbdiag_data_test_bulk_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return data_out_test(dev->bulk_out, cycles, size, duration);
-}
-
-int usbdiag_data_test_isoch_in(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return data_in_test(dev->isoch_in, cycles, size, duration);
-}
-
-int usbdiag_data_test_isoch_out(ddf_fun_t *fun, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	usbdiag_dev_t *dev = ddf_fun_to_usbdiag_dev(fun);
-	if (!dev)
-		return EBADMEM;
-
-	return data_out_test(dev->isoch_out, cycles, size, duration);
+	usb_pipe_t *pipe;
+
+	switch (params->transfer_type) {
+	case USB_TRANSFER_INTERRUPT:
+		pipe = params->validate_data ? dev->data_intr_out : dev->burst_intr_out;
+		break;
+	case USB_TRANSFER_BULK:
+		pipe = params->validate_data ? dev->data_bulk_out : dev->burst_bulk_out;
+		break;
+	case USB_TRANSFER_ISOCHRONOUS:
+		pipe = params->validate_data ? dev->data_isoch_out : dev->burst_isoch_out;
+		break;
+	default:
+		return ENOTSUP;
+	}
+
+	return test_out(pipe, params, results);
 }
 
Index: uspace/drv/bus/usb/usbdiag/tests.h
===================================================================
--- uspace/drv/bus/usb/usbdiag/tests.h	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/drv/bus/usb/usbdiag/tests.h	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -39,17 +39,6 @@
 #include <ddf/driver.h>
 
-int usbdiag_burst_test_intr_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_burst_test_intr_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_burst_test_bulk_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_burst_test_bulk_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_burst_test_isoch_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_burst_test_isoch_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-
-int usbdiag_data_test_intr_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_data_test_intr_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_data_test_bulk_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_data_test_bulk_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_data_test_isoch_in(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
-int usbdiag_data_test_isoch_out(ddf_fun_t *, int, size_t, usbdiag_dur_t *);
+int usbdiag_dev_test_in(ddf_fun_t *, const usbdiag_test_params_t *, usbdiag_test_results_t *);
+int usbdiag_dev_test_out(ddf_fun_t *, const usbdiag_test_params_t *, usbdiag_test_results_t *);
 
 #endif /* USBDIAG_TESTS_H_ */
Index: uspace/lib/drv/generic/remote_usbdiag.c
===================================================================
--- uspace/lib/drv/generic/remote_usbdiag.c	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/lib/drv/generic/remote_usbdiag.c	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -43,16 +43,6 @@
 
 typedef enum {
-	IPC_M_USBDIAG_BURST_INTR_IN,
-	IPC_M_USBDIAG_BURST_INTR_OUT,
-	IPC_M_USBDIAG_BURST_BULK_IN,
-	IPC_M_USBDIAG_BURST_BULK_OUT,
-	IPC_M_USBDIAG_BURST_ISOCH_IN,
-	IPC_M_USBDIAG_BURST_ISOCH_OUT,
-	IPC_M_USBDIAG_DATA_INTR_IN,
-	IPC_M_USBDIAG_DATA_INTR_OUT,
-	IPC_M_USBDIAG_DATA_BULK_IN,
-	IPC_M_USBDIAG_DATA_BULK_OUT,
-	IPC_M_USBDIAG_DATA_ISOCH_IN,
-	IPC_M_USBDIAG_DATA_ISOCH_OUT
+	IPC_M_USBDIAG_TEST_IN,
+	IPC_M_USBDIAG_TEST_OUT,
 } usb_iface_funcs_t;
 
@@ -68,200 +58,71 @@
 }
 
-int usbdiag_burst_intr_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
+int usbdiag_test_in(async_exch_t *exch, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
 {
 	if (!exch)
 		return EBADMEM;
 
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_INTR_IN, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_burst_intr_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_TEST_IN, &answer);
+
+	int rc = async_data_write_start(exch, params, sizeof(usbdiag_test_params_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+
+	rc = async_data_read_start(exch, results, sizeof(usbdiag_test_results_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+
+	async_exchange_end(exch);
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	return (int) retval;
+}
+
+int usbdiag_test_out(async_exch_t *exch, const usbdiag_test_params_t *params, usbdiag_test_results_t *results)
 {
 	if (!exch)
 		return EBADMEM;
 
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_INTR_OUT, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_burst_bulk_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_BULK_IN, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_burst_bulk_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_BULK_OUT, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_burst_isoch_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_ISOCH_IN, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_burst_isoch_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_BURST_ISOCH_OUT, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_data_intr_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_INTR_IN, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_data_intr_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_INTR_OUT, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_data_bulk_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_BULK_IN, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_data_bulk_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_BULK_OUT, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_data_isoch_in(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_ISOCH_IN, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-int usbdiag_data_isoch_out(async_exch_t *exch, int cycles, size_t size, usbdiag_dur_t *duration)
-{
-	if (!exch)
-		return EBADMEM;
-
-	sysarg_t duration_;
-	const int rc = async_req_3_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_DATA_ISOCH_OUT, cycles, size, &duration_);
-
-	if (rc == EOK && duration)
-		*duration = duration_;
-
-	return rc;
-}
-
-static void remote_usbdiag_burst_intr_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_burst_intr_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_burst_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_burst_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_burst_isoch_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_burst_isoch_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-
-static void remote_usbdiag_data_intr_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_data_intr_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_data_bulk_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_data_bulk_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_data_isoch_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
-static void remote_usbdiag_data_isoch_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, DEV_IFACE_ID(USBDIAG_DEV_IFACE), IPC_M_USBDIAG_TEST_OUT, &answer);
+
+	int rc = async_data_write_start(exch, params, sizeof(usbdiag_test_params_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+
+	rc = async_data_read_start(exch, results, sizeof(usbdiag_test_results_t));
+	if (rc != EOK) {
+		async_exchange_end(exch);
+		async_forget(req);
+		return rc;
+	}
+
+	async_exchange_end(exch);
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+
+	return (int) retval;
+}
+
+static void remote_usbdiag_test_in(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
+static void remote_usbdiag_test_out(ddf_fun_t *, void *, ipc_callid_t, ipc_call_t *);
 
 /** Remote USB diagnostic interface operations. */
 static const remote_iface_func_ptr_t remote_usbdiag_iface_ops [] = {
-	[IPC_M_USBDIAG_BURST_INTR_IN] = remote_usbdiag_burst_intr_in,
-	[IPC_M_USBDIAG_BURST_INTR_OUT] = remote_usbdiag_burst_intr_out,
-	[IPC_M_USBDIAG_BURST_BULK_IN] = remote_usbdiag_burst_bulk_in,
-	[IPC_M_USBDIAG_BURST_BULK_OUT] = remote_usbdiag_burst_bulk_out,
-	[IPC_M_USBDIAG_BURST_ISOCH_IN] = remote_usbdiag_burst_isoch_in,
-	[IPC_M_USBDIAG_BURST_ISOCH_OUT] = remote_usbdiag_burst_isoch_out,
-	[IPC_M_USBDIAG_DATA_INTR_IN] = remote_usbdiag_data_intr_in,
-	[IPC_M_USBDIAG_DATA_INTR_OUT] = remote_usbdiag_data_intr_out,
-	[IPC_M_USBDIAG_DATA_BULK_IN] = remote_usbdiag_data_bulk_in,
-	[IPC_M_USBDIAG_DATA_BULK_OUT] = remote_usbdiag_data_bulk_out,
-	[IPC_M_USBDIAG_DATA_ISOCH_IN] = remote_usbdiag_data_isoch_in,
-	[IPC_M_USBDIAG_DATA_ISOCH_OUT] = remote_usbdiag_data_isoch_out
+	[IPC_M_USBDIAG_TEST_IN] = remote_usbdiag_test_in,
+	[IPC_M_USBDIAG_TEST_OUT] = remote_usbdiag_test_out
 };
 
@@ -272,254 +133,106 @@
 };
 
-void remote_usbdiag_burst_intr_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+void remote_usbdiag_test_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
 {
 	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
 
-	if (diag_iface->burst_bulk_in == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->burst_intr_in(fun, cycles, size, &duration);
+	size_t size;
+	ipc_callid_t data_callid;
+	if (!async_data_write_receive(&data_callid, &size)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (size != sizeof(usbdiag_test_params_t)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	usbdiag_test_params_t params;
+	if (async_data_write_finalize(data_callid, &params, size) != EOK) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	usbdiag_test_results_t results;
+	const int ret = !diag_iface->test_in ? ENOTSUP : diag_iface->test_in(fun, &params, &results);
 
 	if (ret != EOK) {
 		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_burst_intr_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
+		return;
+	}
+
+	if (!async_data_read_receive(&data_callid, &size)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (size != sizeof(usbdiag_test_results_t)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	if (async_data_read_finalize(data_callid, &results, size) != EOK) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	async_answer_0(callid, ret);
+}
+
+void remote_usbdiag_test_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
 {
 	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
 
-	if (diag_iface->burst_bulk_out == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->burst_intr_out(fun, cycles, size, &duration);
+	size_t size;
+	ipc_callid_t data_callid;
+	if (!async_data_write_receive(&data_callid, &size)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (size != sizeof(usbdiag_test_params_t)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	usbdiag_test_params_t params;
+	if (async_data_write_finalize(data_callid, &params, size) != EOK) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	usbdiag_test_results_t results;
+	const int ret = !diag_iface->test_out ? ENOTSUP : diag_iface->test_out(fun, &params, &results);
 
 	if (ret != EOK) {
 		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_burst_bulk_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->burst_bulk_in == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->burst_bulk_in(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_burst_bulk_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->burst_bulk_out == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->burst_bulk_out(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_burst_isoch_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->burst_isoch_in == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->burst_isoch_in(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_burst_isoch_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->burst_isoch_out == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->burst_isoch_out(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_data_intr_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->data_bulk_in == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->data_intr_in(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_data_intr_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->data_bulk_out == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->data_intr_out(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_data_bulk_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->data_bulk_in == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->data_bulk_in(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_data_bulk_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->data_bulk_out == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->data_bulk_out(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_data_isoch_in(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->data_isoch_in == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->data_isoch_in(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
-}
-
-void remote_usbdiag_data_isoch_out(ddf_fun_t *fun, void *iface, ipc_callid_t callid, ipc_call_t *call)
-{
-	const usbdiag_iface_t *diag_iface = (usbdiag_iface_t *) iface;
-
-	if (diag_iface->data_isoch_out == NULL) {
-		async_answer_0(callid, ENOTSUP);
-		return;
-	}
-
-	int cycles = DEV_IPC_GET_ARG1(*call);
-	size_t size = DEV_IPC_GET_ARG2(*call);
-	usbdiag_dur_t duration;
-	const int ret = diag_iface->data_isoch_out(fun, cycles, size, &duration);
-
-	if (ret != EOK) {
-		async_answer_0(callid, ret);
-	} else {
-		async_answer_1(callid, EOK, duration);
-	}
+		return;
+	}
+
+	if (!async_data_read_receive(&data_callid, &size)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (size != sizeof(usbdiag_test_results_t)) {
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+	
+	if (async_data_read_finalize(data_callid, &results, size) != EOK) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	async_answer_0(callid, ret);
 }
 
Index: uspace/lib/drv/include/usbdiag_iface.h
===================================================================
--- uspace/lib/drv/include/usbdiag_iface.h	(revision 24c41ba116f95ed1d1214737917cffc3db92868d)
+++ uspace/lib/drv/include/usbdiag_iface.h	(revision 8393c73b627efedd36e9f17f530125baff7a47c6)
@@ -39,4 +39,5 @@
 
 #include <async.h>
+#include <usbhc_iface.h>
 #include "ddf/driver.h"
 
@@ -46,35 +47,29 @@
 typedef unsigned long usbdiag_dur_t;
 
+/** Test parameters. */
+typedef struct usbdiag_test_params {
+	usb_transfer_type_t transfer_type;
+	size_t transfer_size;
+	usbdiag_dur_t min_duration;
+	bool validate_data;
+} usbdiag_test_params_t;
+
+/** Test results. */
+typedef struct usbdiag_test_results {
+	usbdiag_dur_t act_duration;
+	uint32_t transfer_count;
+	size_t transfer_size;
+} usbdiag_test_results_t;
+
 async_sess_t *usbdiag_connect(devman_handle_t);
 void usbdiag_disconnect(async_sess_t*);
 
-int usbdiag_burst_intr_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_burst_intr_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_burst_bulk_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_burst_bulk_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_burst_isoch_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_burst_isoch_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
-
-int usbdiag_data_intr_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_data_intr_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_data_bulk_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_data_bulk_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_data_isoch_in(async_exch_t*, int, size_t, usbdiag_dur_t*);
-int usbdiag_data_isoch_out(async_exch_t*, int, size_t, usbdiag_dur_t*);
+int usbdiag_test_in(async_exch_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
+int usbdiag_test_out(async_exch_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
 
 /** USB diagnostic device communication interface. */
 typedef struct {
-	int (*burst_intr_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*burst_intr_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*burst_bulk_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*burst_bulk_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*burst_isoch_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*burst_isoch_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*data_intr_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*data_intr_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*data_bulk_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*data_bulk_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*data_isoch_in)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
-	int (*data_isoch_out)(ddf_fun_t*, int, size_t, usbdiag_dur_t*);
+	int (*test_in)(ddf_fun_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
+	int (*test_out)(ddf_fun_t*, const usbdiag_test_params_t *, usbdiag_test_results_t *);
 } usbdiag_iface_t;
 
