Index: uspace/srv/devman/devman.c
===================================================================
--- uspace/srv/devman/devman.c	(revision 42a619b240617c4f0e4dd04ddf2366f3c5a0709a)
+++ uspace/srv/devman/devman.c	(revision 7beb220448680668678a63d26f84dedb2b14be05)
@@ -920,4 +920,35 @@
 }
 
+/** Get list of device functions. */
+int dev_get_functions(dev_tree_t *tree, dev_node_t *dev,
+    devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size)
+{
+	size_t act_cnt;
+	size_t buf_cnt;
+
+	assert(fibril_rwlock_is_locked(&tree->rwlock));
+
+	buf_cnt = buf_size / sizeof(devman_handle_t);
+
+	act_cnt = list_count(&dev->functions);
+	*act_size = act_cnt * sizeof(devman_handle_t);
+
+	if (buf_size % sizeof(devman_handle_t) != 0)
+		return EINVAL;
+
+	size_t pos = 0;
+	list_foreach(dev->functions, item) {
+		fun_node_t *fun =
+		    list_get_instance(item, fun_node_t, dev_functions);
+
+		if (pos < buf_cnt)
+			hdl_buf[pos] = fun->handle;
+		pos++;
+	}
+
+	return EOK;
+}
+
+
 /* Function nodes */
 
@@ -1145,5 +1176,5 @@
 	char *rel_path = path;
 	char *next_path_elem = NULL;
-	bool cont = true;
+	bool cont = (rel_path[1] != '\0');
 	
 	while (cont && fun != NULL) {
Index: uspace/srv/devman/devman.h
===================================================================
--- uspace/srv/devman/devman.h	(revision 42a619b240617c4f0e4dd04ddf2366f3c5a0709a)
+++ uspace/srv/devman/devman.h	(revision 7beb220448680668678a63d26f84dedb2b14be05)
@@ -253,4 +253,6 @@
 extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle);
 extern dev_node_t *find_dev_function(dev_node_t *, const char *);
+extern int dev_get_functions(dev_tree_t *tree, dev_node_t *, devman_handle_t *,
+    size_t, size_t *);
 
 extern fun_node_t *create_fun_node(void);
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 42a619b240617c4f0e4dd04ddf2366f3c5a0709a)
+++ uspace/srv/devman/main.c	(revision 7beb220448680668678a63d26f84dedb2b14be05)
@@ -497,7 +497,6 @@
 }
 
-/** Find device path by its handle. */
-static void devman_get_device_path_by_handle(ipc_callid_t iid,
-    ipc_call_t *icall)
+/** Get device name. */
+static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall)
 {
 	devman_handle_t handle = IPC_GET_ARG1(*icall);
@@ -523,4 +522,41 @@
 	}
 
+	size_t sent_length = str_size(fun->name);
+	if (sent_length > data_len) {
+		sent_length = data_len;
+	}
+
+	async_data_read_finalize(data_callid, fun->name, sent_length);
+	async_answer_0(iid, EOK);
+
+	free(buffer);
+}
+
+
+/** Get device path. */
+static void devman_fun_get_path(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);
+		return;
+	}
+
+	void *buffer = malloc(data_len);
+	if (buffer == NULL) {
+		async_answer_0(data_callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+
 	size_t sent_length = str_size(fun->pathname);
 	if (sent_length > data_len) {
@@ -532,4 +568,78 @@
 
 	free(buffer);
+}
+
+static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall)
+{
+	ipc_callid_t callid;
+	size_t size;
+	size_t act_size;
+	int rc;
+	
+	if (!async_data_read_receive(&callid, &size)) {
+		async_answer_0(callid, EREFUSED);
+		async_answer_0(iid, EREFUSED);
+		return;
+	}
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	dev_node_t *dev = find_dev_node_no_lock(&device_tree,
+	    IPC_GET_ARG1(*icall));
+	if (dev == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOENT);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size);
+	if (hdl_buf == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, ENOMEM);
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size);
+	if (rc != EOK) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(callid, rc);
+		async_answer_0(iid, rc);
+		return;
+	}
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
+	
+	sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size);
+	free(hdl_buf);
+	
+	async_answer_1(iid, retval, act_size);
+}
+
+
+/** Get handle for child device of a function. */
+static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall)
+{
+	fun_node_t *fun;
+	
+	fibril_rwlock_read_lock(&device_tree.rwlock);
+	
+	fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
+	if (fun == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	if (fun->child == NULL) {
+		fibril_rwlock_read_unlock(&device_tree.rwlock);
+		async_answer_0(iid, ENOENT);
+		return;
+	}
+	
+	async_answer_1(iid, EOK, fun->child->handle);
+	
+	fibril_rwlock_read_unlock(&device_tree.rwlock);
 }
 
@@ -566,6 +676,15 @@
 			devman_function_get_handle(callid, &call);
 			break;
-		case DEVMAN_DEVICE_GET_DEVICE_PATH:
-			devman_get_device_path_by_handle(callid, &call);
+		case DEVMAN_DEV_GET_FUNCTIONS:
+			devman_dev_get_functions(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_CHILD:
+			devman_fun_get_child(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_NAME:
+			devman_fun_get_name(callid, &call);
+			break;
+		case DEVMAN_FUN_GET_PATH:
+			devman_fun_get_path(callid, &call);
 			break;
 		case DEVMAN_FUN_SID_TO_HANDLE:
