Index: uspace/app/tester/Makefile
===================================================================
--- uspace/app/tester/Makefile	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/app/tester/Makefile	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -56,6 +56,4 @@
 	mm/malloc3.c \
 	mm/mapping1.c \
-	devs/devman1.c \
-	devs/devman2.c \
 	hw/misc/virtchar1.c \
 	hw/serial/serial1.c \
Index: pace/app/tester/devs/devman1.c
===================================================================
--- uspace/app/tester/devs/devman1.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * Copyright (c) 2011 Vojtech Horky
- * 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 tester
- * @brief Test devman service.
- * @{
- */
-/**
- * @file
- */
-
-#include <inttypes.h>
-#include <errno.h>
-#include <str_error.h>
-#include <sys/types.h>
-#include <async.h>
-#include <devman.h>
-#include <str.h>
-#include <vfs/vfs.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "../tester.h"
-
-#define DEVICE_PATH_NORMAL "/virt/null/a"
-#define DEVICE_CLASS "virt-null"
-#define DEVICE_CLASS_NAME "1"
-#define DEVICE_PATH_CLASSES DEVICE_CLASS "/" DEVICE_CLASS_NAME
-
-const char *test_devman1(void)
-{
-	devman_handle_t handle_primary;
-	devman_handle_t handle_class;
-	
-	int rc;
-	
-	TPRINTF("Asking for handle of `%s'...\n", DEVICE_PATH_NORMAL);
-	rc = devman_device_get_handle(DEVICE_PATH_NORMAL, &handle_primary, 0);
-	if (rc != EOK) {
-		TPRINTF(" ...failed: %s.\n", str_error(rc));
-		if (rc == ENOENT) {
-			TPRINTF("Have you compiled the test drivers?\n");
-		}
-		return "Failed getting device handle";
-	}
-
-	TPRINTF("Asking for handle of `%s' by class..\n", DEVICE_PATH_CLASSES);
-	rc = devman_device_get_handle_by_class(DEVICE_CLASS, DEVICE_CLASS_NAME,
-	    &handle_class, 0);
-	if (rc != EOK) {
-		TPRINTF(" ...failed: %s.\n", str_error(rc));
-		return "Failed getting device class handle";
-	}
-
-	TPRINTF("Received handles %" PRIun " and %" PRIun ".\n",
-	    handle_primary, handle_class);
-	if (handle_primary != handle_class) {
-		return "Retrieved different handles for the same device";
-	}
-
-	return NULL;
-}
-
-/** @}
- */
Index: pace/app/tester/devs/devman1.def
===================================================================
--- uspace/app/tester/devs/devman1.def	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"devman1",
-	"devman test",
-	&test_devman1,
-	false
-},
Index: pace/app/tester/devs/devman2.c
===================================================================
--- uspace/app/tester/devs/devman2.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ 	(revision )
@@ -1,94 +1,0 @@
-/*
- * Copyright (c) 2011 Vojtech Horky
- * 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 tester
- * @brief Test devman service.
- * @{
- */
-/**
- * @file
- */
-
-#include <inttypes.h>
-#include <errno.h>
-#include <str_error.h>
-#include <sys/types.h>
-#include <async.h>
-#include <devman.h>
-#include <str.h>
-#include <async.h>
-#include <vfs/vfs.h>
-#include <vfs/vfs_sess.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "../tester.h"
-
-#define DEVICE_CLASS "test3"
-
-const char *test_devman2(void)
-{
-	size_t idx = 1;
-	int rc = EOK;
-	const char *err_msg = NULL;
-	char *path = NULL;
-	while (rc == EOK) {
-		rc = asprintf(&path, "/loc/class/%s\\%zu", DEVICE_CLASS, idx);
-		if (rc < 0) {
-			continue;
-		}
-		int fd = open(path, O_RDONLY);
-		if (fd < 0) {
-			TPRINTF("Failed opening `%s': %s.\n",
-			    path, str_error(fd));
-			rc = fd;
-			err_msg = "Failed opening file";
-			continue;
-		}
-		async_sess_t *sess = fd_session(EXCHANGE_SERIALIZE, fd);
-		close(fd);
-		if (sess == NULL) {
-			TPRINTF("Failed opening phone: %s.\n", str_error(errno));
-			rc = errno;
-			err_msg = "Failed opening file descriptor phone";
-			continue;
-		}
-		async_hangup(sess);
-		TPRINTF("Path `%s' okay.\n", path);
-		free(path);
-		idx++;
-		rc = EOK;
-	}
-	
-	if (path != NULL)
-		free(path);
-	
-	return err_msg;
-}
-
-/** @}
- */
Index: pace/app/tester/devs/devman2.def
===================================================================
--- uspace/app/tester/devs/devman2.def	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ 	(revision )
@@ -1,6 +1,0 @@
-{
-	"devman2",
-	"devman test",
-	&test_devman2,
-	false
-},
Index: uspace/app/tester/hw/misc/virtchar1.c
===================================================================
--- uspace/app/tester/hw/misc/virtchar1.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/app/tester/hw/misc/virtchar1.c	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -49,5 +49,4 @@
 
 #define DEVICE_PATH_NORMAL "/loc/devices/\\virt\\null\\a"
