Index: uspace/drv/bus/usb/usbdiag/tests.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/tests.c	(revision fc3dfe6d5430c1408baf598d3bab95dc3cc4b4c8)
+++ uspace/drv/bus/usb/usbdiag/tests.c	(revision d345ce2f2396010ea2fd5ad90e85202da83d5197)
@@ -87,5 +87,5 @@
 
 		while (remaining > 0) {
-			if ((rc = usb_pipe_read_dma(pipe, buffer + size - remaining, remaining, &transferred))) {
+			if ((rc = usb_pipe_read_dma(pipe, buffer, 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;
@@ -181,5 +181,5 @@
 
 		// Write buffer to device.
-		if ((rc = usb_pipe_write_dma(pipe, buffer, size))) {
+		if ((rc = usb_pipe_write_dma(pipe, buffer, 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;
Index: uspace/lib/drv/include/usbhc_iface.h
===================================================================
--- uspace/lib/drv/include/usbhc_iface.h	(revision fc3dfe6d5430c1408baf598d3bab95dc3cc4b4c8)
+++ uspace/lib/drv/include/usbhc_iface.h	(revision d345ce2f2396010ea2fd5ad90e85202da83d5197)
@@ -137,6 +137,8 @@
 	 * large. Is patched after being transmitted over IPC, so the pointer is
 	 * still valid.
+	 *
+	 * Note that offset might be actually more than PAGE_SIZE.
 	 */
-	void *base;			
+	void *base;
 	size_t offset;			/**< Offset to the buffer */
 	size_t size;			/**< Requested size. */
Index: uspace/lib/usbdev/include/usb/dev/pipes.h
===================================================================
--- uspace/lib/usbdev/include/usb/dev/pipes.h	(revision fc3dfe6d5430c1408baf598d3bab95dc3cc4b4c8)
+++ uspace/lib/usbdev/include/usb/dev/pipes.h	(revision d345ce2f2396010ea2fd5ad90e85202da83d5197)
@@ -110,6 +110,6 @@
 errno_t usb_pipe_write(usb_pipe_t *, const void *, size_t);
 
-errno_t usb_pipe_read_dma(usb_pipe_t *, void *, size_t, size_t *);
-errno_t usb_pipe_write_dma(usb_pipe_t *, void *, size_t);
+errno_t usb_pipe_read_dma(usb_pipe_t *, void *, void *, size_t, size_t *);
+errno_t usb_pipe_write_dma(usb_pipe_t *, void *, void *, size_t);
 
 errno_t usb_pipe_control_read(usb_pipe_t *, const void *, size_t,
Index: uspace/lib/usbdev/src/pipes.c
===================================================================
--- uspace/lib/usbdev/src/pipes.c	(revision fc3dfe6d5430c1408baf598d3bab95dc3cc4b4c8)
+++ uspace/lib/usbdev/src/pipes.c	(revision d345ce2f2396010ea2fd5ad90e85202da83d5197)
@@ -68,6 +68,4 @@
 	usb_direction_t dir;
 	bool is_control;	// Only for checking purposes
-	void *buffer;
-	size_t buffer_size;
 
 	usbhc_iface_transfer_request_t req;
@@ -81,49 +79,4 @@
 static errno_t transfer_common(transfer_t *t)
 {
-	async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
-	if (!exch)
-		return ENOMEM;
-
-	t->req.dir = t->dir;
-	t->req.endpoint = t->pipe->desc.endpoint_no;
-
-	/* We support only aligned buffers for now. */
-	t->req.base = t->buffer;
-	t->req.offset = 0;
-	t->req.size = t->buffer_size;
-
-	const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size);
-
-	async_exchange_end(exch);
-
-	if (rc == ESTALL)
-		clear_self_endpoint_halt(t->pipe);
-
-	return rc;
-}
-
-/**
- * Compatibility wrapper for reads/writes without preallocated buffer.
- */
-static errno_t transfer_wrap_dma(transfer_t *t)
-{
-	void *orig_buffer = t->buffer;
-	t->buffer = usb_pipe_alloc_buffer(t->pipe, t->buffer_size);
-
-	if (t->dir == USB_DIRECTION_OUT)
-		memcpy(t->buffer, orig_buffer, t->buffer_size);
-
-	const errno_t err = transfer_common(t);
-
-	if (!err && t->dir == USB_DIRECTION_IN)
-		memcpy(orig_buffer, t->buffer, t->transferred_size);
-
-	usb_pipe_free_buffer(t->pipe, t->buffer);
-	t->buffer = orig_buffer;
-	return err;
-}
-
-static errno_t transfer_check(const transfer_t *t)
-{
 	if (!t->pipe)
 		return EBADMEM;
@@ -131,9 +84,9 @@
 	/* Only control writes make sense without buffer */
 	if ((t->dir != USB_DIRECTION_OUT || !t->is_control)
-	    && (t->buffer == NULL || t->buffer_size == 0))
+	    && (t->req.base == NULL || t->req.size == 0))
 		return EINVAL;
 
 	/* Nonzero size requires buffer */
-	if (t->buffer == NULL && t->buffer_size != 0)
+	if (t->req.base == NULL && t->req.size != 0)
 		return EINVAL;
 
@@ -147,5 +100,50 @@
 		return EBADF;
 
-	return EOK;
+	async_exch_t *exch = async_exchange_begin(t->pipe->bus_session);
+	if (!exch)
+		return ENOMEM;
+
+	t->req.dir = t->dir;
+	t->req.endpoint = t->pipe->desc.endpoint_no;
+
+	const errno_t rc = usbhc_transfer(exch, &t->req, &t->transferred_size);
+
+	async_exchange_end(exch);
+
+	if (rc == ESTALL)
+		clear_self_endpoint_halt(t->pipe);
+
+	return rc;
+}
+
+/**
+ * Setup the transfer request inside transfer according to dma buffer provided.
+ */
+static void setup_dma_buffer(transfer_t *t, void *base, void *ptr, size_t size)
+{
+	t->req.base = base;
+	t->req.offset = ptr - base;
+	t->req.size = size;
+	t->req.buffer_policy = t->pipe->desc.transfer_buffer_policy;
+}
+
+/**
+ * Compatibility wrapper for reads/writes without preallocated buffer.
+ */
+static errno_t transfer_wrap_dma(transfer_t *t, void *buf, size_t size)
+{
+	void *dma_buf = usb_pipe_alloc_buffer(t->pipe, size);
+	setup_dma_buffer(t, dma_buf, dma_buf, size);
+
+	if (t->dir == USB_DIRECTION_OUT)
+		memcpy(dma_buf, buf, size);
+
+	const errno_t err = transfer_common(t);
+
+	if (!err && t->dir == USB_DIRECTION_IN)
+		memcpy(buf, dma_buf, t->transferred_size);
+
+	usb_pipe_free_buffer(t->pipe, dma_buf);
+	return err;
 }
 
@@ -181,15 +179,10 @@
 		.dir = USB_DIRECTION_IN,
 		.is_control = true,
-		.buffer = buffer,
-		.buffer_size = buffer_size
-	};
-
-	if ((err = transfer_check(&transfer)))
-		return err;
+	};
 
 	if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
 		return err;
 
-	if ((err = transfer_wrap_dma(&transfer)))
+	if ((err = transfer_wrap_dma(&transfer, buffer, buffer_size)))
 		return err;
 
@@ -221,15 +214,10 @@
 		.dir = USB_DIRECTION_OUT,
 		.is_control = true,
-		.buffer = (void *) buffer,
-		.buffer_size = buffer_size
-	};
-
-	if ((err = transfer_check(&transfer)))
-		return err;
+	};
 
 	if ((err = prepare_control(&transfer, setup_buffer, setup_buffer_size)))
 		return err;
 
-	return transfer_wrap_dma(&transfer);
+	return transfer_wrap_dma(&transfer, (void *) buffer, buffer_size);
 }
 
@@ -273,12 +261,7 @@
 		.pipe = pipe,
 		.dir = USB_DIRECTION_IN,
-		.buffer = buffer,
-		.buffer_size = size,
-	};
-
-	if ((err = transfer_check(&transfer)))
-		return err;
-
-	if ((err = transfer_wrap_dma(&transfer)))
+	};
+
+	if ((err = transfer_wrap_dma(&transfer, buffer, size)))
 		return err;
 
@@ -299,19 +282,10 @@
 {
 	assert(pipe);
-	errno_t err;
 	transfer_t transfer = {
 		.pipe = pipe,
 		.dir = USB_DIRECTION_OUT,
-		.buffer = (void *) buffer,
-		.buffer_size = size
-	};
-
-	if ((err = transfer_check(&transfer)))
-		return err;
-
-	if ((err = transfer_wrap_dma(&transfer)))
-		return err;
-
-	return EOK;
+	};
+
+	return transfer_wrap_dma(&transfer, (void *) buffer, size);
 }
 
