Index: uspace/app/trace/ipcp.c
===================================================================
--- uspace/app/trace/ipcp.c	(revision 8c125ad51a8dfadbf925f3871e4ccdf00e4b81df)
+++ uspace/app/trace/ipcp.c	(revision 164385528bfca082a12eee5e01b23c2c9a74acc5)
@@ -39,4 +39,5 @@
 #include "ipc_desc.h"
 #include "proto.h"
+#include "trace.h"
 #include "ipcp.h"
 
@@ -178,19 +179,45 @@
 	proto_t *proto;
 	unsigned long key[1];
+	oper_t *oper;
 
 	if (have_conn[phone]) proto = connections[phone].proto;
 	else proto = NULL;
 
-//	printf("ipcp_call_out()\n");
-	printf("call id: 0x%x, phone: %d, proto: %s, method: ", hash, phone,
-		(proto ? proto->name : "n/a"));
-	ipc_m_print(proto, IPC_GET_METHOD(*call));
-	printf(" args: (%u, %u, %u, %u, %u)\n",
-	    IPC_GET_ARG1(*call),
-	    IPC_GET_ARG2(*call),
-	    IPC_GET_ARG3(*call),
-	    IPC_GET_ARG4(*call),
-	    IPC_GET_ARG5(*call)
-	);
+	if ((display_mask & DM_IPC) != 0) {
+		printf("Call ID: 0x%x, phone: %d, proto: %s, method: ", hash,
+			phone, (proto ? proto->name : "n/a"));
+		ipc_m_print(proto, IPC_GET_METHOD(*call));
+		printf(" args: (%u, %u, %u, %u, %u)\n",
+		    IPC_GET_ARG1(*call),
+		    IPC_GET_ARG2(*call),
+		    IPC_GET_ARG3(*call),
+		    IPC_GET_ARG4(*call),
+		    IPC_GET_ARG5(*call)
+		);
+	}
+
+
+	if ((display_mask & DM_USER) != 0) {
+
+		if (proto != NULL) {
+			oper = proto_get_oper(proto, IPC_GET_METHOD(*call));
+		} else {
+			oper = NULL;
+		}
+
+		if (oper != NULL) {
+
+			printf("%s(%d).%s", (proto ? proto->name : "n/a"),
+			    phone, (oper ? oper->name : "unknown"));
+
+			printf("(%u, %u, %u, %u, %u)\n",
+			    IPC_GET_ARG1(*call),
+			    IPC_GET_ARG2(*call),
+			    IPC_GET_ARG3(*call),
+			    IPC_GET_ARG4(*call),
+			    IPC_GET_ARG5(*call)
+			);
+		}
+	}
 
 	/* Store call in hash table for response matching */
@@ -206,5 +233,6 @@
 }
 
-static void parse_answer(pending_call_t *pcall, ipc_call_t *answer)
+static void parse_answer(ipc_callid_t hash, pending_call_t *pcall,
+    ipc_call_t *answer)
 {
 	int phone;
@@ -220,6 +248,15 @@
 	method = IPC_GET_METHOD(pcall->question);
 	retval = IPC_GET_RETVAL(*answer);
-	printf("phone=%d, method=%d, retval=%d\n",
-		phone, method, retval);
+
+	if ((display_mask & DM_IPC) != 0) {
+		printf("Response to 0x%x: retval=%d, args = (%u, %u, %u, %u, %u)\n",
+			hash, retval, IPC_GET_ARG1(*answer),
+			IPC_GET_ARG2(*answer), IPC_GET_ARG3(*answer),
+			IPC_GET_ARG4(*answer), IPC_GET_ARG5(*answer));
+	}
+
+	if ((display_mask & DM_USER) != 0) {
+		printf("-> %d\n", retval);
+	}
 
 	if (phone == 0 && method == IPC_M_CONNECT_ME_TO && retval == 0) {
@@ -230,6 +267,8 @@
 
 		cphone = IPC_GET_ARG5(*answer);
-		printf("registering connection (phone %d, protocol: %s)\n", cphone,
-			proto->name);
+		if ((display_mask & DM_SYSTEM) != 0) {
+			printf("Registering connection (phone %d, protocol: %s)\n", cphone,
+		    		proto->name);
+		}
 		ipcp_connection_set(cphone, 0, proto);
 	}
@@ -255,5 +294,7 @@
 	if ((hash & IPC_CALLID_ANSWERED) == 0 && hash != IPCP_CALLID_SYNC) {
 		/* Not a response */
-		printf("Not a response (hash %d)\n", hash);
+		if ((display_mask & DM_IPC) != 0) {
+			printf("Not a response (hash %d)\n", hash);
+		}
 		return;
 	}
@@ -264,11 +305,13 @@
 	item = hash_table_find(&pending_calls, key);
 	if (item == NULL) return; // No matching question found
+
+	/*
+	 * Response matched to question.
+	 */
 	
 	pcall = hash_table_get_instance(item, pending_call_t, link);
-
-	printf("response matched to question\n");
 	hash_table_remove(&pending_calls, key, 1);
 
-	parse_answer(pcall, call);
+	parse_answer(hash, pcall, call);
 	free(pcall);
 }
@@ -282,6 +325,8 @@
 void ipcp_hangup(int phone, int rc)
 {
-	printf("hangup phone %d -> %d\n", phone, rc);
-	ipcp_connection_clear(phone);
+	if ((display_mask & DM_SYSTEM) != 0) {
+		printf("Hang phone %d up -> %d\n", phone, rc);
+		ipcp_connection_clear(phone);
+	}
 }
 
Index: uspace/app/trace/trace.c
===================================================================
--- uspace/app/trace/trace.c	(revision 8c125ad51a8dfadbf925f3871e4ccdf00e4b81df)
+++ uspace/app/trace/trace.c	(revision 164385528bfca082a12eee5e01b23c2c9a74acc5)
@@ -52,4 +52,5 @@
 #include "ipcp.h"
 #include "errors.h"
+#include "trace.h"
 
 #define THBUF_SIZE 64
@@ -68,4 +69,8 @@
 
 static proto_t *proto_console;
+static task_id_t task_id;
+
+/** Combination of events/data to print. */
+display_mask_t display_mask;
 
 static int task_connect(task_id_t task_id)
@@ -287,7 +292,9 @@
 	}
 
-	/* Print syscall name, id and arguments */
-	printf("%s", syscall_desc[sc_id].name);
-	print_sc_args(sc_args, syscall_desc[sc_id].n_args);
+	if ((display_mask & DM_SYSCALL) != 0) {
+		/* Print syscall name and arguments */
+		printf("%s", syscall_desc[sc_id].name);
+		print_sc_args(sc_args, syscall_desc[sc_id].n_args);
+	}
 
 	async_serialize_end();
@@ -313,6 +320,9 @@
 	}
 
-	rv_type = syscall_desc[sc_id].rv_type;
-	print_sc_retval(sc_rc, rv_type);
+	if ((display_mask & DM_SYSCALL) != 0) {
+		/* Print syscall return value */
+		rv_type = syscall_desc[sc_id].rv_type;
+		print_sc_retval(sc_rc, rv_type);
+	}
 
 	switch (sc_id) {
@@ -429,6 +439,4 @@
 	int c;
 
-	printf("Syscall Tracer\n");
-
 	rc = task_connect(task_id);
 	if (rc < 0) {
@@ -533,28 +541,89 @@
 static void print_syntax()
 {
-	printf("Syntax: trace <task_id>\n");
-}
-
-int main(int argc, char *argv[])
-{
-	task_id_t task_id;
+	printf("Syntax: trace [+<events>] <task_id>\n");
+	printf("Events: (default is +tp)\n");
+	printf("\n");
+	printf("\tt ... Thread creation and termination\n");
+	printf("\ts ... System calls\n");
+	printf("\ti ... Low-level IPC\n");
+	printf("\tp ... Protocol level\n");
+	printf("\n");
+	printf("Example: trace +tsip 12\n");
+}
+
+static display_mask_t parse_display_mask(char *text)
+{
+	display_mask_t dm;
+	char *c;
+
+	c = text;
+
+	while (*c) {
+		switch (*c) {
+		case 't': dm = dm | DM_THREAD; break;
+		case 's': dm = dm | DM_SYSCALL; break;
+		case 'i': dm = dm | DM_IPC; break;
+		case 'p': dm = dm | DM_SYSTEM | DM_USER; break;
+		default:
+			printf("Unexpected event type '%c'\n", *c);
+			exit(1);
+		}
+
+		++c;
+	}
+
+	return dm;
+}
+
+static int parse_args(int argc, char *argv[])
+{
+	char *arg;
 	char *err_p;
 
-	if (argc != 2) {
-		printf("Mising argument\n");
+	--argc; ++argv;
+
+	while (argc > 1) {
+		arg = *argv;
+		if (arg[0] == '+') {
+			display_mask = parse_display_mask(&arg[1]);
+		} else {
+			printf("Unexpected argument '%s'\n", arg);
+			print_syntax();
+			return -1;
+		}
+
+		--argc; ++argv;
+	}
+
+	if (argc != 1) {
+		printf("Missing argument\n");
 		print_syntax();
 		return 1;
 	}
 
-	task_id = strtol(argv[1], &err_p, 10);
+	task_id = strtol(*argv, &err_p, 10);
 
 	if (*err_p) {
 		printf("Task ID syntax error\n");
 		print_syntax();
+		return -1;
+	}
+
+	return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	printf("System Call / IPC Tracer\n");
+
+	display_mask = DM_THREAD | DM_SYSTEM | DM_USER;
+
+	if (parse_args(argc, argv) < 0)
 		return 1;
-	}
 
 	main_init();
 	trace_active_task(task_id);
+
+	return 0;
 }
 
Index: uspace/app/trace/trace.h
===================================================================
--- uspace/app/trace/trace.h	(revision 164385528bfca082a12eee5e01b23c2c9a74acc5)
+++ uspace/app/trace/trace.h	(revision 164385528bfca082a12eee5e01b23c2c9a74acc5)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008 Jiri Svoboda
+ * 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 trace
+ * @{
+ */
+/** @file
+ */
+
+#ifndef TRACE_H_
+#define TRACE_H_
+
+/**
+ * Classes of events that can be displayed. Can be or-ed together.
+ */
+typedef enum {
+	
+	DM_THREAD	= 1,	/**< Thread creation and termination events */
+	DM_SYSCALL	= 2,	/**< System calls */
+	DM_IPC		= 4,	/**< Low-level IPC */
+	DM_SYSTEM	= 8,	/**< Sysipc protocol */
+	DM_USER		= 16	/**< User IPC protocols */
+
+} display_mask_t;
+
+/** Combination of events to print. */
+extern display_mask_t display_mask;
+
+#endif
+
+/** @}
+ */