-#define DEVICE_PATH_CLASSES "/loc/class/virt-null\\1"
 #define BUFFER_SIZE 64
 
@@ -105,9 +104,4 @@
 	}
 
-	res = test_virtchar1_internal(DEVICE_PATH_CLASSES);
-	if (res != NULL) {
-		return res;
-	}
-
 	return NULL;
 }
Index: uspace/app/tester/tester.c
===================================================================
--- uspace/app/tester/tester.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/app/tester/tester.c	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -68,6 +68,4 @@
 #include "hw/misc/virtchar1.def"
 #include "libext2/libext2_1.def"
-#include "devs/devman1.def"
-#include "devs/devman2.def"
 	{NULL, NULL, NULL, false}
 };
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);
 
 
Index: uspace/srv/devman/main.c
===================================================================
--- uspace/srv/devman/main.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/srv/devman/main.c	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -682,4 +682,6 @@
 	
 	if (fun == NULL || fun->dev->drv == NULL) {
+		log_msg(LVL_WARN, "devman_connection_loc(): function "
+		    "not found.\n");
 		async_answer_0(iid, ENOENT);
 		return;
@@ -687,9 +689,4 @@
 	
 	dev = fun->dev;
-	
-	if ((dev->state != DEVICE_USABLE) || (!dev->drv->sess)) {
-		async_answer_0(iid, EINVAL);
-		return;
-	}
 	
 	async_exch_t *exch = async_exchange_begin(dev->drv->sess);
Index: uspace/srv/hid/input/generic/input.c
===================================================================
--- uspace/srv/hid/input/generic/input.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/srv/hid/input/generic/input.c	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -66,7 +66,4 @@
 #include <abi/ipc/methods.h>
 
-/* In microseconds */
-#define DISCOVERY_POLL_INTERVAL  (10 * 1000 * 1000)
-
 #define NUM_LAYOUTS  3
 
@@ -497,14 +494,7 @@
 }
 
