Index: uspace/app/tmon/resolve.c
===================================================================
--- uspace/app/tmon/resolve.c	(revision d37dd3b977a9ab4c34061f2f4d5ce2f92afcebf1)
+++ uspace/app/tmon/resolve.c	(revision d37dd3b977a9ab4c34061f2f4d5ce2f92afcebf1)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 Petr Manek
+ * 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 tmon
+ * @{
+ */
+/**
+ * @file
+ * USB diagnostic device resolving.
+ */
+
+#include <loc.h>
+#include <errno.h>
+#include <str_error.h>
+#include <stdio.h>
+#include <usbdiag_iface.h>
+#include "resolve.h"
+
+#define NAME "tmon"
+
+int tmon_resolve_default(devman_handle_t *fun)
+{
+	category_id_t diag_cat;
+	service_id_t *svcs;
+	size_t count;
+	int rc;
+
+	if ((rc = loc_category_get_id(USBDIAG_CATEGORY, &diag_cat, 0))) {
+		printf(NAME ": Error resolving category '%s'", USBDIAG_CATEGORY);
+		return rc;
+	}
+
+	if ((rc = loc_category_get_svcs(diag_cat, &svcs, &count))) {
+		printf(NAME ": Error getting list of diagnostic devices.\n");
+		return rc;
+	}
+
+	// There must be exactly one diagnostic device for this to work.
+	if (count != 1) {
+		if (count) {
+			printf(NAME ": Found %ld devices. Please specify which to use.\n", count);
+		} else {
+			printf(NAME ": No diagnostic devices found.\n");
+		}
+		return ENOENT;
+	}
+
+	if ((rc = devman_fun_sid_to_handle(svcs[0], fun))) {
+		printf(NAME ": Error resolving handle of device with SID %ld.\n", svcs[0]);
+		return rc;
+	}
+
+	return EOK;
+}
+
+int tmon_resolve_named(const char *dev_path, devman_handle_t *fun)
+{
+	int rc;
+	service_id_t svc;
+	if ((rc = loc_service_get_id(dev_path, &svc, IPC_FLAG_BLOCKING))) {
+		printf(NAME ": Error resolving device. %s\n", str_error(rc));
+		return rc;
+	}
+
+	if ((rc = devman_fun_sid_to_handle(svc, fun))) {
+		printf(NAME ": Error resolving handle of device with SID %ld.\n", svc);
+		return rc;
+	}
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/app/tmon/resolve.h
===================================================================
--- uspace/app/tmon/resolve.h	(revision d37dd3b977a9ab4c34061f2f4d5ce2f92afcebf1)
+++ uspace/app/tmon/resolve.h	(revision d37dd3b977a9ab4c34061f2f4d5ce2f92afcebf1)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Petr Manek
+ * 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 tmon
+ * @{
+ */
+/**
+ * @file USB diagnostic device resolving.
+ */
+
+#ifndef TMON_RESOLVE_H_
+#define TMON_RESOLVE_H_
+
+#include <devman.h>
+
+int tmon_resolve_default(devman_handle_t *);
+int tmon_resolve_named(const char *, devman_handle_t *);
+
+#endif /* TMON_RESOLVE_H_ */
+
+/** @}
+ */
Index: uspace/app/tmon/test.c
===================================================================
--- uspace/app/tmon/test.c	(revision ad2a8b18d9de9c1dd04ef8b3b13b306d5b53ce7a)
+++ uspace/app/tmon/test.c	(revision d37dd3b977a9ab4c34061f2f4d5ce2f92afcebf1)
@@ -48,5 +48,5 @@
 #define DEFAULT_SIZE    65432
 
-static int resolve_and_test(int argc, char *argv[], int (*test)(devman_handle_t, int, size_t)) {
+static int resolve_and_test(int argc, char *argv[], int (*test)(async_exch_t *, int, size_t)) {
 	devman_handle_t fun = -1;
 
@@ -62,5 +62,5 @@
 	}
 
-	int rc;
+	int rc, ec;
 	char path[MAX_PATH_LENGTH];
 	if ((rc = devman_fun_get_path(fun, path, sizeof(path)))) {
@@ -73,73 +73,67 @@
 	// TODO: Read options here.
 
-	return test(fun, DEFAULT_CYCLES, DEFAULT_SIZE);
-}
-
-static int stress_intr_in(devman_handle_t fun, int cycles, size_t size) {
 	async_sess_t *sess = usbdiag_connect(fun);
-	async_exch_t *exch = async_exchange_begin(sess);
-
-	int rc = usbdiag_stress_intr_in(exch, cycles, size);
-	int ec = 0;
-
-	if (rc) {
-		printf(NAME ": %s\n", str_error(rc));
-		ec = 1;
+	if (!sess) {
+		printf(NAME ": Could not connect to the device.\n");
+		return 1;
 	}
 
+	async_exch_t *exch = async_exchange_begin(sess);
+	if (!exch) {
+		printf(NAME ": Could not start exchange with the device.\n");
+		ec = 1;
+		goto err_sess;
+	}
+
+	ec = test(exch, DEFAULT_CYCLES, DEFAULT_SIZE);
 	async_exchange_end(exch);
+
+err_sess:
 	usbdiag_disconnect(sess);
 	return ec;
 }
 
-static int stress_intr_out(devman_handle_t fun, int cycles, size_t size) {
-	async_sess_t *sess = usbdiag_connect(fun);
-	async_exch_t *exch = async_exchange_begin(sess);
-
-	int rc = usbdiag_stress_intr_out(exch, cycles, size);
-	int ec = 0;
-
+static int stress_intr_in(async_exch_t *exch, int cycles, size_t size)
+{
+	int rc = usbdiag_stress_intr_in(exch, cycles, size);
 	if (rc) {
 		printf(NAME ": %s\n", str_error(rc));
-		ec = 1;
+		return 1;
 	}
 
-	async_exchange_end(exch);
-	usbdiag_disconnect(sess);
-	return ec;
+	return 0;
 }
 
-static int stress_bulk_in(devman_handle_t fun, int cycles, size_t size) {
-	async_sess_t *sess = usbdiag_connect(fun);
-	async_exch_t *exch = async_exchange_begin(sess);
-
-	int rc = usbdiag_stress_bulk_in(exch, cycles, size);
-	int ec = 0;
-
+static int stress_intr_out(async_exch_t *exch, int cycles, size_t size)
+{
+	int rc = usbdiag_stress_intr_out(exch, cycles, size);
 	if (rc) {
 		printf(NAME ": %s\n", str_error(rc));
-		ec = 1;
+		return 1;
 	}
 
-	async_exchange_end(exch);
-	usbdiag_disconnect(sess);
-	return ec;
+	return 0;
 }
 
-static int stress_bulk_out(devman_handle_t fun, int cycles, size_t size) {
-	async_sess_t *sess = usbdiag_connect(fun);
-	async_exch_t *exch = async_exchange_begin(sess);
-
-	int rc = usbdiag_stress_bulk_out(exch, cycles, size);
-	int ec = 0;
-
+static int stress_bulk_in(async_exch_t *exch, int cycles, size_t size)
+{
+	int rc = usbdiag_stress_bulk_in(exch, cycles, size);
 	if (rc) {
 		printf(NAME ": %s\n", str_error(rc));
-		ec = 1;
+		return 1;
 	}
 
-	async_exchange_end(exch);
-	usbdiag_disconnect(sess);
-	return ec;
+	return 0;
+}
+
+static int stress_bulk_out(async_exch_t *exch, int cycles, size_t size)
+{
+	int rc = usbdiag_stress_bulk_out(exch, cycles, size);
+	if (rc) {
+		printf(NAME ": %s\n", str_error(rc));
+		return 1;
+	}
+
+	return 0;
 }
 
