Index: uspace/lib/c/generic/devman.c
===================================================================
--- uspace/lib/c/generic/devman.c	(revision d0dd7b558f0c1e5da6887176956a13225dd0f05e)
+++ uspace/lib/c/generic/devman.c	(revision 7beb220448680668678a63d26f84dedb2b14be05)
@@ -1,5 +1,5 @@
 /*
  * Copyright (c) 2007 Josef Cejka
- * Copyright (c) 2009 Jiri Svoboda
+ * Copyright (c) 2011 Jiri Svoboda
  * Copyright (c) 2010 Lenka Trochtova
  * All rights reserved.
@@ -342,5 +342,5 @@
 }
 
-int devman_device_get_handle(const char *pathname, devman_handle_t *handle,
+int devman_fun_get_handle(const char *pathname, devman_handle_t *handle,
     unsigned int flags)
 {
@@ -383,5 +383,132 @@
 }
 
-int devman_get_device_path(devman_handle_t handle, char *path, size_t path_size)
+static int devman_get_str_internal(sysarg_t method, sysarg_t arg1, char *buf,
+    size_t buf_size)
+{
+	async_exch_t *exch;
+	ipc_call_t dreply;
+	size_t act_size;
+	sysarg_t dretval;
+	
+	exch = devman_exchange_begin_blocking(LOC_PORT_CONSUMER);
+	
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	aid_t dreq = async_data_read(exch, buf, buf_size - 1, &dreply);
+	async_wait_for(dreq, &dretval);
+	
+	devman_exchange_end(exch);
+	
+	if (dretval != EOK) {
+		async_wait_for(req, NULL);
+		return dretval;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK)
+		return retval;
+	
+	act_size = IPC_GET_ARG2(dreply);
+	assert(act_size <= buf_size - 1);
+	buf[act_size] = '\0';
+	
+	return EOK;
+}
+
+int devman_fun_get_path(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_PATH, handle, buf,
+	    buf_size);
+}
+
+int devman_fun_get_name(devman_handle_t handle, char *buf, size_t buf_size)
+{
+	return devman_get_str_internal(DEVMAN_FUN_GET_NAME, handle, buf,
+	    buf_size);
+}
+
+static int devman_get_handles_once(sysarg_t method, sysarg_t arg1,
+    devman_handle_t *handle_buf, size_t buf_size, size_t *act_size)
+{
+	async_exch_t *exch = devman_exchange_begin_blocking(DEVMAN_CLIENT);
+
+	ipc_call_t answer;
+	aid_t req = async_send_1(exch, method, arg1, &answer);
+	int rc = async_data_read_start(exch, handle_buf, buf_size);
+	
+	devman_exchange_end(exch);
+	
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+	
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	
+	if (retval != EOK) {
+		return retval;
+	}
+	
+	*act_size = IPC_GET_ARG1(answer);
+	return EOK;
+}
+
+/** Get list of handles.
+ *
+ * Returns an allocated array of handles.
+ *
+ * @param method	IPC method
+ * @param arg1		IPC argument 1
+ * @param data		Place to store pointer to array of handles
+ * @param count		Place to store number of handles
+ * @return 		EOK on success or negative error code
+ */
+static int devman_get_handles_internal(sysarg_t method, sysarg_t arg1,
+    devman_handle_t **data, size_t *count)
+{
+	devman_handle_t *handles;
+	size_t act_size;
+	size_t alloc_size;
+	int rc;
+
+	*data = NULL;
+	act_size = 0;	/* silence warning */
+
+	rc = devman_get_handles_once(method, arg1, NULL, 0,
+	    &act_size);
+	if (rc != EOK)
+		return rc;
+
+	alloc_size = act_size;
+	handles = malloc(alloc_size);
+	if (handles == NULL)
+		return ENOMEM;
+
+	while (true) {
+		rc = devman_get_handles_once(method, arg1, handles, alloc_size,
+		    &act_size);
+		if (rc != EOK)
+			return rc;
+
+		if (act_size <= alloc_size)
+			break;
+
+		alloc_size *= 2;
+		free(handles);
+
+		handles = malloc(alloc_size);
+		if (handles == NULL)
+			return ENOMEM;
+	}
+
+	*count = act_size / sizeof(devman_handle_t);
+	*data = handles;
+	return EOK;
+}
+
+int devman_fun_get_child(devman_handle_t funh, devman_handle_t *devh)
 {
 	async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT);
@@ -389,45 +516,16 @@
 		return ENOMEM;
 	
-	ipc_call_t answer;
-	aid_t req = async_send_1(exch, DEVMAN_DEVICE_GET_DEVICE_PATH,
-	    handle, &answer);
-	
-	ipc_call_t data_request_call;
-	aid_t data_request = async_data_read(exch, path, path_size,
-	    &data_request_call);
-	
-	devman_exchange_end(exch);
-	
-	if (data_request == 0) {
-		async_wait_for(req, NULL);
-		return ENOMEM;
-	}
-	
-	sysarg_t data_request_rc;
-	async_wait_for(data_request, &data_request_rc);
-	
-	sysarg_t opening_request_rc;
-	async_wait_for(req, &opening_request_rc);
-	
-	if (data_request_rc != EOK) {
-		/* Prefer the return code of the opening request. */
-		if (opening_request_rc != EOK)
-			return (int) opening_request_rc;
-		else
-			return (int) data_request_rc;
-	}
-	
-	if (opening_request_rc != EOK)
-		return (int) opening_request_rc;
-	
-	/* To be on the safe-side. */
-	path[path_size - 1] = 0;
-	size_t transferred_size = IPC_GET_ARG2(data_request_call);
-	if (transferred_size >= path_size)
-		return ELIMIT;
-	
-	/* Terminate the string (trailing 0 not send over IPC). */
-	path[transferred_size] = 0;
-	return EOK;
+	sysarg_t retval = async_req_1_1(exch, DEVMAN_FUN_GET_CHILD,
+	    funh, devh);
+	
+	devman_exchange_end(exch);
+	return (int) retval;
+}
+
+int devman_dev_get_functions(devman_handle_t devh, devman_handle_t **funcs,
+    size_t *count)
+{
+	return devman_get_handles_internal(DEVMAN_DEV_GET_FUNCTIONS,
+	    devh, funcs, count);
 }
 
