Index: uspace/lib/usb/Makefile
===================================================================
--- uspace/lib/usb/Makefile	(revision d5ac90f0e33c4c353bae229add2cc7d993740ee7)
+++ uspace/lib/usb/Makefile	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -43,4 +43,5 @@
 	src/hidparser.c \
 	src/hub.c \
+	src/pipepriv.c \
 	src/pipes.c \
 	src/pipesinit.c \
Index: uspace/lib/usb/include/usb/pipes.h
===================================================================
--- uspace/lib/usb/include/usb/pipes.h	(revision d5ac90f0e33c4c353bae229add2cc7d993740ee7)
+++ uspace/lib/usb/include/usb/pipes.h	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -84,4 +84,7 @@
 	/** Guard for serialization of requests over the phone. */
 	fibril_mutex_t hc_phone_mutex;
+
+	/** Number of active transfers over the pipe. */
+	int refcount;
 } usb_pipe_t;
 
Index: uspace/lib/usb/src/pipepriv.c
===================================================================
--- uspace/lib/usb/src/pipepriv.c	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
+++ uspace/lib/usb/src/pipepriv.c	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb
+ * @{
+ */
+/** @file
+ * Library internal functions on USB pipes (implementation).
+ */
+#include "pipepriv.h"
+#include <devman.h>
+#include <errno.h>
+#include <assert.h>
+
+/** Ensure exclusive access to the IPC phone of given pipe.
+ *
+ * @param pipe Pipe to be exclusively accessed.
+ */
+void pipe_acquire(usb_pipe_t *pipe)
+{
+	fibril_mutex_lock(&pipe->hc_phone_mutex);
+}
+
+/** Terminate exclusive access to the IPC phone of given pipe.
+ *
+ * @param pipe Pipe to be released from exclusive usage.
+ */
+void pipe_release(usb_pipe_t *pipe)
+{
+	fibril_mutex_unlock(&pipe->hc_phone_mutex);
+}
+
+/** Add reference of active transfers over the pipe.
+ *
+ * @param pipe The USB pipe.
+ * @return Error code.
+ * @retval EOK Currently always.
+ */
+int pipe_add_ref(usb_pipe_t *pipe)
+{
+another_try:
+	pipe_acquire(pipe);
+
+	if (pipe->refcount == 0) {
+		/* Need to open the phone by ourselves. */
+		int phone = devman_device_connect(pipe->wire->hc_handle, 0);
+		if (phone < 0) {
+			// TODO: treat some error as non-recoverable
+			// and return error from here
+			pipe_release(pipe);
+			goto another_try;
+		}
+		pipe->hc_phone = phone;
+	}
+	pipe->refcount++;
+
+	pipe_release(pipe);
+
+	return EOK;
+}
+
+/** Drop active transfer reference on the pipe.
+ *
+ * @param pipe The USB pipe.
+ */
+void pipe_drop_ref(usb_pipe_t *pipe)
+{
+	pipe_acquire(pipe);
+	assert(pipe->refcount > 0);
+	pipe->refcount--;
+	if (pipe->refcount == 0) {
+		/* We were the last users, let's hang-up. */
+		async_hangup(pipe->hc_phone);
+		pipe->hc_phone = -1;
+	}
+	pipe_release(pipe);
+}
+
+
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipepriv.h
===================================================================
--- uspace/lib/usb/src/pipepriv.h	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
+++ uspace/lib/usb/src/pipepriv.h	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Vojtech Horky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libusb
+ * @{
+ */
+/** @file
+ * Library internal functions on USB pipes.
+ */
+#ifndef LIBUSB_PIPEPRIV_H_
+#define LIBUSB_PIPEPRIV_H_
+
+#include <usb/pipes.h>
+
+void pipe_acquire(usb_pipe_t *);
+void pipe_release(usb_pipe_t *);
+
+int pipe_add_ref(usb_pipe_t *);
+void pipe_drop_ref(usb_pipe_t *);
+
+
+#endif
+/**
+ * @}
+ */
Index: uspace/lib/usb/src/pipes.c
===================================================================
--- uspace/lib/usb/src/pipes.c	(revision d5ac90f0e33c4c353bae229add2cc7d993740ee7)
+++ uspace/lib/usb/src/pipes.c	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -41,4 +41,5 @@
 #include <errno.h>
 #include <assert.h>
+#include "pipepriv.h"
 
 #define IPC_AGAIN_DELAY (1000 * 2) /* 2ms */
@@ -246,18 +247,5 @@
 int usb_pipe_start_session(usb_pipe_t *pipe)
 {
-	assert(pipe);
-
-	if (usb_pipe_is_session_started(pipe)) {
-		return EBUSY;
-	}
-
-	int phone = devman_device_connect(pipe->wire->hc_handle, 0);
-	if (phone < 0) {
-		return phone;
-	}
-
-	pipe->hc_phone = phone;
-
-	return EOK;
+	return pipe_add_ref(pipe);
 }
 
@@ -272,17 +260,5 @@
 int usb_pipe_end_session(usb_pipe_t *pipe)
 {
-	assert(pipe);
-
-	if (!usb_pipe_is_session_started(pipe)) {
-		return ENOENT;
-	}
-
-	int rc = async_hangup(pipe->hc_phone);
-	if (rc != EOK) {
-		return rc;
-	}
-
-	pipe->hc_phone = -1;
-
+	pipe_drop_ref(pipe);
 	return EOK;
 }
@@ -298,5 +274,8 @@
 bool usb_pipe_is_session_started(usb_pipe_t *pipe)
 {
-	return (pipe->hc_phone >= 0);
+	pipe_acquire(pipe);
+	bool started = pipe->refcount > 0;
+	pipe_release(pipe);
+	return started;
 }
 
Index: uspace/lib/usb/src/pipesinit.c
===================================================================
--- uspace/lib/usb/src/pipesinit.c	(revision d5ac90f0e33c4c353bae229add2cc7d993740ee7)
+++ uspace/lib/usb/src/pipesinit.c	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -363,4 +363,5 @@
 	pipe->max_packet_size = max_packet_size;
 	pipe->direction = direction;
+	pipe->refcount = 0;
 
 	return EOK;
Index: uspace/lib/usb/src/pipesio.c
===================================================================
--- uspace/lib/usb/src/pipesio.c	(revision d5ac90f0e33c4c353bae229add2cc7d993740ee7)
+++ uspace/lib/usb/src/pipesio.c	(revision a546687aac830d43eba7e840773f61e4c01e5a31)
@@ -49,24 +49,5 @@
 #include <assert.h>
 #include <usbhc_iface.h>
-
-/** Ensure exclusive access to the IPC phone of given pipe.
- *
- * @param pipe Pipe to be exclusively accessed.
- */
-static void pipe_acquire(usb_pipe_t *pipe)
-{
-	fibril_mutex_lock(&pipe->hc_phone_mutex);
-}
-
-/** Terminate exclusive access to the IPC phone of given pipe.
- *
- * @param pipe Pipe to be released from exclusive usage.
- */
-static void pipe_release(usb_pipe_t *pipe)
-{
-	fibril_mutex_unlock(&pipe->hc_phone_mutex);
-}
-
-
+#include "pipepriv.h"
 
 /** Request an in transfer, no checking of input parameters.
@@ -176,13 +157,9 @@
 
 	if (buffer == NULL) {
-			return EINVAL;
+		return EINVAL;
 	}
 
 	if (size == 0) {
 		return EINVAL;
-	}
-
-	if (!usb_pipe_is_session_started(pipe)) {
-		return EBADF;
 	}
 
@@ -195,8 +172,17 @@
 	}
 
+	int rc;
+	rc = pipe_add_ref(pipe);
+	if (rc != EOK) {
+		return rc;
+	}
+
+
 	size_t act_size = 0;
-	int rc;
 
 	rc = usb_pipe_read_no_checks(pipe, buffer, size, &act_size);
+
+	pipe_drop_ref(pipe);
+
 	if (rc != EOK) {
 		return rc;
@@ -301,8 +287,4 @@
 	}
 
-	if (!usb_pipe_is_session_started(pipe)) {
-		return EBADF;
-	}
-
 	if (pipe->direction != USB_DIRECTION_OUT) {
 		return EBADF;
@@ -313,5 +295,14 @@
 	}
 
-	int rc = usb_pipe_write_no_check(pipe, buffer, size);
+	int rc;
+
+	rc = pipe_add_ref(pipe);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_pipe_write_no_check(pipe, buffer, size);
+
+	pipe_drop_ref(pipe);
 
 	return rc;
@@ -432,8 +423,4 @@
 	}
 
-	if (!usb_pipe_is_session_started(pipe)) {
-		return EBADF;
-	}
-
 	if ((pipe->direction != USB_DIRECTION_BOTH)
 	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
@@ -441,8 +428,17 @@
 	}
 
+	int rc;
+
+	rc = pipe_add_ref(pipe);
+	if (rc != EOK) {
+		return rc;
+	}
+
 	size_t act_size = 0;
-	int rc = usb_pipe_control_read_no_check(pipe,
+	rc = usb_pipe_control_read_no_check(pipe,
 	    setup_buffer, setup_buffer_size,
 	    data_buffer, data_buffer_size, &act_size);
+
+	pipe_drop_ref(pipe);
 
 	if (rc != EOK) {
@@ -556,8 +552,4 @@
 	}
 
-	if (!usb_pipe_is_session_started(pipe)) {
-		return EBADF;
-	}
-
 	if ((pipe->direction != USB_DIRECTION_BOTH)
 	    || (pipe->transfer_type != USB_TRANSFER_CONTROL)) {
@@ -565,6 +557,15 @@
 	}
 
-	int rc = usb_pipe_control_write_no_check(pipe,
+	int rc;
+
+	rc = pipe_add_ref(pipe);
+	if (rc != EOK) {
+		return rc;
+	}
+
+	rc = usb_pipe_control_write_no_check(pipe,
 	    setup_buffer, setup_buffer_size, data_buffer, data_buffer_size);
+
+	pipe_drop_ref(pipe);
 
 	return rc;
