Index: uspace/drv/test/test2/test2.c
===================================================================
--- uspace/drv/test/test2/test2.c	(revision 1dc4a5e441cc195a33bd958ea4994dcd59141df0)
+++ uspace/drv/test/test2/test2.c	(revision b29bb098aa093f6015e148a9c216b7fcd225b8d6)
@@ -41,7 +41,13 @@
 
 static int test2_add_device(ddf_dev_t *dev);
+static int test2_dev_remove(ddf_dev_t *dev);
+static int test2_fun_online(ddf_fun_t *fun);
+static int test2_fun_offline(ddf_fun_t *fun);
 
 static driver_ops_t driver_ops = {
-	.add_device = &test2_add_device
+	.add_device = &test2_add_device,
+	.dev_remove = &test2_dev_remove,
+	.fun_online = &test2_fun_online,
+	.fun_offline = &test2_fun_offline
 };
 
@@ -50,4 +56,14 @@
 	.driver_ops = &driver_ops
 };
+
+/* Device soft state */
+typedef struct {
+	ddf_dev_t *dev;
+
+	ddf_fun_t *fun_a;
+	ddf_fun_t *fun_err;
+	ddf_fun_t *child;
+	ddf_fun_t *test1;
+} test2_t;
 
 /** Register child and inform user about it.
@@ -60,5 +76,5 @@
  */
 static int register_fun_verbose(ddf_dev_t *parent, const char *message,
-    const char *name, const char *match_id, int match_score)
+    const char *name, const char *match_id, int match_score, ddf_fun_t **pfun)
 {
 	ddf_fun_t *fun;
@@ -89,4 +105,6 @@
 	}
 
+	*pfun = fun;
+
 	ddf_msg(LVL_NOTE, "Registered child device `%s'", name);
 	return EOK;
@@ -100,5 +118,5 @@
 static int postponed_birth(void *arg)
 {
-	ddf_dev_t *dev = (ddf_dev_t *) arg;
+	test2_t *test2 = (test2_t *) arg;
 	ddf_fun_t *fun_a;
 	int rc;
@@ -106,10 +124,10 @@
 	async_usleep(1000);
 
-	(void) register_fun_verbose(dev, "child driven by the same task",
-	    "child", "virtual&test2", 10);
-	(void) register_fun_verbose(dev, "child driven by test1",
-	    "test1", "virtual&test1", 10);
-
-	fun_a = ddf_fun_create(dev, fun_exposed, "a");
+	(void) register_fun_verbose(test2->dev, "child driven by the same task",
+	    "child", "virtual&test2", 10, &test2->child);
+	(void) register_fun_verbose(test2->dev, "child driven by test1",
+	    "test1", "virtual&test1", 10, &test2->test1);
+
+	fun_a = ddf_fun_create(test2->dev, fun_exposed, "a");
 	if (fun_a == NULL) {
 		ddf_msg(LVL_ERROR, "Failed creating function 'a'.");
@@ -124,5 +142,27 @@
 
 	ddf_fun_add_to_category(fun_a, "virtual");
-
+	test2->fun_a = fun_a;
+
+	return EOK;
+}
+
+static int fun_remove(ddf_fun_t *fun, const char *name)
+{
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')\n", fun, name);
+	rc = ddf_fun_offline(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name);
+		return rc;
+	}
+
+	rc = ddf_fun_unbind(fun);
+	if (rc != EOK) {
+		ddf_msg(LVL_ERROR, "Failed unbinding function '%s'.", name);
+		return rc;
+	}
+
+	ddf_fun_destroy(fun);
 	return EOK;
 }
@@ -130,9 +170,19 @@
 static int test2_add_device(ddf_dev_t *dev)
 {
+	test2_t *test2;
+
 	ddf_msg(LVL_DEBUG, "test2_add_device(name=\"%s\", handle=%d)",
 	    dev->name, (int) dev->handle);
 
+	test2 = ddf_dev_data_alloc(dev, sizeof(test2_t));
+	if (test2 == NULL) {
+		ddf_msg(LVL_ERROR, "Failed allocating soft state.");
+		return ENOMEM;
+	}
+
+	test2->dev = dev;
+
 	if (str_cmp(dev->name, "child") != 0) {
-		fid_t postpone = fibril_create(postponed_birth, dev);
+		fid_t postpone = fibril_create(postponed_birth, test2);
 		if (postpone == 0) {
 			ddf_msg(LVL_ERROR, "fibril_create() failed.");
@@ -142,8 +192,55 @@
 	} else {
 		(void) register_fun_verbose(dev, "child without available driver",
-		    "ERROR", "non-existent.match.id", 10);
-	}
-
-	return EOK;
+		    "ERROR", "non-existent.match.id", 10, &test2->fun_err);
+	}
+
+	return EOK;
+}
+
+static int test2_dev_remove(ddf_dev_t *dev)
+{
+	test2_t *test2 = (test2_t *)dev->driver_data;
+	int rc;
+
+	ddf_msg(LVL_DEBUG, "test2_dev_remove(%p)", dev);
+
+	if (test2->fun_a != NULL) {
+		rc = fun_remove(test2->fun_a, "a");
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (test2->fun_err != NULL) {
+		rc = fun_remove(test2->fun_err, "ERROR");
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (test2->child != NULL) {
+		rc = fun_remove(test2->child, "child");
+		if (rc != EOK)
+			return rc;
+	}
+
+	if (test2->test1 != NULL) {
+		rc = fun_remove(test2->test1, "test1");
+		if (rc != EOK)
+			return rc;
+	}
+
+	return EOK;
+}
+
+
+static int test2_fun_online(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "test2_fun_online()");
+	return ddf_fun_online(fun);
+}
+
+static int test2_fun_offline(ddf_fun_t *fun)
+{
+	ddf_msg(LVL_DEBUG, "test2_fun_offline()");
+	return ddf_fun_offline(fun);
 }
 
