Diff between c7c092bca3f13348f2f92e72999ee585f98e7974 and 813b674bce1aab009e7f2d14d1825f603330563d

Changed Files

File Additions Deletions Status
attrib/client.c +1 -0 modified
audio/avctp.c +1 -0 modified
audio/avdtp.c +1 -0 modified
audio/avrcp.c +1 -0 modified
audio/control.c +5 -7 modified
audio/control.h +2 -2 modified
audio/device.c +1 -0 modified
audio/gateway.h +1 -1 modified
audio/headset.c +21 -60 modified
audio/headset.h +4 -4 modified
audio/manager.c +129 -154 modified
audio/manager.h +0 -2 modified
audio/sink.c +1 -0 modified
audio/source.c +1 -0 modified
plugins/adaptername.c +1 -0 modified
plugins/dbusoob.c +2 -0 modified
plugins/wiimote.c +2 -0 modified
profiles/deviceinfo/deviceinfo.c +2 -0 modified
profiles/deviceinfo/manager.c +8 -7 modified
profiles/gatt/gas.c +2 -0 modified
profiles/gatt/manager.c +8 -7 modified
profiles/health/hdp.c +1 -0 modified
profiles/health/hdp_manager.c +15 -15 modified
profiles/health/hdp_util.c +1 -0 modified
profiles/input/device.c +1 -0 modified
profiles/input/fakehid.c +1 -0 modified
profiles/input/hog_device.c +1 -0 modified
profiles/input/hog_manager.c +8 -7 modified
profiles/input/manager.c +19 -24 modified
profiles/network/connection.c +4 -10 modified
profiles/network/connection.h +1 -1 modified
profiles/network/manager.c +22 -69 modified
profiles/proximity/immalert.c +2 -0 modified
profiles/proximity/linkloss.c +2 -0 modified
profiles/proximity/manager.c +17 -26 modified
profiles/proximity/monitor.c +1 -0 modified
profiles/proximity/reporter.c +6 -15 modified
profiles/proximity/reporter.h +3 -0 modified
profiles/sap/manager.c +9 -6 modified
profiles/thermometer/manager.c +8 -7 modified
profiles/thermometer/thermometer.c +4 -1 modified
profiles/time/manager.c +10 -7 modified
src/adapter.c +41 -9 modified
src/agent.c +1 -0 modified
src/attrib-server.c +1 -0 modified
src/device.c +108 -82 modified
src/device.h +33 -13 modified
src/event.c +1 -0 modified
src/mgmt.c +1 -0 modified

Full Patch

diff --git a/attrib/client.c b/attrib/client.c
index bb6adf8..906d345 100644
--- a/attrib/client.c
+++ b/attrib/client.c
@@ -29,6 +29,7 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <glib.h>
 
 #include <bluetooth/bluetooth.h>
diff --git a/audio/avctp.c b/audio/avctp.c
index 2970986..03f3e7f 100644
--- a/audio/avctp.c
+++ b/audio/avctp.c
@@ -29,6 +29,7 @@
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <unistd.h>
 #include <assert.h>
diff --git a/audio/avdtp.c b/audio/avdtp.c
index eafafc0..d44c504 100644
--- a/audio/avdtp.c
+++ b/audio/avdtp.c
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <unistd.h>
 #include <assert.h>
diff --git a/audio/avrcp.c b/audio/avrcp.c
index d925365..0688ffa 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -29,6 +29,7 @@
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <unistd.h>
 #include <assert.h>
diff --git a/audio/control.c b/audio/control.c
index 187f838..5477c2d 100644
--- a/audio/control.c
+++ b/audio/control.c
@@ -40,6 +40,7 @@
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sdp.h>
 #include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -58,9 +59,7 @@
 static unsigned int avctp_id = 0;
 
 struct control {
-	struct audio_device *dev;
 	struct avctp *session;
-
 	gboolean target;
 };
 
@@ -238,13 +237,13 @@ void control_unregister(struct audio_device *dev)
 						AUDIO_CONTROL_INTERFACE);
 }
 
-void control_update(struct control *control, uint16_t uuid16)
+void control_update(struct control *control, GSList *uuids)
 {
-	if (uuid16 == AV_REMOTE_TARGET_SVCLASS_ID)
+	if (g_slist_find_custom(uuids, AVRCP_TARGET_UUID, bt_uuid_strcmp))
 		control->target = TRUE;
 }
 
-struct control *control_init(struct audio_device *dev, uint16_t uuid16)
+struct control *control_init(struct audio_device *dev, GSList *uuids)
 {
 	struct control *control;
 
@@ -258,9 +257,8 @@ struct control *control_init(struct audio_device *dev, uint16_t uuid16)
 		AUDIO_CONTROL_INTERFACE, dev->path);
 
 	control = g_new0(struct control, 1);
-	control->dev = dev;
 
-	control_update(control, uuid16);
+	control_update(control, uuids);
 
 	if (!avctp_id)
 		avctp_id = avctp_add_state_cb(state_changed, NULL);
diff --git a/audio/control.h b/audio/control.h
index 2219e5f..5f4f728 100644
--- a/audio/control.h
+++ b/audio/control.h
@@ -24,7 +24,7 @@
 
 #define AUDIO_CONTROL_INTERFACE "org.bluez.Control"
 
-struct control *control_init(struct audio_device *dev, uint16_t uuid16);
-void control_update(struct control *control, uint16_t uuid16);
+struct control *control_init(struct audio_device *dev, GSList *uuids);
+void control_update(struct control *control, GSList *uuids);
 void control_unregister(struct audio_device *dev);
 gboolean control_is_active(struct audio_device *dev);
diff --git a/audio/device.c b/audio/device.c
index 9507eac..4952b57 100644
--- a/audio/device.c
+++ b/audio/device.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <unistd.h>
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <netinet/in.h>
diff --git a/audio/gateway.h b/audio/gateway.h
index 77f5787..6fde445 100644
--- a/audio/gateway.h
+++ b/audio/gateway.h
@@ -56,7 +56,7 @@ typedef void (*gateway_stream_cb_t) (struct audio_device *dev, GError *err,
 
 void gateway_set_state(struct audio_device *dev, gateway_state_t new_state);
 void gateway_unregister(struct audio_device *dev);
-struct gateway *gateway_init(struct audio_device *device);
+struct gateway *gateway_init(struct audio_device *dev);
 gboolean gateway_is_active(struct audio_device *dev);
 gboolean gateway_is_connected(struct audio_device *dev);
 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io);
diff --git a/audio/headset.c b/audio/headset.c
index 0ddd134..1ef6c49 100644
--- a/audio/headset.c
+++ b/audio/headset.c
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <signal.h>
 #include <string.h>
 #include <getopt.h>
@@ -42,6 +43,7 @@
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sdp.h>
 #include <bluetooth/sdp_lib.h>
+#include <bluetooth/uuid.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -1956,45 +1958,23 @@ static const GDBusSignalTable headset_signals[] = {
 	{ }
 };
 
-void headset_update(struct audio_device *dev, uint16_t svc,
-			const char *uuidstr)
+void headset_update(struct audio_device *dev, struct headset *headset,
+								GSList *uuids)
 {
-	struct headset *headset = dev->headset;
 	const sdp_record_t *record;
 
-	record = btd_device_get_record(dev->btd_dev, uuidstr);
-	if (!record)
-		return;
-
-	switch (svc) {
-	case HANDSFREE_SVCLASS_ID:
-		if (headset->hfp_handle &&
-				(headset->hfp_handle != record->handle)) {
-			error("More than one HFP record found on device");
-			return;
-		}
-
-		headset->hfp_handle = record->handle;
-		break;
-
-	case HEADSET_SVCLASS_ID:
-		if (headset->hsp_handle &&
-				(headset->hsp_handle != record->handle)) {
-			error("More than one HSP record found on device");
-			return;
-		}
-
-		headset->hsp_handle = record->handle;
-
-		/* Ignore this record if we already have access to HFP */
-		if (headset->hfp_handle)
-			return;
-
-		break;
+	if (g_slist_find_custom(uuids, HFP_HS_UUID, bt_uuid_strcmp) &&
+						headset->hfp_handle == 0) {
+		record = btd_device_get_record(dev->btd_dev, HFP_HS_UUID);
+		if (record)
+			headset->hfp_handle = record->handle;
+	}
 
-	default:
-		DBG("Invalid record passed to headset_update");
-		return;
+	if (g_slist_find_custom(uuids, HSP_HS_UUID, bt_uuid_strcmp) &&
+						headset->hsp_handle == 0) {
+		record = btd_device_get_record(dev->btd_dev, HSP_HS_UUID);
+		if (record)
+			headset->hsp_handle = record->handle;
 	}
 }
 
@@ -2057,36 +2037,17 @@ void headset_unregister(struct audio_device *dev)
 		AUDIO_HEADSET_INTERFACE);
 }
 
