Index: uspace/lib/usbhost/include/usb/host/bus.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/bus.h	(revision 2f762a7c6e72f686c37eb21ceb35942d89b918e5)
+++ uspace/lib/usbhost/include/usb/host/bus.h	(revision 95f1b8fb04a16c3932f15cfbed3adcd434b47bbb)
@@ -153,7 +153,24 @@
 int bus_device_offline(device_t *);
 
-int bus_device_send_batch(device_t *, usb_target_t,
-    usb_direction_t direction, char *, size_t, uint64_t,
-    usbhc_iface_transfer_callback_t, void *, const char *);
+/**
+ * A proforma to USB transfer batch. As opposed to transfer batch, which is
+ * supposed to be a dynamic structrure, this one is static and descriptive only.
+ * Its fields are copied to the final batch.
+ */
+typedef struct transfer_request {
+	usb_target_t target;
+	usb_direction_t dir;
+
+	dma_buffer_t buffer;
+	size_t offset, size;
+	uint64_t setup;
+
+	usbhc_iface_transfer_callback_t on_complete;
+	void *arg;
+
+	const char *name;
+} transfer_request_t;
+
+int bus_issue_transfer(device_t *, const transfer_request_t *);
 
 errno_t bus_device_send_batch_sync(device_t *, usb_target_t,
Index: uspace/lib/usbhost/include/usb/host/endpoint.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 2f762a7c6e72f686c37eb21ceb35942d89b918e5)
+++ uspace/lib/usbhost/include/usb/host/endpoint.h	(revision 95f1b8fb04a16c3932f15cfbed3adcd434b47bbb)
@@ -51,4 +51,5 @@
 typedef struct bus bus_t;
 typedef struct device device_t;
+typedef struct transfer_request transfer_request_t;
 typedef struct usb_transfer_batch usb_transfer_batch_t;
 
@@ -98,6 +99,8 @@
 	/** Maximum size of one transfer */
 	size_t max_transfer_size;
-	/** Policy for transfer buffers */
-	dma_policy_t transfer_buffer_policy;
+
+	/* Policies for transfer buffers */
+	dma_policy_t transfer_buffer_policy;		/**< A hint for optimal performance. */
+	dma_policy_t required_transfer_buffer_policy;	/**< Enforced by the library. */
 
 	/**
@@ -122,7 +125,5 @@
 extern void endpoint_deactivate_locked(endpoint_t *);
 
-int endpoint_send_batch(endpoint_t *, usb_target_t, usb_direction_t,
-    char *, size_t, uint64_t, usbhc_iface_transfer_callback_t, void *,
-    const char *);
+int endpoint_send_batch(endpoint_t *, const transfer_request_t *);
 
 static inline bus_t *endpoint_get_bus(endpoint_t *ep)
Index: uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h
===================================================================
--- uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision 2f762a7c6e72f686c37eb21ceb35942d89b918e5)
+++ uspace/lib/usbhost/include/usb/host/usb_transfer_batch.h	(revision 95f1b8fb04a16c3932f15cfbed3adcd434b47bbb)
@@ -70,14 +70,14 @@
 	} setup;
 
+	/** DMA buffer with enforced policy */
+	dma_buffer_t dma_buffer;
+	/** Size of memory buffer */
+	size_t offset, size;
+
 	/**
 	 * In case a bounce buffer is allocated, the original buffer must to be
 	 * stored to be filled after the IN transaction is finished.
 	 */
-	char *buffer;
-	/** Size of memory buffer */
-	size_t buffer_size;
-
-	/** DMA buffer with enforced policy */
-	dma_buffer_t dma_buffer;
+	char *original_buffer;
 	bool is_bounced;
 
@@ -107,5 +107,5 @@
 	usb_str_transfer_type_short((batch).ep->transfer_type), \
 	usb_str_direction((batch).dir), \
-	(batch).buffer_size, (batch).ep->max_packet_size
+	(batch).size, (batch).ep->max_packet_size
 
 /** Wrapper for bus operation. */
@@ -115,7 +115,7 @@
 void usb_transfer_batch_init(usb_transfer_batch_t *, endpoint_t *);
 
+/** Buffer handling */
+bool usb_transfer_batch_bounce_required(usb_transfer_batch_t *);
 errno_t usb_transfer_batch_bounce(usb_transfer_batch_t *);
-/** Buffer preparation */
-errno_t usb_transfer_batch_prepare_buffer(usb_transfer_batch_t *, char *);
 
 /** Batch finalization. */
