Index: uspace/app/devctl/devctl.c
===================================================================
--- uspace/app/devctl/devctl.c	(revision 375e501a4e8faac7fad7a1d019a8a778e97346e6)
+++ uspace/app/devctl/devctl.c	(revision 3f57fb73696fea31ef6a619b390a707b4091eda9)
@@ -44,7 +44,9 @@
 #define MAX_NAME_LENGTH 1024
 
+char name[MAX_NAME_LENGTH];
+char drv_name[MAX_NAME_LENGTH];
+
 static int fun_subtree_print(devman_handle_t funh, int lvl)
 {
-	char name[MAX_NAME_LENGTH];
 	devman_handle_t devh;
 	devman_handle_t *cfuns;
@@ -57,13 +59,18 @@
 
 	rc = devman_fun_get_name(funh, name, MAX_NAME_LENGTH);
-	if (rc != EOK) {
-		str_cpy(name, MAX_NAME_LENGTH, "unknown");
-		return ENOMEM;
-	}
+	if (rc != EOK)
+		return ELIMIT;
 
 	if (name[0] == '\0')
 		str_cpy(name, MAX_NAME_LENGTH, "/");
 
-	printf("%s (%" PRIun ")\n", name, funh);
+	rc = devman_fun_get_driver_name(funh, drv_name, MAX_NAME_LENGTH);
+	if (rc != EOK && rc != EINVAL)
+		return ELIMIT;
+
+	if (rc == EINVAL)
+		printf("%s\n", name);
+	else
+		printf("%s : %s\n", name, drv_name);
 
 	rc = devman_fun_get_child(funh, &devh);
Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision 375e501a4e8faac7fad7a1d019a8a778e97346e6)
+++ uspace/lib/c/generic/devman.c	(revision 3f57fb73696fea31ef6a619b390a707b4091eda9)
@@ -430,6 +430,7 @@
 	async_wait_for(req, &retval);
 	
-	if (retval != EOK)
-		return retval;
+	if (retval != EOK) {
+		return retval;
+	}
 	
 	act_size = IPC_GET_ARG2(dreply);
@@ -449,4 +450,10 @@
 {
 	return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
+	    buf_size);
+}
+
+int devman_fun_get_driver_name(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_DRIVER_NAME, handle, buf,
 	    buf_size);
 }
Index: uspace/lib/c/include/devman.h
===================================================================
--- uspace/lib/c/include/devman.h	(revision 375e501a4e8faac7fad7a1d019a8a778e97346e6)
+++ uspace/lib/c/include/devman.h	(revision 3f57fb73696fea31ef6a619b390a707b4091eda9)
@@ -64,4 +64,5 @@
     size_t *);
 extern int devman_fun_get_name(devman_handle_t, char *, size_t);
+extern int devman_fun_get_driver_name(devman_handle_t, char *, size_t);
 extern int devman_fun_get_path(devman_handle_t, char *, size_t);
 extern int devman_fun_online(devman_handle_t);
Index: uspace/lib/c/include/ipc/devman.h
===================================================================
--- uspace/lib/c/include/ipc/devman.h	(revision 375e501a4e8faac7fad7a1d019a8a778e97346e6)
+++ uspace/lib/c/include/ipc/devman.h	(revision 3f57fb73696fea31ef6a619b390a707b4091eda9)
@@ -157,4 +157,5 @@
 	DEVMAN_FUN_GET_CHILD,
 	DEVMAN_FUN_GET_NAME,
+	DEVMAN_FUN_GET_DRIVER_NAME,
 	DEVMAN_FUN_ONLINE,
 	DEVMAN_FUN_OFFLINE,
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 375e501a4e8faac7fad7a1d019a8a778e97346e6)
+++ uspace/srv/devman/main.c	(revision 3f57fb73696fea31ef6a619b390a707b4091eda9)
@@ -855,4 +855,68 @@
 }
 
+/** Get function driver name. */
+static void devman_fun_get_driver_name(ipc_callid_t iid, ipc_call_t *icall)
+{
+	devman_handle_t handle = IPC_GET_ARG1(*icall);
+
+	fun_node_t *fun = find_fun_node(&device_tree, handle);
+	if (fun == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
+	ipc_callid_t data_callid;
+	size_t data_len;
+	if (!async_data_read_receive(&data_callid, &data_len)) {
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		fun_del_ref(fun);
+		return;
+	}
+
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+
+	/* Check function state */
+	if (fun->state == FUN_REMOVED) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		free(buffer);
+
+		async_answer_0(data_callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		fun_del_ref(fun);
+		return;
+	}
+
+	/* Check whether function has a driver */
+	if (fun->child == NULL || fun->child->drv == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		free(buffer);
+
+		async_answer_0(data_callid, EINVAL);
+		async_answer_0(iid, EINVAL);
+		fun_del_ref(fun);
+		return;
+	}
+
+	size_t sent_length = str_size(fun->child->drv->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->child->drv->name,
+	    sent_length);
+	async_answer_0(iid, EOK);
+
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	fun_del_ref(fun);
+	free(buffer);
+}
 
 /** Get device path. */
@@ -1082,4 +1146,7 @@
 		case DEVMAN_FUN_GET_NAME:
 			devman_fun_get_name(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_DRIVER_NAME:
+			devman_fun_get_driver_name(callid, &call);
 			break;
 		case DEVMAN_FUN_GET_PATH:
