Index: uspace/lib/c/generic/loc.c
===================================================================
--- uspace/lib/c/generic/loc.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/lib/c/generic/loc.c	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -45,4 +45,7 @@
 static FIBRIL_MUTEX_INITIALIZE(loc_consumer_mutex);
 
+static FIBRIL_MUTEX_INITIALIZE(loc_callback_mutex);
+static bool loc_callback_created = false;
+
 static async_sess_t *loc_supp_block_sess = NULL;
 static async_sess_t *loc_cons_block_sess = NULL;
@@ -51,4 +54,40 @@
 static async_sess_t *loc_consumer_sess = NULL;
 
+static loc_cat_change_cb_t cat_change_cb = NULL;
+
+static void loc_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	loc_cat_change_cb_t cb_fun;
+	
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+		
+		int retval;
+		
+		switch (IPC_GET_IMETHOD(call)) {
+		case LOC_EVENT_CAT_CHANGE:
+			fibril_mutex_lock(&loc_callback_mutex);
+			cb_fun = cat_change_cb;
+			if (cb_fun != NULL) {
+				(*cb_fun)();
+			}
+			fibril_mutex_unlock(&loc_callback_mutex);
+			retval = 0;
+			break;
+		default:
+			retval = ENOTSUP;
+		}
+		
+		async_answer_0(callid, retval);
+	}
+}
+
+
 static void clone_session(fibril_mutex_t *mtx, async_sess_t *src,
     async_sess_t **dst)
@@ -60,4 +99,38 @@
 	
 	fibril_mutex_unlock(mtx);
+}
+
+static int loc_callback_create(void)
+{
+	async_exch_t *exch;
+	sysarg_t retval;
+	int rc = EOK;
+
+	fibril_mutex_lock(&loc_callback_mutex);
+	
+	if (!loc_callback_created) {
+		exch = loc_exchange_begin_blocking(LOC_PORT_CONSUMER);
+		
+		ipc_call_t answer;
+		aid_t req = async_send_0(exch, LOC_CALLBACK_CREATE, &answer);
+		async_connect_to_me(exch, 0, 0, 0, loc_cb_conn, NULL);
+		loc_exchange_end(exch);
+		
+		async_wait_for(req, &retval);
+		if (rc != EOK)
+			goto done;
+		
+		if (retval != EOK) {
+			rc = retval;
+			goto done;
+		}
+		
+		loc_callback_created = true;
+	}
+	
+	rc = EOK;
+done:
+	fibril_mutex_unlock(&loc_callback_mutex);
+	return rc;
 }
 
@@ -749,2 +822,11 @@
 	    data, count);
 }
+
+int loc_register_cat_change_cb(loc_cat_change_cb_t cb_fun)
+{
+	if (loc_callback_create() != EOK)
+		return EIO;
+
+	cat_change_cb = cb_fun;
+	return EOK;
+}
Index: uspace/lib/c/include/ipc/loc.h
===================================================================
--- uspace/lib/c/include/ipc/loc.h	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/lib/c/include/ipc/loc.h	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -57,4 +57,5 @@
 	LOC_SERVICE_GET_NAME,
 	LOC_NAMESPACE_GET_ID,
+	LOC_CALLBACK_CREATE,
 	LOC_CATEGORY_GET_ID,
 	LOC_CATEGORY_GET_SVCS,
@@ -68,4 +69,8 @@
 	LOC_GET_SERVICES
 } loc_request_t;
+
+typedef enum {
+	LOC_EVENT_CAT_CHANGE = IPC_FIRST_USER_METHOD
+} loc_event_t;
 
 /** Ports provided by location service.
Index: uspace/lib/c/include/loc.h
===================================================================
--- uspace/lib/c/include/loc.h	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/lib/c/include/loc.h	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -40,4 +40,6 @@
 #include <bool.h>
 
+typedef void (*loc_cat_change_cb_t)(void);
+
 extern async_exch_t *loc_exchange_begin_blocking(loc_interface_t);
 extern async_exch_t *loc_exchange_begin(loc_interface_t);
@@ -73,4 +75,5 @@
 extern size_t loc_get_services(service_id_t, loc_sdesc_t **);
 extern int loc_get_categories(category_id_t **, size_t *);
+extern int loc_register_cat_change_cb(loc_cat_change_cb_t);
 
 