-struct headset *headset_init(struct audio_device *dev, uint16_t svc,
-				const char *uuidstr)
+struct headset *headset_init(struct audio_device *dev, GSList *uuids,
+							gboolean hfp_enabled)
 {
 	struct headset *hs;
-	const sdp_record_t *record;
 
 	hs = g_new0(struct headset, 1);
 	hs->rfcomm_ch = -1;
-	hs->search_hfp = server_is_enabled(&dev->src, HANDSFREE_SVCLASS_ID);
-
-	record = btd_device_get_record(dev->btd_dev, uuidstr);
-	if (!record)
-		goto register_iface;
+	hs->search_hfp = hfp_enabled;
 
-	switch (svc) {
-	case HANDSFREE_SVCLASS_ID:
-		hs->hfp_handle = record->handle;
-		break;
-
-	case HEADSET_SVCLASS_ID:
-		hs->hsp_handle = record->handle;
-		break;
+	headset_update(dev, hs, uuids);
 
-	default:
-		DBG("Invalid record passed to headset_init");
-		g_free(hs);
-		return NULL;
-	}
-
-register_iface:
 	if (!g_dbus_register_interface(dev->conn, dev->path,
 					AUDIO_HEADSET_INTERFACE,
 					headset_methods, headset_signals, NULL,
@@ -2095,8 +2056,8 @@ register_iface:
 		return NULL;
 	}
 
-	DBG("Registered interface %s on path %s",
-		AUDIO_HEADSET_INTERFACE, dev->path);
+	DBG("Registered interface %s on path %s", AUDIO_HEADSET_INTERFACE,
+								dev->path);
 
 	return hs;
 }
diff --git a/audio/headset.h b/audio/headset.h
index 465c2d6..736e4fe 100644
--- a/audio/headset.h
+++ b/audio/headset.h
@@ -57,15 +57,15 @@ void headset_connect_cb(GIOChannel *chan, GError *err, gpointer user_data);
 
 GIOChannel *headset_get_rfcomm(struct audio_device *dev);
 
-struct headset *headset_init(struct audio_device *dev, uint16_t svc,
-				const char *uuidstr);
+struct headset *headset_init(struct audio_device *dev, GSList *uuids,
+							gboolean hfp_enabled);
 
 void headset_unregister(struct audio_device *dev);
 
 uint32_t headset_config_init(GKeyFile *config);
 
-void headset_update(struct audio_device *dev, uint16_t svc,
-			const char *uuidstr);
+void headset_update(struct audio_device *dev, struct headset *headset,
+								GSList *uuids);
 
 unsigned int headset_config_stream(struct audio_device *dev,
 					gboolean auto_dc,
diff --git a/audio/manager.c b/audio/manager.c
index 7406a1f..5b34f9b 100644
--- a/audio/manager.c
+++ b/audio/manager.c
@@ -33,6 +33,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <dirent.h>
 #include <ctype.h>
@@ -128,104 +129,6 @@ static struct audio_adapter *find_adapter(GSList *list,
 	return NULL;
 }
 
-gboolean server_is_enabled(bdaddr_t *src, uint16_t svc)
-{
-	switch (svc) {
-	case HEADSET_SVCLASS_ID:
-		return enabled.headset;
-	case HEADSET_AGW_SVCLASS_ID:
-		return FALSE;
-	case HANDSFREE_SVCLASS_ID:
-		return enabled.headset && enabled.hfp;
-	case HANDSFREE_AGW_SVCLASS_ID:
-		return enabled.gateway;
-	case AUDIO_SINK_SVCLASS_ID:
-		return enabled.sink;
-	case AUDIO_SOURCE_SVCLASS_ID:
-		return enabled.source;
-	case AV_REMOTE_TARGET_SVCLASS_ID:
-	case AV_REMOTE_SVCLASS_ID:
-		return enabled.control;
-	default:
-		return FALSE;
-	}
-}
-
-static void handle_uuid(const char *uuidstr, struct audio_device *device)
-{
-	uuid_t uuid;
-	uint16_t uuid16;
-
-	if (bt_string2uuid(&uuid, uuidstr) < 0) {
-		error("%s not detected as an UUID-128", uuidstr);
-		return;
-	}
-
-	if (!sdp_uuid128_to_uuid(&uuid) && uuid.type != SDP_UUID16) {
-		error("Could not convert %s to a UUID-16", uuidstr);
-		return;
-	}
-
-	uuid16 = uuid.value.uuid16;
-
-	if (!server_is_enabled(&device->src, uuid16)) {
-		DBG("server not enabled for %s (0x%04x)", uuidstr, uuid16);
-		return;
-	}
-
-	switch (uuid16) {
-	case HEADSET_SVCLASS_ID:
-		DBG("Found Headset record");
-		if (device->headset)
-			headset_update(device, uuid16, uuidstr);
-		else
-			device->headset = headset_init(device, uuid16,
-							uuidstr);
-		break;
-	case HEADSET_AGW_SVCLASS_ID:
-		DBG("Found Headset AG record");
-		break;
-	case HANDSFREE_SVCLASS_ID:
-		DBG("Found Handsfree record");
-		if (device->headset)
-			headset_update(device, uuid16, uuidstr);
-		else
-			device->headset = headset_init(device, uuid16,
-								uuidstr);
-		break;
-	case HANDSFREE_AGW_SVCLASS_ID:
-		DBG("Found Handsfree AG record");
-		if (enabled.gateway && (device->gateway == NULL))
-			device->gateway = gateway_init(device);
-		break;
-	case AUDIO_SINK_SVCLASS_ID:
-		DBG("Found Audio Sink");
-		if (device->sink == NULL)
-			device->sink = sink_init(device);
-		break;
-	case AUDIO_SOURCE_SVCLASS_ID:
-		DBG("Found Audio Source");
-		if (device->source == NULL)
-			device->source = source_init(device);
-		break;
-	case AV_REMOTE_SVCLASS_ID:
-	case AV_REMOTE_TARGET_SVCLASS_ID:
-		DBG("Found AV %s", uuid16 == AV_REMOTE_SVCLASS_ID ?
-							"Remote" : "Target");
-		if (device->control)
-			control_update(device->control, uuid16);
-		else
-			device->control = control_init(device, uuid16);
-
-		if (device->sink && sink_is_active(device))
-			avrcp_connect(device);
-		break;
-	default:
-		DBG("Unrecognized UUID: 0x%04X", uuid16);
-		break;
-	}
-}
-
 static sdp_record_t *hsp_ag_record(uint8_t ch)
 {
 	sdp_list_t *svclass_id, *pfseq, *apseq, *root;
@@ -769,41 +672,106 @@ failed:
 	return -1;
 }
 
-static int audio_probe(struct btd_device *device, GSList *uuids)
+static struct audio_device *get_audio_dev(struct btd_device *device)
 {
 	struct btd_adapter *adapter = device_get_adapter(device);
 	bdaddr_t src, dst;
-	struct audio_device *audio_dev;
 
 	adapter_get_address(adapter, &src);
 	device_get_address(device, &dst, NULL);
 
-	audio_dev = manager_get_device(&src, &dst, TRUE);
+	return manager_get_device(&src, &dst, TRUE);
+}
+
+static void audio_remove(struct btd_device *device)
+{
+	struct audio_device *dev;
+
+	dev = get_audio_dev(device);
+	if (!dev)
+		return;
+
+	devices = g_slist_remove(devices, dev);
+	audio_device_unregister(dev);
+}
+
+static int hs_probe(struct btd_device *device, GSList *uuids)
+{
+	struct audio_device *audio_dev;
+
+	audio_dev = get_audio_dev(device);
 	if (!audio_dev) {
 		DBG("unable to get a device object");
 		return -1;
 	}
 
-	g_slist_foreach(uuids, (GFunc) handle_uuid, audio_dev);
+	if (audio_dev->headset)
+		headset_update(audio_dev, audio_dev->headset, uuids);
+	else
+		audio_dev->headset = headset_init(audio_dev, uuids,
+								enabled.hfp);
 
 	return 0;
 }
 
-static void audio_remove(struct btd_device *device)
+static int ag_probe(struct btd_device *device, GSList *uuids)
 {
-	struct audio_device *dev;
-	const char *path;
+	struct audio_device *audio_dev;
 
-	path = device_get_path(device);
+	audio_dev = get_audio_dev(device);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
 
-	dev = manager_find_device(path, NULL, NULL, NULL, FALSE);
-	if (!dev)
-		return;
+	if (!audio_dev->gateway)
+		return -EALREADY;
 
-	devices = g_slist_remove(devices, dev);
+	audio_dev->gateway = gateway_init(audio_dev);
 
-	audio_device_unregister(dev);
+	return 0;
+}
+
+static int a2dp_probe(struct btd_device *device, GSList *uuids)
+{
+	struct audio_device *audio_dev;
+
+	audio_dev = get_audio_dev(device);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
 
+	if (g_slist_find_custom(uuids, A2DP_SINK_UUID, bt_uuid_strcmp) &&
+						audio_dev->sink == NULL)
+		audio_dev->sink = sink_init(audio_dev);
+
+	if (g_slist_find_custom(uuids, A2DP_SOURCE_UUID, bt_uuid_strcmp) &&
+						audio_dev->source == NULL)
+		audio_dev->source = source_init(audio_dev);
+
+	return 0;
+}
+
+static int avrcp_probe(struct btd_device *device, GSList *uuids)
+{
+	struct audio_device *audio_dev;
+
+	audio_dev = get_audio_dev(device);
+	if (!audio_dev) {
+		DBG("unable to get a device object");
+		return -1;
+	}
+
+	if (audio_dev->control)
+		control_update(audio_dev->control, uuids);
+	else
+		audio_dev->control = control_init(audio_dev, uuids);
+
+	if (audio_dev->sink && sink_is_active(audio_dev))
+		avrcp_connect(audio_dev);
+
+	return 0;
 }
 
 static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp)
@@ -1113,40 +1081,51 @@ static void media_server_remove(struct btd_adapter *adapter)
 	audio_adapter_unref(adp);
 }
 
-static struct btd_device_driver audio_driver = {
-	.name	= "audio",
-	.uuids	= BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID, HSP_AG_UUID, HFP_AG_UUID,
-			ADVANCED_AUDIO_UUID, A2DP_SOURCE_UUID, A2DP_SINK_UUID,
-			AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID),
-	.probe	= audio_probe,
-	.remove	= audio_remove,
-};
+static struct btd_profile headset_profile = {
+	.name		= "audio-headset",
 
-static struct btd_adapter_driver headset_server_driver = {
-	.name	= "audio-headset",
-	.probe	= headset_server_probe,
-	.remove	= headset_server_remove,
+	.remote_uuids	= BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID),
+	.device_probe	= hs_probe,
+	.device_remove	= audio_remove,
+
+	.adapter_probe	= headset_server_probe,
+	.adapter_remove = headset_server_remove,
 };
 
-static struct btd_adapter_driver gateway_server_driver = {
-	.name	= "audio-gateway",
-	.probe	= gateway_server_probe,
-	.remove	= gateway_server_remove,
+static struct btd_profile gateway_profile = {
+	.name		= "audio-gateway",
+
+	.remote_uuids	= BTD_UUIDS(HSP_AG_UUID, HFP_AG_UUID),
+	.device_probe	= ag_probe,
+	.device_remove	= audio_remove,
+
+	.adapter_probe	= gateway_server_probe,
+	.adapter_remove = gateway_server_remove,
 };
 
-static struct btd_adapter_driver a2dp_server_driver = {
-	.name	= "audio-a2dp",
-	.probe	= a2dp_server_probe,
-	.remove	= a2dp_server_remove,
+static struct btd_profile a2dp_profile = {
+	.name		= "audio-a2dp",
+
+	.remote_uuids	= BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID),
+	.device_probe	= a2dp_probe,
+	.device_remove	= audio_remove,
+
+	.adapter_probe	= a2dp_server_probe,
+	.adapter_remove = a2dp_server_remove,
 };
 
-static struct btd_adapter_driver avrcp_server_driver = {
-	.name	= "audio-control",
-	.probe	= avrcp_server_probe,
-	.remove	= avrcp_server_remove,
+static struct btd_profile avrcp_profile = {
+	.name		= "audio-avrcp",
+
+	.remote_uuids	= BTD_UUIDS(AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID),
+	.device_probe	= avrcp_probe,
+	.device_remove	= audio_remove,
+
+	.adapter_probe	= avrcp_server_probe,
+	.adapter_remove = avrcp_server_remove,
 };
 
-static struct btd_adapter_driver media_server_driver = {
+static struct btd_adapter_driver media_driver = {
 	.name	= "media",
 	.probe	= media_server_probe,
 	.remove	= media_server_remove,
@@ -1228,22 +1207,20 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *conf,
 		max_connected_headsets = i;
 
 proceed:
-	if (enabled.control)
-		btd_register_adapter_driver(&avrcp_server_driver);
-
-	if (enabled.media)
-		btd_register_adapter_driver(&media_server_driver);
-
 	if (enabled.headset)
-		btd_register_adapter_driver(&headset_server_driver);
+		btd_profile_register(&headset_profile);
 
 	if (enabled.gateway)
-		btd_register_adapter_driver(&gateway_server_driver);
+		btd_profile_register(&gateway_profile);
 
 	if (enabled.source || enabled.sink)
-		btd_register_adapter_driver(&a2dp_server_driver);
+		btd_profile_register(&a2dp_profile);
 
-	btd_register_device_driver(&audio_driver);
+	if (enabled.control)
+		btd_profile_register(&avrcp_profile);
+
+	if (enabled.media)
+		btd_register_adapter_driver(&media_driver);
 
 	*enable_sco = (enabled.gateway || enabled.headset);
 
@@ -1264,22 +1241,20 @@ void audio_manager_exit(void)
 		config = NULL;
 	}
 
-	if (enabled.media)
-		btd_unregister_adapter_driver(&media_server_driver);
-
 	if (enabled.headset)
-		btd_unregister_adapter_driver(&headset_server_driver);
+		btd_profile_unregister(&headset_profile);
 
 	if (enabled.gateway)
-		btd_unregister_adapter_driver(&gateway_server_driver);
+		btd_profile_unregister(&gateway_profile);
 
 	if (enabled.source || enabled.sink)
-		btd_unregister_adapter_driver(&a2dp_server_driver);
+		btd_profile_unregister(&a2dp_profile);
 
 	if (enabled.control)
-		btd_unregister_adapter_driver(&avrcp_server_driver);
+		btd_profile_unregister(&avrcp_profile);
 
-	btd_unregister_device_driver(&audio_driver);
+	if (enabled.media)
+		btd_unregister_adapter_driver(&media_driver);
 }
 
 GSList *manager_find_devices(const char *path,
diff --git a/audio/manager.h b/audio/manager.h
index f1d3021..1320c71 100644
--- a/audio/manager.h
+++ b/audio/manager.h
@@ -38,8 +38,6 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *config,
 							gboolean *enable_sco);
 void audio_manager_exit(void);
 
-gboolean server_is_enabled(bdaddr_t *src, uint16_t svc);
-
 struct audio_device *manager_find_device(const char *path,
 					const bdaddr_t *src,
 					const bdaddr_t *dst,
diff --git a/audio/sink.c b/audio/sink.c
index 64e38f4..53a0b80 100644
--- a/audio/sink.c
+++ b/audio/sink.c
@@ -27,6 +27,7 @@
 #endif
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <errno.h>
 
 #include <bluetooth/bluetooth.h>
diff --git a/audio/source.c b/audio/source.c
index 6dabd1b..e4ba211 100644
--- a/audio/source.c
+++ b/audio/source.c
@@ -28,6 +28,7 @@
 #endif
 
 #include <stdint.h>
+#include <stdbool.h>
 #include <errno.h>
 
 #include <bluetooth/bluetooth.h>
diff --git a/plugins/adaptername.c b/plugins/adaptername.c
index d3341b5..c109b44 100644
--- a/plugins/adaptername.c
+++ b/plugins/adaptername.c
@@ -30,6 +30,7 @@
 #endif
 
 #include <stdlib.h>
+#include <stdbool.h>
 #include <unistd.h>
 #include <errno.h>
 
diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c
index ef2a7e7..a7259ba 100644
--- a/plugins/dbusoob.c
+++ b/plugins/dbusoob.c
@@ -27,6 +27,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <errno.h>
 #include <gdbus.h>
 
diff --git a/plugins/wiimote.c b/plugins/wiimote.c
index 9c69c6d..337d408 100644
--- a/plugins/wiimote.c
+++ b/plugins/wiimote.c
@@ -25,6 +25,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <bluetooth/bluetooth.h>
 #include <glib.h>
 
diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c
index ca849ad..e7c442f 100644
--- a/profiles/deviceinfo/deviceinfo.c
+++ b/profiles/deviceinfo/deviceinfo.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <glib.h>
 #include <bluetooth/uuid.h>
 
diff --git a/profiles/deviceinfo/manager.c b/profiles/deviceinfo/manager.c
index 1d59918..914ec40 100644
--- a/profiles/deviceinfo/manager.c
+++ b/profiles/deviceinfo/manager.c
@@ -22,6 +22,7 @@
 
 #include <glib.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <bluetooth/uuid.h>
 
 #include "adapter.h"
@@ -62,19 +63,19 @@ static void deviceinfo_driver_remove(struct btd_device *device)
 	deviceinfo_unregister(device);
 }
 
-static struct btd_device_driver deviceinfo_device_driver = {
-	.name	= "deviceinfo-driver",
-	.uuids	= BTD_UUIDS(DEVICE_INFORMATION_UUID),
-	.probe	= deviceinfo_driver_probe,
-	.remove	= deviceinfo_driver_remove
+static struct btd_profile deviceinfo_profile = {
+	.name		= "deviceinfo",
+	.remote_uuids	= BTD_UUIDS(DEVICE_INFORMATION_UUID),
+	.device_probe	= deviceinfo_driver_probe,
+	.device_remove	= deviceinfo_driver_remove
 };
 
 int deviceinfo_manager_init(void)
 {
-	return btd_register_device_driver(&deviceinfo_device_driver);
+	return btd_profile_register(&deviceinfo_profile);
 }
 
 void deviceinfo_manager_exit(void)
 {
-	btd_unregister_device_driver(&deviceinfo_device_driver);
+	btd_profile_unregister(&deviceinfo_profile);
 }
diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c
index 67cc5ae..ddd4e70 100644
--- a/profiles/gatt/gas.c
+++ b/profiles/gatt/gas.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <glib.h>
 #include <bluetooth/uuid.h>
 
diff --git a/profiles/gatt/manager.c b/profiles/gatt/manager.c
index 0702d26..9c5ea14 100644
--- a/profiles/gatt/manager.c
+++ b/profiles/gatt/manager.c
@@ -22,6 +22,7 @@
 
 #include <glib.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <bluetooth/uuid.h>
 
 #include "adapter.h"
@@ -69,19 +70,19 @@ static void gatt_driver_remove(struct btd_device *device)
 	gas_unregister(device);
 }
 
-static struct btd_device_driver gatt_device_driver = {
-	.name	= "gap-gatt-driver",
-	.uuids	= BTD_UUIDS(GAP_UUID, GATT_UUID),
-	.probe	= gatt_driver_probe,
-	.remove	= gatt_driver_remove
+static struct btd_profile gatt_profile = {
+	.name		= "gap-gatt-profile",
+	.remote_uuids	= BTD_UUIDS(GAP_UUID, GATT_UUID),
+	.device_probe	= gatt_driver_probe,
+	.device_remove	= gatt_driver_remove
 };
 
 int gatt_manager_init(void)
 {
-	return btd_register_device_driver(&gatt_device_driver);
+	return btd_profile_register(&gatt_profile);
 }
 
 void gatt_manager_exit(void)
 {
-	btd_unregister_device_driver(&gatt_device_driver);
+	btd_profile_unregister(&gatt_profile);
 }
diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c
index b54733b..5d62d35 100644
--- a/profiles/health/hdp.c
+++ b/profiles/health/hdp.c
@@ -22,6 +22,7 @@
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <sdpd.h>
 #include <unistd.h>
 
diff --git a/profiles/health/hdp_manager.c b/profiles/health/hdp_manager.c
index ffaed5d..416286e 100644
--- a/profiles/health/hdp_manager.c
+++ b/profiles/health/hdp_manager.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <bluetooth/sdp.h>
 #include <bluetooth/sdp_lib.h>
 #include <bluetooth/uuid.h>
@@ -51,12 +53,6 @@ static void hdp_adapter_remove(struct btd_adapter *adapter)
 	hdp_adapter_unregister(adapter);
 }
 
-static struct btd_adapter_driver hdp_adapter_driver = {
-	.name	= "hdp-adapter-driver",
-	.probe	= hdp_adapter_probe,
-	.remove	= hdp_adapter_remove,
-};
-
 static int hdp_driver_probe(struct btd_device *device, GSList *uuids)
 {
 	return hdp_device_register(connection, device);
@@ -67,11 +63,15 @@ static void hdp_driver_remove(struct btd_device *device)
 	hdp_device_unregister(device);
 }
 
-static struct btd_device_driver hdp_device_driver = {
-	.name	= "hdp-device-driver",
-	.uuids	= BTD_UUIDS(HDP_UUID, HDP_SOURCE_UUID, HDP_SINK_UUID),
-	.probe	= hdp_driver_probe,
-	.remove	= hdp_driver_remove
+static struct btd_profile hdp_profile = {
+	.name		= "hdp-profile",
+	.remote_uuids	= BTD_UUIDS(HDP_UUID, HDP_SOURCE_UUID, HDP_SINK_UUID),
+
+	.device_probe	= hdp_driver_probe,
+	.device_remove	= hdp_driver_remove,
+
+	.adapter_probe	= hdp_adapter_probe,
+	.adapter_remove	= hdp_adapter_remove,
 };
 
 int hdp_manager_init(DBusConnection *conn)
@@ -80,16 +80,16 @@ int hdp_manager_init(DBusConnection *conn)
 		return -1;
 
 	connection = dbus_connection_ref(conn);
-	btd_register_adapter_driver(&hdp_adapter_driver);
-	btd_register_device_driver(&hdp_device_driver);
+
+	btd_profile_register(&hdp_profile);
 
 	return 0;
 }
 
 void hdp_manager_exit(void)
 {
-	btd_unregister_device_driver(&hdp_device_driver);
-	btd_unregister_adapter_driver(&hdp_adapter_driver);
+	btd_profile_unregister(&hdp_profile);
+
 	hdp_manager_stop();
 
 	dbus_connection_unref(connection);
diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c
index 744e390..761e07d 100644
--- a/profiles/health/hdp_util.c
+++ b/profiles/health/hdp_util.c
@@ -25,6 +25,7 @@
 #endif
 
 #include <stdint.h>
+#include <stdbool.h>
 
 #include <glib.h>
 
diff --git a/profiles/input/device.c b/profiles/input/device.c
index e3f9dac..f1e1af0 100644
--- a/profiles/input/device.c
+++ b/profiles/input/device.c
@@ -26,6 +26,7 @@
 #endif
 
 #include <stdlib.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <unistd.h>
diff --git a/profiles/input/fakehid.c b/profiles/input/fakehid.c
index 3be1489..d9af2dd 100644
--- a/profiles/input/fakehid.c
+++ b/profiles/input/fakehid.c
@@ -25,6 +25,7 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
 #include <fcntl.h>
 #include <unistd.h>
 
diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c
index 000f173..664c52b 100644
--- a/profiles/input/hog_device.c
+++ b/profiles/input/hog_device.c
@@ -28,6 +28,7 @@
 #endif
 
 #include <stdlib.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <unistd.h>
 #include <sys/types.h>
diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c
index c544e79..6d971fa 100644
--- a/profiles/input/hog_manager.c
+++ b/profiles/input/hog_manager.c
@@ -27,6 +27,7 @@
 #endif
 
 #include <errno.h>
+#include <stdbool.h>
 
 #include "log.h"
 #include "../src/adapter.h"
@@ -55,21 +56,21 @@ static void hog_device_remove(struct btd_device *device)
 	hog_device_unregister(path);
 }
 
-static struct btd_device_driver hog_driver = {
-	.name	= "input-hog",
-	.uuids	= BTD_UUIDS(HOG_UUID),
-	.probe	= hog_device_probe,
-	.remove	= hog_device_remove,
+static struct btd_profile hog_profile = {
+	.name		= "input-hog",
+	.remote_uuids	= BTD_UUIDS(HOG_UUID),
+	.device_probe	= hog_device_probe,
+	.device_remove	= hog_device_remove,
 };
 
 static int hog_manager_init(void)
 {
-	return btd_register_device_driver(&hog_driver);
+	return btd_profile_register(&hog_profile);
 }
 
 static void hog_manager_exit(void)
 {
-	btd_unregister_device_driver(&hog_driver);
+	btd_profile_register(&hog_profile);
 }
 
 static int hog_init(void)
diff --git a/profiles/input/manager.c b/profiles/input/manager.c
index add9789..2f9e087 100644
--- a/profiles/input/manager.c
+++ b/profiles/input/manager.c
@@ -26,6 +26,7 @@
 #endif
 
 #include <errno.h>
+#include <stdbool.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sdp.h>
@@ -139,24 +140,23 @@ static void hid_server_remove(struct btd_adapter *adapter)
 	btd_adapter_unref(adapter);
 }
 
-static struct btd_device_driver input_hid_driver = {
-	.name	= "input-hid",
-	.uuids	= BTD_UUIDS(HID_UUID),
-	.probe	= hid_device_probe,
-	.remove	= hid_device_remove,
-};
+static struct btd_profile input_profile = {
+	.name		= "input-hid",
+	.remote_uuids	= BTD_UUIDS(HID_UUID),
+
+	.device_probe	= hid_device_probe,
+	.device_remove	= hid_device_remove,
 
-static struct btd_device_driver input_headset_driver = {
-	.name	= "input-headset",
-	.uuids	= BTD_UUIDS(HSP_HS_UUID),
-	.probe	= headset_probe,
-	.remove	= headset_remove,
+	.adapter_probe	= hid_server_probe,
+	.adapter_remove = hid_server_remove,
 };
 
-static struct btd_adapter_driver input_server_driver = {
-	.name   = "input-server",
-	.probe  = hid_server_probe,
-	.remove = hid_server_remove,
+static struct btd_profile input_headset_profile = {
+	.name		= "input-headset",
+	.remote_uuids	= BTD_UUIDS(HSP_HS_UUID),
+
+	.device_probe	= headset_probe,
+	.device_remove	= headset_remove,
 };
 
 int input_manager_init(DBusConnection *conn, GKeyFile *config)
@@ -174,22 +174,17 @@ int input_manager_init(DBusConnection *conn, GKeyFile *config)
 
 	connection = dbus_connection_ref(conn);
 
-	btd_register_adapter_driver(&input_server_driver);
-
-	btd_register_device_driver(&input_hid_driver);
-	btd_register_device_driver(&input_headset_driver);
+	btd_profile_register(&input_profile);
+	btd_profile_register(&input_headset_profile);
 
 	return 0;
 }
 
 void input_manager_exit(void)
 {
-	btd_unregister_device_driver(&input_hid_driver);
-	btd_unregister_device_driver(&input_headset_driver);
-
-	btd_unregister_adapter_driver(&input_server_driver);
+	btd_profile_unregister(&input_profile);
+	btd_profile_unregister(&input_headset_profile);
 
 	dbus_connection_unref(connection);
-
 	connection = NULL;
 }
diff --git a/profiles/network/connection.c b/profiles/network/connection.c
index 40b360f..dba448e 100644
--- a/profiles/network/connection.c
+++ b/profiles/network/connection.c
@@ -26,6 +26,7 @@
 #endif
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <errno.h>
 #include <unistd.h>
 #include <netinet/in.h>
@@ -573,23 +574,16 @@ static const GDBusSignalTable connection_signals[] = {
 	{ }
 };
 
-void connection_unregister(const char *path, uint16_t id)
+void connection_unregister(const char *path)
 {
 	struct network_peer *peer;
-	struct network_conn *nc;
 
 	peer = find_peer(peers, path);
 	if (!peer)
 		return;
 
-	nc = find_connection(peer->connections, id);
-	if (!nc)
-		return;
-
-	peer->connections = g_slist_remove(peer->connections, nc);
-	connection_free(nc);
-	if (peer->connections)
-		return;
+	g_slist_free_full(peer->connections, connection_free);
+	peer->connections = NULL;
 
 	g_dbus_unregister_interface(connection, path, NETWORK_PEER_INTERFACE);
 }
diff --git a/profiles/network/connection.h b/profiles/network/connection.h
index 5ea4147..a5e0e61 100644
--- a/profiles/network/connection.h
+++ b/profiles/network/connection.h
@@ -25,4 +25,4 @@ int connection_init(DBusConnection *conn);
 void connection_exit(void);
 int connection_register(struct btd_device *device, const char *path,
 			bdaddr_t *src, bdaddr_t *dst, uint16_t id);
-void connection_unregister(const char *path, uint16_t id);
+void connection_unregister(const char *path);
diff --git a/profiles/network/manager.c b/profiles/network/manager.c
index 7fcd8f0..ac36406 100644
--- a/profiles/network/manager.c
+++ b/profiles/network/manager.c
@@ -25,6 +25,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/bnep.h>
 #include <bluetooth/sdp.h>
@@ -72,7 +74,7 @@ done:
 				conf_security ? "true" : "false");
 }
 
-static int network_probe(struct btd_device *device, GSList *uuids, uint16_t id)
+static int network_probe(struct btd_device *device, GSList *uuids)
 {
 	struct btd_adapter *adapter = device_get_adapter(device);
 	const gchar *path = device_get_path(device);
@@ -83,46 +85,23 @@ static int network_probe(struct btd_device *device, GSList *uuids, uint16_t id)
 	adapter_get_address(adapter, &src);
 	device_get_address(device, &dst, NULL);
 
-	return connection_register(device, path, &src, &dst, id);
+	if (g_slist_find_custom(uuids, PANU_UUID, bt_uuid_strcmp))
+		connection_register(device, path, &src, &dst, BNEP_SVC_PANU);
+	if (g_slist_find_custom(uuids, GN_UUID, bt_uuid_strcmp))
+		connection_register(device, path, &src, &dst, BNEP_SVC_GN);
+	if (g_slist_find_custom(uuids, NAP_UUID, bt_uuid_strcmp))
+		connection_register(device, path, &src, &dst, BNEP_SVC_NAP);
+
+	return 0;
 }
 
-static void network_remove(struct btd_device *device, uint16_t id)
+static void network_remove(struct btd_device *device)
 {
 	const gchar *path = device_get_path(device);
 
 	DBG("path %s", path);
 
-	connection_unregister(path, id);
-}
-
-static int panu_probe(struct btd_device *device, GSList *uuids)
-{
-	return network_probe(device, uuids, BNEP_SVC_PANU);
-}
-
-static void panu_remove(struct btd_device *device)
-{
-	network_remove(device, BNEP_SVC_PANU);
-}
-
-static int gn_probe(struct btd_device *device, GSList *uuids)
-{
-	return network_probe(device, uuids, BNEP_SVC_GN);
-}
-
-static void gn_remove(struct btd_device *device)
-{
-	network_remove(device, BNEP_SVC_GN);
-}
-
-static int nap_probe(struct btd_device *device, GSList *uuids)
-{
-	return network_probe(device, uuids, BNEP_SVC_NAP);
-}
-
-static void nap_remove(struct btd_device *device)
-{
-	network_remove(device, BNEP_SVC_NAP);
+	connection_unregister(path);
 }
 
 static int network_server_probe(struct btd_adapter *adapter)
@@ -143,31 +122,14 @@ static void network_server_remove(struct btd_adapter *adapter)
 	server_unregister(adapter);
 }
 
-static struct btd_device_driver network_panu_driver = {
-	.name	= "network-panu",
-	.uuids	= BTD_UUIDS(PANU_UUID),
-	.probe	= panu_probe,
-	.remove	= panu_remove,
-};
-
-static struct btd_device_driver network_gn_driver = {
-	.name	= "network-gn",
-	.uuids	= BTD_UUIDS(GN_UUID),
-	.probe	= gn_probe,
-	.remove	= gn_remove,
-};
+static struct btd_profile network_profile = {
+	.name		= "network",
+	.remote_uuids	= BTD_UUIDS(PANU_UUID, GN_UUID, NAP_UUID),
+	.device_probe	= network_probe,
+	.device_remove	= network_remove,
 
-static struct btd_device_driver network_nap_driver = {
-	.name	= "network-nap",
-	.uuids	= BTD_UUIDS(NAP_UUID),
-	.probe	= nap_probe,
-	.remove	= nap_remove,
-};
-
-static struct btd_adapter_driver network_server_driver = {
-	.name	= "network-server",
-	.probe	= network_server_probe,
-	.remove	= network_server_remove,
+	.adapter_probe	= network_server_probe,
+	.adapter_remove	= network_server_remove,
 };
 
 int network_manager_init(DBusConnection *conn)
@@ -189,16 +151,11 @@ int network_manager_init(DBusConnection *conn)
 	if (server_init(conn, conf_security) < 0)
 		return -1;
 
-	/* Register network server if it doesn't exist */
-	btd_register_adapter_driver(&network_server_driver);
+	btd_profile_register(&network_profile);
 
 	if (connection_init(conn) < 0)
 		return -1;
 
-	btd_register_device_driver(&network_panu_driver);
-	btd_register_device_driver(&network_gn_driver);
-	btd_register_device_driver(&network_nap_driver);
-
 	connection = dbus_connection_ref(conn);
 
 	return 0;
@@ -208,13 +165,9 @@ void network_manager_exit(void)
 {
 	server_exit();
 
-	btd_unregister_device_driver(&network_panu_driver);
-	btd_unregister_device_driver(&network_gn_driver);
-	btd_unregister_device_driver(&network_nap_driver);
-
 	connection_exit();
 
-	btd_unregister_adapter_driver(&network_server_driver);
+	btd_profile_unregister(&network_profile);
 
 	dbus_connection_unref(connection);
 	connection = NULL;
diff --git a/profiles/proximity/immalert.c b/profiles/proximity/immalert.c
index 1540b61..cc7c26a 100644
--- a/profiles/proximity/immalert.c
+++ b/profiles/proximity/immalert.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <glib.h>
 #include <bluetooth/uuid.h>
 #include <adapter.h>
diff --git a/profiles/proximity/linkloss.c b/profiles/proximity/linkloss.c
index 14403cb..7be5223 100644
--- a/profiles/proximity/linkloss.c
+++ b/profiles/proximity/linkloss.c
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <glib.h>
 #include <bluetooth/uuid.h>
 #include <adapter.h>
diff --git a/profiles/proximity/manager.c b/profiles/proximity/manager.c
index f2e49a6..6368221 100644
--- a/profiles/proximity/manager.c
+++ b/profiles/proximity/manager.c
@@ -26,6 +26,8 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include <glib.h>
 #include <gdbus.h>
 #include <bluetooth/uuid.h>
@@ -60,6 +62,8 @@ static int attio_device_probe(struct btd_device *device, GSList *uuids)
 	struct gatt_primary *linkloss, *txpower, *immediate;
 	GSList *l, *primaries;
 
+	reporter_device_probe(device);
+
 	primaries = btd_device_get_primaries(device);
 
 	l = g_slist_find_custom(primaries, IMMEDIATE_ALERT_UUID,
@@ -79,19 +83,18 @@ static int attio_device_probe(struct btd_device *device, GSList *uuids)
 static void attio_device_remove(struct btd_device *device)
 {
 	monitor_unregister(connection, device);
+	reporter_device_remove(device);
 }
 
-static struct btd_device_driver monitor_driver = {
-	.name = "Proximity GATT Monitor Driver",
-	.uuids = BTD_UUIDS(IMMEDIATE_ALERT_UUID, LINK_LOSS_UUID, TX_POWER_UUID),
-	.probe = attio_device_probe,
-	.remove = attio_device_remove,
-};
+static struct btd_profile pxp_profile = {
+	.name		= "Proximity GATT Driver",
+	.remote_uuids	= BTD_UUIDS(GATT_UUID, IMMEDIATE_ALERT_UUID,
+						LINK_LOSS_UUID, TX_POWER_UUID),
+	.device_probe	= attio_device_probe,
+	.device_remove	= attio_device_remove,
 
-static struct btd_adapter_driver reporter_server_driver = {
-	.name = "Proximity GATT Reporter Driver",
-	.probe = reporter_init,
-	.remove = reporter_exit,
+	.adapter_probe	= reporter_init,
+	.adapter_remove	= reporter_exit,
 };
 
 static void load_config_file(GKeyFile *config)
@@ -122,29 +125,17 @@ int proximity_manager_init(DBusConnection *conn, GKeyFile *config)
 
 	load_config_file(config);
 
-	connection = dbus_connection_ref(conn);
-
-	ret = btd_register_device_driver(&monitor_driver);
+	ret = btd_profile_register(&pxp_profile);
 	if (ret < 0)
-		goto fail_monitor;
+		return ret;
 
-	ret = btd_register_adapter_driver(&reporter_server_driver);
-	if (ret < 0)
-		goto fail_reporter;
+	connection = dbus_connection_ref(conn);
 
 	return 0;
-
-fail_reporter:
-	btd_unregister_device_driver(&monitor_driver);
-
-fail_monitor:
-	dbus_connection_unref(connection);
-	return ret;
 }
 
 void proximity_manager_exit(void)
 {
-	btd_unregister_device_driver(&monitor_driver);
-	btd_unregister_adapter_driver(&reporter_server_driver);
+	btd_profile_unregister(&pxp_profile);
 	dbus_connection_unref(connection);
 }
diff --git a/profiles/proximity/monitor.c b/profiles/proximity/monitor.c
index f22d6f4..a5f265e 100644
--- a/profiles/proximity/monitor.c
+++ b/profiles/proximity/monitor.c
@@ -30,6 +30,7 @@
 #include <fcntl.h>
 #include <gdbus.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
diff --git a/profiles/proximity/reporter.c b/profiles/proximity/reporter.c
index 607de2b..d2eb194 100644
--- a/profiles/proximity/reporter.c
+++ b/profiles/proximity/reporter.c
@@ -26,10 +26,12 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+#include <errno.h>
+
 #include <glib.h>
 #include <bluetooth/uuid.h>
 #include <adapter.h>
-#include <errno.h>
 
 #include <dbus/dbus.h>
 #include <gdbus.h>
@@ -223,7 +225,7 @@ static void register_reporter_device(struct btd_device *device,
 	radapter->devices = g_slist_prepend(radapter->devices, device);
 }
 
-static int reporter_device_probe(struct btd_device *device, GSList *uuids)
+int reporter_device_probe(struct btd_device *device)
 {
 	struct reporter_adapter *radapter;
 	struct btd_adapter *adapter = device_get_adapter(device);
@@ -233,10 +235,11 @@ static int reporter_device_probe(struct btd_device *device, GSList *uuids)
 		return -1;
 
 	register_reporter_device(device, radapter);
+
 	return 0;
 }
 
-static void reporter_device_remove(struct btd_device *device)
+void reporter_device_remove(struct btd_device *device)
 {
 	struct reporter_adapter *radapter;
 	struct btd_adapter *adapter = device_get_adapter(device);
@@ -248,14 +251,6 @@ static void reporter_device_remove(struct btd_device *device)
 	unregister_reporter_device(device, radapter);
 }
 
-/* device driver for tracking remote GATT client devices */
-static struct btd_device_driver reporter_device_driver = {
-	.name = "Proximity GATT Reporter Device Tracker Driver",
-	.uuids = BTD_UUIDS(GATT_UUID),
-	.probe = reporter_device_probe,
-	.remove = reporter_device_remove,
-};
-
 int reporter_init(struct btd_adapter *adapter)
 {
 	struct reporter_adapter *radapter;
@@ -278,8 +273,6 @@ int reporter_init(struct btd_adapter *adapter)
 	register_tx_power(adapter);
 	imm_alert_register(adapter, radapter->conn);
 
-	btd_register_device_driver(&reporter_device_driver);
-
 	reporter_adapters = g_slist_prepend(reporter_adapters, radapter);
 	DBG("Proximity Reporter for adapter %p", adapter);
 
@@ -292,8 +285,6 @@ void reporter_exit(struct btd_adapter *adapter)
 	if (!radapter)
 		return;
 
-	btd_unregister_device_driver(&reporter_device_driver);
-
 	g_slist_foreach(radapter->devices, unregister_reporter_device,
 								radapter);
 
diff --git a/profiles/proximity/reporter.h b/profiles/proximity/reporter.h
index 5ae0eb2..4f3bee2 100644
--- a/profiles/proximity/reporter.h
+++ b/profiles/proximity/reporter.h
@@ -36,6 +36,9 @@ enum {
 	HIGH_ALERT = 0x02,
 };
 
+void reporter_device_remove(struct btd_device *device);
+int reporter_device_probe(struct btd_device *device);
+
 int reporter_init(struct btd_adapter *adapter);
 void reporter_exit(struct btd_adapter *adapter);
 
diff --git a/profiles/sap/manager.c b/profiles/sap/manager.c
index 9fa9c56..b563d7b 100644
--- a/profiles/sap/manager.c
+++ b/profiles/sap/manager.c
@@ -22,8 +22,11 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #include "log.h"
 #include "adapter.h"
+#include "device.h"
 
 #include "manager.h"
 #include "server.h"
@@ -51,10 +54,10 @@ static void sap_server_remove(struct btd_adapter *adapter)
 	sap_server_unregister(path);
 }
 
-static struct btd_adapter_driver sap_server_driver = {
-	.name	= "sap-server",
-	.probe	= sap_server_probe,
-	.remove	= sap_server_remove,
+static struct btd_profile sap_profile = {
+	.name		= "sap-server",
+	.adapter_probe	= sap_server_probe,
+	.adapter_remove	= sap_server_remove,
 };
 
 int sap_manager_init(DBusConnection *conn)
@@ -67,14 +70,14 @@ int sap_manager_init(DBusConnection *conn)
 		return -1;
 	}
 
-	btd_register_adapter_driver(&sap_server_driver);
+	btd_profile_register(&sap_profile);
 
 	return 0;
 }
 
 void sap_manager_exit(void)
 {
-	btd_unregister_adapter_driver(&sap_server_driver);
+	btd_profile_unregister(&sap_profile);
 
 	dbus_connection_unref(connection);
 	connection = NULL;
diff --git a/profiles/thermometer/manager.c b/profiles/thermometer/manager.c
index 3d5452b..9e909a3 100644
--- a/profiles/thermometer/manager.c
+++ b/profiles/thermometer/manager.c
@@ -22,6 +22,7 @@
 
 #include <gdbus.h>
 #include <errno.h>
+#include <stdbool.h>
 #include <bluetooth/uuid.h>
 
 #include "adapter.h"
@@ -64,18 +65,18 @@ static void thermometer_driver_remove(struct btd_device *device)
 	thermometer_unregister(device);
 }
 
-static struct btd_device_driver thermometer_device_driver = {
-	.name	= "thermometer-device-driver",
-	.uuids	= BTD_UUIDS(HEALTH_THERMOMETER_UUID),
-	.probe	= thermometer_driver_probe,
-	.remove	= thermometer_driver_remove
+static struct btd_profile thermometer_profile = {
+	.name		= "thermometer-device-driver",
+	.remote_uuids	= BTD_UUIDS(HEALTH_THERMOMETER_UUID),
+	.device_probe	= thermometer_driver_probe,
+	.device_remove	= thermometer_driver_remove
 };
 
 int thermometer_manager_init(DBusConnection *conn)
 {
 	int ret;
 
-	ret = btd_register_device_driver(&thermometer_device_driver);
+	ret = btd_profile_register(&thermometer_profile);
 	if (ret < 0)
                 return ret;
 
@@ -85,7 +86,7 @@ int thermometer_manager_init(DBusConnection *conn)
 
 void thermometer_manager_exit(void)
 {
-	btd_unregister_device_driver(&thermometer_device_driver);
+	btd_profile_unregister(&thermometer_profile);
 
 	dbus_connection_unref(connection);
 	connection = NULL;
diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c
index 6652a41..f58e558 100644
--- a/profiles/thermometer/thermometer.c
+++ b/profiles/thermometer/thermometer.c
@@ -24,10 +24,13 @@
 #include <config.h>
 #endif
 
-#include <gdbus.h>
+#include <stdbool.h>
 #include <errno.h>
+
 #include <bluetooth/uuid.h>
 
+#include <gdbus.h>
+
 #include "dbus-common.h"
 #include "adapter.h"
 #include "device.h"
diff --git a/profiles/time/manager.c b/profiles/time/manager.c
index 285c7b1..c29951c 100644
--- a/profiles/time/manager.c
+++ b/profiles/time/manager.c
@@ -26,24 +26,27 @@
 #include <config.h>
 #endif
 
-#include "adapter.h"
+#include <stdbool.h>
+
 #include "manager.h"
+#include "adapter.h"
+#include "device.h"
 #include "server.h"
 
-struct btd_adapter_driver time_server_driver = {
-	.name = "gatt-time-server",
-	.probe = time_server_init,
-	.remove = time_server_exit,
+struct btd_profile time_profile = {
+	.name 		= "gatt-time-server",
+	.adapter_probe	= time_server_init,
+	.adapter_remove	= time_server_exit,
 };
 
 int time_manager_init(void)
 {
-	btd_register_adapter_driver(&time_server_driver);
+	btd_profile_register(&time_profile);
 
 	return 0;
 }
 
 void time_manager_exit(void)
 {
-	btd_unregister_adapter_driver(&time_server_driver);
+	btd_profile_unregister(&time_profile);
 }
diff --git a/src/adapter.c b/src/adapter.c
index 50779fd..31fa87d 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <sys/ioctl.h>
 
 #include <bluetooth/bluetooth.h>
@@ -150,7 +151,8 @@ struct btd_adapter {
 	GSList *powered_callbacks;
 	GSList *pin_callbacks;
 
-	GSList *loaded_drivers;
+	GSList *drivers;
+	GSList *profiles;
 };
 
 static void dev_info_free(void *data)
@@ -1703,7 +1705,7 @@ static void create_stored_device_from_profiles(char *key, char *value,
 	if (list)
 		device_register_services(connection, device, list, ATT_PSM);
 
-	device_probe_drivers(device, uuids);
+	device_probe_profiles(device, uuids);
 
 	g_slist_free_full(uuids, g_free);
 }
@@ -1946,7 +1948,7 @@ static void create_stored_device_from_primaries(char *key, char *value,
 
 	device_register_services(connection, device, services, -1);
 
-	device_probe_drivers(device, uuids);
+	device_probe_profiles(device, uuids);
 
 	g_slist_free(uuids);
 }
@@ -2038,8 +2040,7 @@ static void probe_driver(struct btd_adapter *adapter, gpointer user_data)
 		return;
 	}
 
-	adapter->loaded_drivers = g_slist_prepend(adapter->loaded_drivers,
-									driver);
+	adapter->drivers = g_slist_prepend(adapter->drivers, driver);
 }
 
 static void load_drivers(struct btd_adapter *adapter)
@@ -2050,6 +2051,23 @@ static void load_drivers(struct btd_adapter *adapter)
 		probe_driver(adapter, l->data);
 }
 
+static void probe_profile(struct btd_profile *profile, void *data)
+{
+	struct btd_adapter *adapter = data;
+	int err;
+
+	if (profile->adapter_probe == NULL)
+		return;
+
+	err = profile->adapter_probe(adapter);
+	if (err < 0) {
+		error("%s: %s (%d)", profile->name, strerror(-err), -err);
+		return;
+	}
+
+	adapter->profiles = g_slist_prepend(adapter->profiles, profile);
+}
+
 static void load_connections(struct btd_adapter *adapter)
 {
 	GSList *l, *conns;
@@ -2229,11 +2247,24 @@ static void remove_driver(gpointer data, gpointer user_data)
 		driver->remove(adapter);
 }
 
+static void remove_profile(gpointer data, gpointer user_data)
+{
+	struct btd_profile *profile = data;
+	struct btd_adapter *adapter = user_data;
+
+	if (profile->adapter_remove)
+		profile->adapter_remove(adapter);
+}
+
 static void unload_drivers(struct btd_adapter *adapter)
 {
-	g_slist_foreach(adapter->loaded_drivers, remove_driver, adapter);
-	g_slist_free(adapter->loaded_drivers);
-	adapter->loaded_drivers = NULL;
+	g_slist_foreach(adapter->drivers, remove_driver, adapter);
+	g_slist_free(adapter->drivers);
+	adapter->drivers = NULL;
+
+	g_slist_foreach(adapter->profiles, remove_profile, adapter);
+	g_slist_free(adapter->profiles);
+	adapter->profiles = NULL;
 }
 
 static void set_mode_complete(struct btd_adapter *adapter)
@@ -2414,6 +2445,7 @@ gboolean adapter_init(struct btd_adapter *adapter, gboolean up)
 		btd_adapter_gatt_server_start(adapter);
 
 	load_drivers(adapter);
+	btd_profile_foreach(probe_profile, adapter);
 	clear_blocked(adapter);
 	load_devices(adapter);
 
@@ -3049,7 +3081,7 @@ int btd_register_adapter_driver(struct btd_adapter_driver *driver)
 
 static void unload_driver(struct btd_adapter *adapter, gpointer data)
 {
-	adapter->loaded_drivers = g_slist_remove(adapter->loaded_drivers, data);
+	adapter->drivers = g_slist_remove(adapter->drivers, data);
 }
 
 void btd_unregister_adapter_driver(struct btd_adapter_driver *driver)
diff --git a/src/agent.c b/src/agent.c
index e542425..b6ddd82 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 5cb1383..9b03e54 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -28,6 +28,7 @@
 
 #include <errno.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
 #include <glib.h>
diff --git a/src/device.c b/src/device.c
index 3b44d9b..8cb0876 100644
--- a/src/device.c
+++ b/src/device.c
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <errno.h>
@@ -136,7 +137,8 @@ struct btd_device {
 	GSList		*uuids;
 	GSList		*services;		/* Primary services path */
 	GSList		*primaries;		/* List of primary services */
-	GSList		*drivers;		/* List of device drivers */
+	GSList		*profiles;		/* Probed profiles */
+	GSList		*conns;			/* Connected profiles */
 	GSList		*watches;		/* List of disconnect_data */
 	gboolean	temporary;
 	struct agent	*agent;
@@ -169,6 +171,8 @@ struct btd_device {
 	guint		cleanup_id;
 };
 
+static GSList *profiles = NULL;
+
 static uint16_t uuid_list[] = {
 	L2CAP_UUID,
 	PNP_INFO_SVCLASS_ID,
@@ -176,8 +180,6 @@ static uint16_t uuid_list[] = {
 	0
 };
 
-static GSList *device_drivers = NULL;
-
 static void browse_request_free(struct browse_req *req)
 {
 	if (req->listener_id)
@@ -499,12 +501,12 @@ static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg,
 	return dbus_message_new_method_return(msg);
 }
 
-static void driver_remove(struct btd_device_driver *driver,
+static void profile_remove(struct btd_profile *profile,
 						struct btd_device *device)
 {
-	driver->remove(device);
+	profile->device_remove(device);
 
-	device->drivers = g_slist_remove(device->drivers, driver);
+	device->profiles = g_slist_remove(device->profiles, profile);
 }
 
 static gboolean do_disconnect(gpointer user_data)
@@ -531,7 +533,7 @@ int device_block(DBusConnection *conn, struct btd_device *device,
 	if (device->connected)
 		do_disconnect(device);
 
-	g_slist_foreach(device->drivers, (GFunc) driver_remove, device);
+	g_slist_foreach(device->profiles, (GFunc) profile_remove, device);
 
 	if (!update_only)
 		err = btd_adapter_block_address(device->adapter,
@@ -584,7 +586,7 @@ int device_unblock(DBusConnection *conn, struct btd_device *device,
 		emit_property_changed(conn, device->path,
 					DEVICE_INTERFACE, "Blocked",
 					DBUS_TYPE_BOOLEAN, &device->blocked);
-		device_probe_drivers(device, device->uuids);
+		device_probe_profiles(device, device->uuids);
 	}
 
 	return 0;
@@ -1209,9 +1211,9 @@ void device_remove(struct btd_device *device, gboolean remove_stored)
 	if (remove_stored)
 		device_remove_stored(device);
 
-	g_slist_foreach(device->drivers, (GFunc) driver_remove, device);
-	g_slist_free(device->drivers);
-	device->drivers = NULL;
+	g_slist_foreach(device->profiles, (GFunc) profile_remove, device);
+	g_slist_free(device->profiles);
+	device->profiles = NULL;
 
 	attrib_client_unregister(device->services);
 
@@ -1252,112 +1254,114 @@ static gboolean record_has_uuid(const sdp_record_t *rec,
 
 static GSList *device_match_pattern(struct btd_device *device,
 					const char *match_uuid,
-					GSList *profiles)
+					GSList *uuids)
 {
-	GSList *l, *uuids = NULL;
+	GSList *l, *match_uuids = NULL;
 
-	for (l = profiles; l; l = l->next) {
-		char *profile_uuid = l->data;
+	for (l = uuids; l; l = l->next) {
+		char *uuid = l->data;
 		const sdp_record_t *rec;
 
-		rec = btd_device_get_record(device, profile_uuid);
+		rec = btd_device_get_record(device, uuid);
 		if (!rec)
 			continue;
 
 		if (record_has_uuid(rec, match_uuid))
-			uuids = g_slist_append(uuids, profile_uuid);
+			match_uuids = g_slist_append(match_uuids, uuid);
 	}
 
-	return uuids;
+	return match_uuids;
 }
 
-static GSList *device_match_driver(struct btd_device *device,
-					struct btd_device_driver *driver,
-					GSList *profiles)
+static GSList *device_match_profile(struct btd_device *device,
+					struct btd_profile *profile,
+					GSList *uuids)
 {
 	const char **uuid;
-	GSList *uuids = NULL;
+	GSList *match_uuids = NULL;
 
-	for (uuid = driver->uuids; *uuid; uuid++) {
+	for (uuid = profile->remote_uuids; *uuid; uuid++) {
 		GSList *match;
 
 		/* skip duplicated uuids */
-		if (g_slist_find_custom(uuids, *uuid,
+		if (g_slist_find_custom(match_uuids, *uuid,
 				(GCompareFunc) strcasecmp))
 			continue;
 
-		/* match profile driver */
-		match = g_slist_find_custom(profiles, *uuid,
+		/* match profile uuid */
+		match = g_slist_find_custom(uuids, *uuid,
 					(GCompareFunc) strcasecmp);
 		if (match) {
-			uuids = g_slist_append(uuids, match->data);
+			match_uuids = g_slist_append(match_uuids, match->data);
 			continue;
 		}
 
 		/* match pattern driver */
-		match = device_match_pattern(device, *uuid, profiles);
-		uuids = g_slist_concat(uuids, match);
+		match = device_match_pattern(device, *uuid, uuids);
+		match_uuids = g_slist_concat(match_uuids, match);
 	}
 
-	return uuids;
+	return match_uuids;
 }
 
-void device_probe_drivers(struct btd_device *device, GSList *profiles)
+void device_probe_profiles(struct btd_device *device, GSList *uuids)
 {
-	GSList *list;
 	char addr[18];
-	int err;
+	GSList *l;
 
 	ba2str(&device->bdaddr, addr);
 
 	if (device->blocked) {
-		DBG("Skipping drivers for blocked device %s", addr);
+		DBG("Skipping profiles for blocked device %s", addr);
 		goto add_uuids;
 	}
 
-	DBG("Probing drivers for %s", addr);
+	DBG("Probing profiles for device %s", addr);
 
-	for (list = device_drivers; list; list = list->next) {
-		struct btd_device_driver *driver = list->data;
+	for (l = profiles; l != NULL; l = g_slist_next(l)) {
+		struct btd_profile *profile = l->data;
 		GSList *probe_uuids;
+		int err;
 
-		probe_uuids = device_match_driver(device, driver, profiles);
+		if (profile->device_probe == NULL)
+			continue;
 
+		probe_uuids = device_match_profile(device, profile, uuids);
 		if (!probe_uuids)
 			continue;
 
-		err = driver->probe(device, probe_uuids);
+		err = profile->device_probe(device, probe_uuids);
 		if (err < 0) {
-			error("%s driver probe failed for device %s",
-							driver->name, addr);
+			error("%s profile probe failed for device %s",
+							profile->name, addr);
 			g_slist_free(probe_uuids);
 			continue;
 		}
 
-		device->drivers = g_slist_append(device->drivers, driver);
+		device->profiles = g_slist_append(device->profiles, profile);
 		g_slist_free(probe_uuids);
 	}
 
 add_uuids:
-	for (list = profiles; list; list = list->next) {
-		GSList *l = g_slist_find_custom(device->uuids, list->data,
+	for (l = uuids; l != NULL; l = g_slist_next(l)) {
+		GSList *match = g_slist_find_custom(device->uuids, l->data,
 						(GCompareFunc) strcasecmp);
-		if (l)
+		if (match)
 			continue;
 
 		device->uuids = g_slist_insert_sorted(device->uuids,
-						g_strdup(list->data),
+						g_strdup(l->data),
 						(GCompareFunc) strcasecmp);
 	}
 }
 
-static void device_remove_drivers(struct btd_device *device, GSList *uuids)
+static void device_remove_profiles(struct btd_device *device, GSList *uuids)
 {
 	struct btd_adapter *adapter = device_get_adapter(device);
-	GSList *list, *next;
 	char srcaddr[18], dstaddr[18];
 	bdaddr_t src;
 	sdp_list_t *records;
+	GSList *l;
 
 	adapter_get_address(adapter, &src);
 	ba2str(&src, srcaddr);
@@ -1365,35 +1369,32 @@ static void device_remove_drivers(struct btd_device *device, GSList *uuids)
 
 	records = read_records(&src, &device->bdaddr);
 
-	DBG("Removing drivers for %s", dstaddr);
+	DBG("Removing profiles for %s", dstaddr);
 
-	for (list = device->drivers; list; list = next) {
-		struct btd_device_driver *driver = list->data;
+	for (l = profiles; l != NULL; l = g_slist_next(l)) {
+		struct btd_profile *profile = l->data;
 		const char **uuid;
 
-		next = list->next;
-
-		for (uuid = driver->uuids; *uuid; uuid++) {
+		for (uuid = profile->remote_uuids; *uuid; uuid++) {
 			if (!g_slist_find_custom(uuids, *uuid,
 						(GCompareFunc) strcasecmp))
 				continue;
 
-			DBG("UUID %s was removed from device %s",
-							*uuid, dstaddr);
+			DBG("UUID %s was removed from device %s", *uuid, dstaddr);
 
-			driver->remove(device);
-			device->drivers = g_slist_remove(device->drivers,
-								driver);
+			profile->device_remove(device);
+			device->profiles = g_slist_remove(device->profiles,
+									profile);
 			break;
 		}
 	}
 
-	for (list = uuids; list; list = list->next) {
+	for (l = uuids; l != NULL; l = g_slist_next(l)) {
 		sdp_record_t *rec;
 
-		device->uuids = g_slist_remove(device->uuids, list->data);
+		device->uuids = g_slist_remove(device->uuids, l->data);
 
-		rec = find_record_in_list(records, list->data);
+		rec = find_record_in_list(records, l->data);
 		if (!rec)
 			continue;
 
@@ -1402,7 +1403,6 @@ static void device_remove_drivers(struct btd_device *device, GSList *uuids)
 
 		records = sdp_list_remove(records, rec);
 		sdp_record_free(rec);
-
 	}
 
 	if (records)
@@ -1672,7 +1672,7 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
 		goto send_reply;
 	}
 
-	/* Probe matching drivers for services added */
+	/* Probe matching profiles for services added */
 	if (req->profiles_added) {
 		GSList *list;
 
@@ -1681,12 +1681,12 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data)
 			device_register_services(req->conn, device, list,
 								ATT_PSM);
 
-		device_probe_drivers(device, req->profiles_added);
+		device_probe_profiles(device, req->profiles_added);
 	}
 
-	/* Remove drivers for services removed */
+	/* Remove profiles for services removed */
 	if (req->profiles_removed)
-		device_remove_drivers(device, req->profiles_removed);
+		device_remove_profiles(device, req->profiles_removed);
 
 	/* Propagate services changes */
 	uuids_changed(req->device);
@@ -1903,9 +1903,9 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
 
 	device_register_services(req->conn, device, g_slist_copy(services), -1);
 	if (req->profiles_removed)
-		device_remove_drivers(device, req->profiles_removed);
+		device_remove_profiles(device, req->profiles_removed);
 
-	device_probe_drivers(device, req->profiles_added);
+	device_probe_profiles(device, req->profiles_added);
 
 	if (device->attios == NULL && device->attios_offline == NULL)
 		attio_cleanup(device);
@@ -2965,7 +2965,7 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid)
 	new_uuid = g_strdup(uuid);
 	uuid_list = g_slist_append(NULL, new_uuid);
 
-	device_probe_drivers(device, uuid_list);
+	device_probe_profiles(device, uuid_list);
 
 	g_free(new_uuid);
 	g_slist_free(uuid_list);
@@ -3000,18 +3000,6 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device,
 	return find_record_in_list(device->tmp_records, uuid);
 }
 
-int btd_register_device_driver(struct btd_device_driver *driver)
-{
-	device_drivers = g_slist_append(device_drivers, driver);
-
-	return 0;
-}
-
-void btd_unregister_device_driver(struct btd_device_driver *driver)
-{
-	device_drivers = g_slist_remove(device_drivers, driver);
-}
-
 struct btd_device *btd_device_ref(struct btd_device *device)
 {
 	device->ref++;
@@ -3190,3 +3178,41 @@ void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src,
 	device_set_product(device, product_id);
 	device_set_version(device, product_ver);
 }
+
+void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data),
+								void *data)
+{
+	GSList *l, *next;
+
+	for (l = profiles; l != NULL; l = next) {
+		struct btd_profile *profile = l->data;
+
+		next = g_slist_next(l);
+
+		func(profile, data);
+	}
+}
+
+int btd_profile_register(struct btd_profile *profile)
+{
+	profiles = g_slist_append(profiles, profile);
+	return 0;
+}
+
+void btd_profile_unregister(struct btd_profile *profile)
+{
+	profiles = g_slist_remove(profiles, profile);
+}
+
+void btd_profile_connected(struct btd_profile *profile,
+				struct btd_device *device, int err)
+{
+	if (err == 0)
+		device->conns = g_slist_append(device->conns, profile);
+}
+
+void btd_profile_disconnected(struct btd_profile *profile,
+						struct btd_device *device)
+{
+	device->conns = g_slist_remove(device->conns, profile);
+}
diff --git a/src/device.h b/src/device.h
index a65de26..ccb15fc 100644
--- a/src/device.h
+++ b/src/device.h
@@ -34,9 +34,41 @@ typedef enum {
 	AUTH_TYPE_NOTIFY_PINCODE,
 } auth_type_t;
 
+#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } )
+
+struct btd_profile {
+	const char *name;
+
+	const char *local_uuid;
+	const char **remote_uuids;
+
+	bool auto_connect;
+
+	int (*device_probe) (struct btd_device *device, GSList *uuids);
+	void (*device_remove) (struct btd_device *device);
+
+	void (*connect) (struct btd_device *device);
+	void (*disconnect) (struct btd_device *device);
+
+	int (*adapter_probe) (struct btd_adapter *adapter);
+	void (*adapter_remove) (struct btd_adapter *adapter);
+};
+
+void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data),
+								void *data);
+
+int btd_profile_register(struct btd_profile *profile);
+void btd_profile_unregister(struct btd_profile *profile);
+
+void btd_profile_connected(struct btd_profile *profile,
+					struct btd_device *device, int err);
+void btd_profile_disconnected(struct btd_profile *profile,
+						struct btd_device *device);
+
 struct btd_device *device_create(DBusConnection *conn,
 					struct btd_adapter *adapter,
 					const char *address, uint8_t bdaddr_type);
+
 void device_set_name(struct btd_device *device, const char *name);
 void device_get_name(struct btd_device *device, char *name, size_t len);
 uint16_t btd_device_get_vendor(struct btd_device *device);
@@ -49,7 +81,7 @@ int device_browse_primary(struct btd_device *device, DBusConnection *conn,
 				DBusMessage *msg, gboolean secure);
 int device_browse_sdp(struct btd_device *device, DBusConnection *conn,
 			DBusMessage *msg, uuid_t *search, gboolean reverse);
-void device_probe_drivers(struct btd_device *device, GSList *profiles);
+void device_probe_profiles(struct btd_device *device, GSList *profiles);
 const sdp_record_t *btd_device_get_record(struct btd_device *device,
 						const char *uuid);
 GSList *btd_device_get_primaries(struct btd_device *device);
@@ -108,18 +140,6 @@ void device_set_class(struct btd_device *device, uint32_t value);
 int device_get_appearance(struct btd_device *device, uint16_t *value);
 void device_set_appearance(struct btd_device *device, uint16_t value);
 
-#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } )
-
-struct btd_device_driver {
-	const char *name;
-	const char **uuids;
-	int (*probe) (struct btd_device *device, GSList *uuids);
-	void (*remove) (struct btd_device *device);
-};
-
-int btd_register_device_driver(struct btd_device_driver *driver);
-void btd_unregister_device_driver(struct btd_device_driver *driver);
-
 struct btd_device *btd_device_ref(struct btd_device *device);
 void btd_device_unref(struct btd_device *device);
 
diff --git a/src/event.c b/src/event.c
index 1586293..42d05b6 100644
--- a/src/event.c
+++ b/src/event.c
@@ -32,6 +32,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 
 #include <bluetooth/bluetooth.h>
diff --git a/src/mgmt.c b/src/mgmt.c
index 58aab2d..45a5c90 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <stdbool.h>
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <sys/wait.h>