Index: uspace/drv/bus/usb/usbdiag/device.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/device.c	(revision a8723748f11aced50ec8c8b3ca56ba447f743ba0)
+++ uspace/drv/bus/usb/usbdiag/device.c	(revision 64d138bec5d6824306e69dd9350f6058fb4a56a0)
@@ -36,4 +36,5 @@
 #include <errno.h>
 #include <usb/debug.h>
+#include <usb/diag/iface.h>
 
 #include "device.h"
@@ -41,8 +42,35 @@
 #define NAME "usbdiag"
 
+static void connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	// usb_diag_fun_t *fun = (usb_diag_fun_t *) ddf_fun_data_get((ddf_fun_t *) arg);
+
+	// FIXME: handle connection
+}
+
+static int some_test(ddf_fun_t *fun, int x, int *y)
+{
+	*y = x + 42;
+	return EOK;
+}
+
+static usb_diag_iface_t diag_interface = {
+	.test = some_test,
+};
+
+static ddf_dev_ops_t diag_ops = {
+	.interfaces[USBDIAG_DEV_IFACE] = &diag_interface
+};
+
 static int device_init(usb_diag_dev_t *dev)
 {
-	// TODO: allocate data structures, set up stuffs
+	ddf_fun_t *fun = usb_device_ddf_fun_create(dev->usb_dev, fun_exposed, "tmon");
+	if (!fun)
+		return ENOMEM;
 
+	ddf_fun_set_conn_handler(fun, connection);
+	ddf_fun_set_ops(fun, &diag_ops);
+
+	dev->fun = fun;
 	return EOK;
 }
@@ -50,5 +78,5 @@
 static void device_fini(usb_diag_dev_t *dev)
 {
-	// TODO: tear down data structures
+	ddf_fun_destroy(dev->fun);
 }
 
Index: uspace/drv/bus/usb/usbdiag/device.h
===================================================================
--- uspace/drv/bus/usb/usbdiag/device.h	(revision a8723748f11aced50ec8c8b3ca56ba447f743ba0)
+++ uspace/drv/bus/usb/usbdiag/device.h	(revision 64d138bec5d6824306e69dd9350f6058fb4a56a0)
@@ -40,8 +40,9 @@
 
 /**
- * USB debug device.
+ * USB diagnostic device.
  */
 typedef struct usb_diag_dev {
 	usb_device_t *usb_dev;
+	ddf_fun_t *fun;
 } usb_diag_dev_t;
 
Index: uspace/drv/bus/usb/usbdiag/main.c
===================================================================
--- uspace/drv/bus/usb/usbdiag/main.c	(revision a8723748f11aced50ec8c8b3ca56ba447f743ba0)
+++ uspace/drv/bus/usb/usbdiag/main.c	(revision 64d138bec5d6824306e69dd9350f6058fb4a56a0)
@@ -38,4 +38,5 @@
 #include <usb/dev/driver.h>
 #include <usb/diag/diag.h>
+#include <str_error.h>
 
 #include "usbdiag.h"
@@ -44,29 +45,39 @@
 #define NAME "usbdiag"
 
-static void usb_diag_test_impl(ipc_callid_t rid, ipc_call_t *request)
-{
-	int x = IPC_GET_ARG1(*request);
-	int ret = 4200 + x;
-	async_answer_0(rid, ret);
-}
-
 static int device_add(usb_device_t *dev)
 {
+	int rc;
 	usb_log_info("Adding device '%s'", usb_device_get_name(dev));
 
-	int err;
+	usb_diag_dev_t *diag_dev;
+	if ((rc = usb_diag_dev_create(dev, &diag_dev))) {
+		usb_log_error("Failed create device: %s.\n", str_error(rc));
+		goto err;
+	}
 
-	usb_diag_dev_t *diag_dev;
-	if ((err = usb_diag_dev_create(dev, &diag_dev)))
-		return err;
+	if ((rc = ddf_fun_bind(diag_dev->fun))) {
+		usb_log_error("Failed to bind DDF function: %s.\n", str_error(rc));
+		goto err_create;
+	}
 
-	/* TODO: Register device in some list. */
-	/* TODO: Register device DDF function. */
+	if ((rc = ddf_fun_add_to_category(diag_dev->fun, USB_DIAG_CATEGORY))) {
+		usb_log_error("Failed add DDF to category '"
+		    USB_DIAG_CATEGORY "': %s.\n", str_error(rc));
+		goto err_bind;
+	}
 
 	return EOK;
+
+err_bind:
+	ddf_fun_unbind(diag_dev->fun);
+err_create:
+	usb_diag_dev_destroy(diag_dev);
+err:
+	return rc;
 }
 
 static int device_remove(usb_device_t *dev)
 {
+	int rc;
 	usb_log_info("Removing device '%s'", usb_device_get_name(dev));
 
@@ -74,10 +85,16 @@
 
 	/* TODO: Make sure nothing is going on with the device. */
-	/* TODO: Unregister device DDF function. */
-	/* TODO: Remove device from list */
+
+	if ((rc = ddf_fun_unbind(diag_dev->fun))) {
+		usb_log_error("Failed to unbind DDF function: %s\n", str_error(rc));
+		goto err;
+	}
 
 	usb_diag_dev_destroy(diag_dev);
 
 	return EOK;
+
+err:
+	return rc;
 }
 
@@ -107,41 +124,4 @@
 }
 
-static void connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	bool cont = true;
-
-	async_answer_0(iid, EOK);
-
-	while (cont) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case USB_DIAG_IN_TEST:
-			usb_diag_test_impl(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
-static int server_fibril(void *arg)
-{
-	// async_set_client_data_constructor(NULL);
-	// async_set_client_data_destructor(NULL);
-	async_set_fallback_port_handler(connection, NULL);
-	// async_event_task_subscribe();
-	// service_register();
-	async_manager();
-
-	/* Never reached. */
-	return EOK;
-}
-
 /** USB diagnostic driver ops. */
 static const usb_driver_ops_t diag_driver_ops = {
@@ -166,10 +146,4 @@
 	log_init(NAME);
 
-	/* Start usbdiag service. */
-	fid_t srv = fibril_create(server_fibril, NULL);
-	if (!srv)
-		return ENOMEM;
-	fibril_add_ready(srv);
-
 	return usb_driver_main(&diag_driver);
 }