@@ -326,5 +300,5 @@
  * @return Error code.
  */
-errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *buffer, size_t size,
+errno_t usb_pipe_read_dma(usb_pipe_t *pipe, void *base, void *ptr, size_t size,
     size_t *size_transferred)
 {
@@ -334,10 +308,7 @@
 		.pipe = pipe,
 		.dir = USB_DIRECTION_IN,
-		.buffer = buffer,
-		.buffer_size = size
-	};
-
-	if ((err = transfer_check(&transfer)))
-		return err;
+	};
+
+	setup_dma_buffer(&transfer, base, ptr, size);
 
 	if ((err = transfer_common(&transfer)))
@@ -359,22 +330,15 @@
  * @return Error code.
  */
-errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *buffer, size_t size)
-{
-	assert(pipe);
-	errno_t err;
+errno_t usb_pipe_write_dma(usb_pipe_t *pipe, void *base, void* ptr,  size_t size)
+{
+	assert(pipe);
 	transfer_t transfer = {
 		.pipe = pipe,
 		.dir = USB_DIRECTION_OUT,
-		.buffer = buffer,
-		.buffer_size = size
-	};
-
-	if ((err = transfer_check(&transfer)))
-		return err;
-
-	if ((err = transfer_common(&transfer)))
-		return err;
-
-	return EOK;
+	};
+
+	setup_dma_buffer(&transfer, base, ptr, size);
+
+	return transfer_common(&transfer);
 }
 