-/** Periodically check for new input devices.
- *
- * Looks under /loc/class/keyboard and /loc/class/mouse.
- *
- * @param arg Ignored
- *
- */
-static int dev_discovery_fibril(void *arg)
-{
-	category_id_t keyboard_cat, mouse_cat;
+static int dev_check_new_kbdevs(void)
+{
+	category_id_t keyboard_cat;
 	service_id_t *svcs;
 	size_t count, i;
@@ -518,4 +508,49 @@
 	}
 	
+	/*
+	 * Check for new keyboard devices
+	 */
+	rc = loc_category_get_svcs(keyboard_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf("%s: Failed getting list of keyboard devices.\n",
+		    NAME);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+		
+		/* Determine whether we already know this device. */
+		list_foreach(kbd_devs, kdev_link) {
+			kbd_dev_t *kdev = list_get_instance(kdev_link,
+			    kbd_dev_t, kbd_devs);
+			if (kdev->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+		
+		if (!already_known) {
+			kbd_dev_t *kdev;
+			if (kbd_add_kbdev(svcs[i], &kdev) == EOK) {
+				printf("%s: Connected keyboard device '%s'\n",
+				    NAME, kdev->svc_name);
+			}
+		}
+	}
+	
+	/* XXX Handle device removal */
+	
+	return EOK;
+}
+
+static int dev_check_new_mousedevs(void)
+{
+	category_id_t mouse_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	bool already_known;
+	int rc;
+	
 	rc = loc_category_get_id("mouse", &mouse_cat, IPC_FLAG_BLOCKING);
 	if (rc != EOK) {
@@ -524,90 +559,74 @@
 	}
 	
-	while (true) {
-		async_usleep(DISCOVERY_POLL_INTERVAL);
-		
-		/*
-		 * Check for new keyboard devices
-		 */
-		rc = loc_category_get_svcs(keyboard_cat, &svcs, &count);
-		if (rc != EOK) {
-			printf("%s: Failed getting list of keyboard devices.\n",
-			    NAME);
-			continue;
-		}
-
-		for (i = 0; i < count; i++) {
-			already_known = false;
-			
-			/* Determine whether we already know this device. */
-			list_foreach(kbd_devs, kdev_link) {
-				kbd_dev_t *kdev = list_get_instance(kdev_link,
-				    kbd_dev_t, kbd_devs);
-				if (kdev->svc_id == svcs[i]) {
-					already_known = true;
-					break;
-				}
-			}
-
-			if (!already_known) {
-				kbd_dev_t *kdev;
-				if (kbd_add_kbdev(svcs[i], &kdev) == EOK) {
-					printf("%s: Connected keyboard device '%s'\n",
-					    NAME, kdev->svc_name);
-				}
+	/*
+	 * Check for new mouse devices
+	 */
+	rc = loc_category_get_svcs(mouse_cat, &svcs, &count);
+	if (rc != EOK) {
+		printf("%s: Failed getting list of mouse devices.\n",
+		    NAME);
+		return EIO;
+	}
+	
+	for (i = 0; i < count; i++) {
+		already_known = false;
+		
+		/* Determine whether we already know this device. */
+		list_foreach(mouse_devs, mdev_link) {
+			mouse_dev_t *mdev = list_get_instance(mdev_link,
+			    mouse_dev_t, mouse_devs);
+			if (mdev->svc_id == svcs[i]) {
+				already_known = true;
+				break;
 			}
 		}
 		
-		/* XXX Handle device removal */
-		
-		/*
-		 * Check for new mouse devices
-		 */
-		rc = loc_category_get_svcs(mouse_cat, &svcs, &count);
-		if (rc != EOK) {
-			printf("%s: Failed getting list of mouse devices.\n",
-			    NAME);
-			continue;
-		}
-
-		for (i = 0; i < count; i++) {
-			already_known = false;
-			
-			/* Determine whether we already know this device. */
-			list_foreach(mouse_devs, mdev_link) {
-				mouse_dev_t *mdev = list_get_instance(mdev_link,
-				    mouse_dev_t, mouse_devs);
-				if (mdev->svc_id == svcs[i]) {
-					already_known = true;
-					break;
-				}
-			}
-
-			if (!already_known) {
-				mouse_dev_t *mdev;
-				if (mouse_add_mousedev(svcs[i], &mdev) == EOK) {
-					printf("%s: Connected mouse device '%s'\n",
-					    NAME, mdev->svc_name);
-				}
+		if (!already_known) {
+			mouse_dev_t *mdev;
+			if (mouse_add_mousedev(svcs[i], &mdev) == EOK) {
+				printf("%s: Connected mouse device '%s'\n",
+				    NAME, mdev->svc_name);
 			}
 		}
-		
-		/* XXX Handle device removal */
-	}
+	}
+	
+	/* XXX Handle device removal */
 	
 	return EOK;
 }
 
-/** Start a fibril for discovering new devices. */
-static void input_start_dev_discovery(void)
-{
-	fid_t fid = fibril_create(dev_discovery_fibril, NULL);
-	if (!fid) {
-		printf("%s: Failed to create device discovery fibril.\n",
-		    NAME);
-		return;
-	}
-	
-	fibril_add_ready(fid);
+static int dev_check_new(void)
+{
+	int rc;
+	
+	rc = dev_check_new_kbdevs();
+	if (rc != EOK)
+		return rc;
+	
+	rc = dev_check_new_mousedevs();
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+static void cat_change_cb(void)
+{
+	dev_check_new();
+}
+
+/** Start listening for new devices. */
+static int input_start_dev_discovery(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(cat_change_cb);
+	if (rc != EOK) {
+		printf("%s: Failed registering callback for device discovery. "
+		    "(%d)\n", NAME, rc);
+		return rc;
+	}
+
+	return dev_check_new();
 }
 
Index: uspace/srv/loc/loc.c
===================================================================
--- uspace/srv/loc/loc.c	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/srv/loc/loc.c	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -84,4 +84,7 @@
 /** Service directory ogranized by categories (yellow pages) */
 static categ_dir_t cdir;
+
+static FIBRIL_MUTEX_INITIALIZE(callback_sess_mutex);
+static async_sess_t *callback_sess = NULL;
 
 service_id_t loc_create_id(void)
@@ -728,4 +731,44 @@
  *
  */
+static void loc_callback_create(ipc_callid_t iid, ipc_call_t *icall)
+{
+	async_sess_t *cb_sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (cb_sess == NULL) {
+		async_answer_0(iid, ENOMEM);
+		return;
+	}
+	
+	fibril_mutex_lock(&callback_sess_mutex);
+	if (callback_sess != NULL) {
+		fibril_mutex_unlock(&callback_sess_mutex);
+		async_answer_0(iid, EEXIST);
+		return;
+	}
+	
+	callback_sess = cb_sess;
+	fibril_mutex_unlock(&callback_sess_mutex);
+	
+	async_answer_0(iid, EOK);
+}
+
+void loc_category_change_event(void)
+{
+	fibril_mutex_lock(&callback_sess_mutex);
+
+	if (callback_sess != NULL) {
+		async_exch_t *exch = async_exchange_begin(callback_sess);
+		async_msg_0(exch, LOC_EVENT_CAT_CHANGE);
+		async_exchange_end(exch);
+	}
+
+	fibril_mutex_unlock(&callback_sess_mutex);
+}
+
+/** Find ID for category specified by name.
+ *
+ * On success, answer will contain EOK int retval and service ID in arg1.
+ * On failure, error code will be sent in retval.
+ *
+ */
 static void loc_category_get_id(ipc_callid_t iid, ipc_call_t *icall)
 {
@@ -1129,4 +1172,6 @@
 
 	async_answer_0(iid, retval);
+
+	loc_category_change_event();
 }
 
@@ -1243,4 +1288,7 @@
 		case LOC_NAMESPACE_GET_ID:
 			loc_namespace_get_id(callid, &call);
+			break;
+		case LOC_CALLBACK_CREATE:
+			loc_callback_create(callid, &call);
 			break;
 		case LOC_CATEGORY_GET_ID:
Index: uspace/srv/loc/loc.h
===================================================================
--- uspace/srv/loc/loc.h	(revision 45058baac302e720d9b9a31fb3657f26d57e0f73)
+++ uspace/srv/loc/loc.h	(revision 12f9f0d0827e1f7c54cf26d56ffabf49e22936f7)
@@ -102,4 +102,5 @@
 
 extern service_id_t loc_create_id(void);
+extern void loc_category_change_event(void);
 
 #endif
