Refactor class of device (and related values) handling to adapter_ops

The management interface will move class of device and extended inquiry
response handling to the kernel side so the same functionality needs to
be moved into hciops. These features are quite tightly coupled in
bluetoothd so splitting this into multiple patches would have been hard
(if not impossible). Thus this quite large single commit.
diff --git a/plugins/hciops.c b/plugins/hciops.c
index 499e193..3b6e11f 100644
--- a/plugins/hciops.c
+++ b/plugins/hciops.c
@@ -63,8 +63,19 @@
 
 #define SK(index) devs[(index)].sk
 #define BDADDR(index) devs[(index)].bdaddr
+#define NAME(index) devs[(index)].name
+#define EIR(index) devs[(index)].eir
 #define FEATURES(index) devs[(index)].features
+#define SSP_MODE(index) devs[(index)].ssp_mode
+#define TX_POWER(index) devs[(index)].tx_power
+#define CURRENT_COD(index) devs[(index)].current_cod
+#define WANTED_COD(index) devs[(index)].wanted_cod
+#define PENDING_COD(index) devs[(index)].pending_cod
+#define CACHE_ENABLE(index) devs[(index)].cache_enable
 #define VER(index) devs[(index)].ver
+#define DID_VENDOR(index) devs[(index)].did_vendor
+#define DID_PRODUCT(index) devs[(index)].did_product
+#define DID_VERSION(index) devs[(index)].did_version
 #define UP(index) devs[(index)].up
 #define PENDING(index) devs[(index)].pending
 #define CHANNEL(index) devs[(index)].channel
@@ -75,9 +86,24 @@
 static struct dev_info {
 	int sk;
 	bdaddr_t bdaddr;
+	char name[249];
+	uint8_t eir[240];
 	uint8_t features[8];
+	uint8_t ssp_mode;
+
+	int8_t tx_power;
+
+	uint32_t current_cod;
+	uint32_t wanted_cod;
+	uint32_t pending_cod;
+	gboolean cache_enable;
+
 	struct hci_version ver;
 
+	uint16_t did_vendor;
+	uint16_t did_product;
+	uint16_t did_version;
+
 	gboolean up;
 	unsigned long pending;
 
@@ -96,6 +122,7 @@
 	memset(&devs[index], 0, sizeof(struct dev_info));
 	SK(index) = sk;
 	PIN_LENGTH(index) = -1;
+	CACHE_ENABLE(index) = TRUE;
 }
 
 /* Async HCI command handling with callback support */
@@ -318,6 +345,9 @@
 		hci_send_cmd(SK(index), OGF_HOST_CTL,
 				OCF_READ_INQ_RESPONSE_TX_POWER_LEVEL, 0, NULL);
 
+	CURRENT_COD(index) = 0;
+	memset(EIR(index), 0, sizeof(EIR(index)));
+
 	manager_start_adapter(index);
 }
 
@@ -397,6 +427,16 @@
 	return err;
 }
 
+static int hciops_set_did(int index, uint16_t vendor, uint16_t product,
+							uint16_t version)
+{
+	DID_VENDOR(index) = vendor;
+	DID_PRODUCT(index) = product;
+	DID_VERSION(index) = version;
+
+	return 0;
+}
+
 /* End async HCI command handling */
 
 /* Start of HCI event callbacks */
@@ -872,6 +912,206 @@
 		start_adapter(index);
 }
 
+#define SIZEOF_UUID128 16
+
+static void eir_generate_uuid128(sdp_list_t *list,
+					uint8_t *ptr, uint16_t *eir_len)
+{
+	int i, k, uuid_count = 0;
+	uint16_t len = *eir_len;
+	uint8_t *uuid128;
+	gboolean truncated = FALSE;
+
+	/* Store UUIDs in place, skip 2 bytes to write type and length later */
+	uuid128 = ptr + 2;
+
+	for (; list; list = list->next) {
+		sdp_record_t *rec = list->data;
+		uint8_t *uuid128_data = rec->svclass.value.uuid128.data;
+
+		if (rec->svclass.type != SDP_UUID128)
+			continue;
+
+		/* Stop if not enough space to put next UUID128 */
+		if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
+			truncated = TRUE;
+			break;
+		}
+
+		/* Check for duplicates, EIR data is Little Endian */
+		for (i = 0; i < uuid_count; i++) {
+			for (k = 0; k < SIZEOF_UUID128; k++) {
+				if (uuid128[i * SIZEOF_UUID128 + k] !=
+					uuid128_data[SIZEOF_UUID128 - 1 - k])
+					break;
+			}
+			if (k == SIZEOF_UUID128)
+				break;
+		}
+
+		if (i < uuid_count)
+			continue;
+
+		/* EIR data is Little Endian */
+		for (k = 0; k < SIZEOF_UUID128; k++)
+			uuid128[uuid_count * SIZEOF_UUID128 + k] =
+				uuid128_data[SIZEOF_UUID128 - 1 - k];
+
+		len += SIZEOF_UUID128;
+		uuid_count++;
+	}
+
+	if (uuid_count > 0 || truncated) {
+		/* EIR Data length */
+		ptr[0] = (uuid_count * SIZEOF_UUID128) + 1;
+		/* EIR Data type */
+		ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
+		len += 2;
+		*eir_len = len;
+	}
+}
+
+static void create_ext_inquiry_response(int index, uint8_t *data)
+{
+	sdp_list_t *services;
+	sdp_list_t *list;
+	uint8_t *ptr = data;
+	uint16_t eir_len = 0;
+	uint16_t uuid16[EIR_DATA_LENGTH / 2];
+	int i, uuid_count = 0;
+	gboolean truncated = FALSE;
+	struct btd_adapter *adapter;
+	size_t name_len;
+
+	name_len = strlen(NAME(index));
+
+	if (name_len > 0) {
+		/* EIR Data type */
+		if (name_len > 48) {
+			name_len = 48;
+			ptr[1] = EIR_NAME_SHORT;
+		} else
+			ptr[1] = EIR_NAME_COMPLETE;
+
+		/* EIR Data length */
+		ptr[0] = name_len + 1;
+
+		memcpy(ptr + 2, NAME(index), name_len);
+
+		eir_len += (name_len + 2);
+		ptr += (name_len + 2);
+	}
+
+	if (TX_POWER(index) != 0) {
+		*ptr++ = 2;
+		*ptr++ = EIR_TX_POWER;
+		*ptr++ = (uint8_t) TX_POWER(index);
+		eir_len += 3;
+	}
+
+	if (DID_VENDOR(index) != 0x0000) {
+		uint16_t source = 0x0002;
+		*ptr++ = 9;
+		*ptr++ = EIR_DEVICE_ID;
+		*ptr++ = (source & 0x00ff);
+		*ptr++ = (source & 0xff00) >> 8;
+		*ptr++ = (DID_VENDOR(index) & 0x00ff);
+		*ptr++ = (DID_VENDOR(index) & 0xff00) >> 8;
+		*ptr++ = (DID_PRODUCT(index) & 0x00ff);
+		*ptr++ = (DID_PRODUCT(index) & 0xff00) >> 8;
+		*ptr++ = (DID_VERSION(index) & 0x00ff);
+		*ptr++ = (DID_VERSION(index) & 0xff00) >> 8;
+		eir_len += 10;
+	}
+
+	adapter = manager_find_adapter(&BDADDR(index));
+	if (adapter == NULL)
+		return;
+
+	services = adapter_get_services(adapter);
+
+	/* Group all UUID16 types */
+	for (list = services; list; list = list->next) {
+		sdp_record_t *rec = list->data;
+
+		if (rec->svclass.type != SDP_UUID16)
+			continue;
+
+		if (rec->svclass.value.uuid16 < 0x1100)
+			continue;
+
+		if (rec->svclass.value.uuid16 == PNP_INFO_SVCLASS_ID)
+			continue;
+
+		/* Stop if not enough space to put next UUID16 */
+		if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
+			truncated = TRUE;
+			break;
+		}
+
+		/* Check for duplicates */
+		for (i = 0; i < uuid_count; i++)
+			if (uuid16[i] == rec->svclass.value.uuid16)
+				break;
+
+		if (i < uuid_count)
+			continue;
+
+		uuid16[uuid_count++] = rec->svclass.value.uuid16;
+		eir_len += sizeof(uint16_t);
+	}
+
+	if (uuid_count > 0) {
+		/* EIR Data length */
+		ptr[0] = (uuid_count * sizeof(uint16_t)) + 1;
+		/* EIR Data type */
+		ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
+
+		ptr += 2;
+		eir_len += 2;
+
+		for (i = 0; i < uuid_count; i++) {
+			*ptr++ = (uuid16[i] & 0x00ff);
+			*ptr++ = (uuid16[i] & 0xff00) >> 8;
+		}
+	}
+
+	/* Group all UUID128 types */
+	if (eir_len <= EIR_DATA_LENGTH - 2)
+		eir_generate_uuid128(services, ptr, &eir_len);
+}
+
+static void update_ext_inquiry_response(int index)
+{
+	write_ext_inquiry_response_cp cp;
+
+	DBG("hci%d", index);
+
+	if (!(FEATURES(index)[6] & LMP_EXT_INQ))
+		return;
+
+	if (SSP_MODE(index) == 0)
+		return;
+
+	if (CACHE_ENABLE(index))
+		return;
+
+	memset(&cp, 0, sizeof(cp));
+
+	create_ext_inquiry_response(index, cp.data);
+
+	if (memcmp(cp.data, EIR(index), sizeof(cp.data)) == 0)
+		return;
+
+	memcpy(EIR(index), cp.data, sizeof(cp.data));
+
+	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
+				OCF_WRITE_EXT_INQUIRY_RESPONSE,
+				WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0)
+		error("Unable to write EIR data: %s (%d)",
+						strerror(errno), errno);
+}
+
 static void update_name(int index, const char *name)
 {
 	struct btd_adapter *adapter;
@@ -879,6 +1119,8 @@
 	adapter = manager_find_adapter(&BDADDR(index));
 	if (adapter)
 		adapter_update_local_name(adapter, name);
+
+	update_ext_inquiry_response(index);
 }
 
 static void read_local_name_complete(int index, read_local_name_rp *rp)
@@ -888,6 +1130,8 @@
 	if (rp->status)
 		return;
 
+	memcpy(NAME(index), rp->name, 248);
+
 	if (!PENDING(index)) {
 		update_name(index, (char *) rp->name);
 		return;
@@ -922,20 +1166,14 @@
 static void read_tx_power_complete(int index, void *ptr)
 {
 	read_inq_response_tx_power_level_rp *rp = ptr;
-	struct btd_adapter *adapter;
 
 	DBG("hci%d status %u", index, rp->status);
 
 	if (rp->status)
 		return;
 
-	adapter = manager_find_adapter(&BDADDR(index));
-	if (!adapter) {
-		error("No matching adapter found");
-		return;
-	}
-
-	adapter_update_tx_power(adapter, rp->level);
+	TX_POWER(index) = rp->level;
+	update_ext_inquiry_response(index);
 }
 
 static void read_simple_pairing_mode_complete(int index, void *ptr)
@@ -948,6 +1186,9 @@
 	if (rp->status)
 		return;
 
+	SSP_MODE(index) = rp->mode;
+	update_ext_inquiry_response(index);
+
 	adapter = manager_find_adapter(&BDADDR(index));
 	if (!adapter) {
 		error("No matching adapter found");
@@ -1026,6 +1267,91 @@
 	adapter_mode_changed(adapter, rp->enable);
 }
 
+static int hciops_set_class(int index, uint32_t class)
+{
+	write_class_of_dev_cp cp;
+
+	DBG("hci%d class 0x%06x", index, class);
+
+	memcpy(cp.dev_class, &class, 3);
+
+	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV,
+					WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0)
+		return -errno;
+
+	PENDING_COD(index) = class;
+
+	return 0;
+}
+
+/* Limited Discoverable bit mask in CoD */
+#define LIMITED_BIT			0x002000
+
+static int hciops_set_limited_discoverable(int index, gboolean limited)
+{
+	int num = (limited ? 2 : 1);
+	uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };
+	write_current_iac_lap_cp cp;
+
+	DBG("hci%d limited %d", index, limited);
+
+	/* Check if limited bit needs to be set/reset */
+	if (limited)
+		WANTED_COD(index) |= LIMITED_BIT;
+	else
+		WANTED_COD(index) &= ~LIMITED_BIT;
+
+	/* If we dont need the toggling, save an unnecessary CoD write */
+	if (PENDING_COD(index) || WANTED_COD(index) == CURRENT_COD(index))
+		return 0;
+
+	/*
+	 * 1: giac
+	 * 2: giac + liac
+	 */
+	memset(&cp, 0, sizeof(cp));
+	cp.num_current_iac = num;
+	memcpy(&cp.lap, lap, num * 3);
+
+	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP,
+						(num * 3 + 1), &cp) < 0)
+		return -errno;
+
+	return hciops_set_class(index, WANTED_COD(index));
+}
+
+static void write_class_complete(int index, uint8_t status)
+{
+	struct btd_adapter *adapter;
+
+	if (status)
+		return;
+
+	if (PENDING_COD(index) == 0)
+		return;
+
+	CURRENT_COD(index) = PENDING_COD(index);
+	PENDING_COD(index) = 0;
+
+	adapter = manager_find_adapter(&BDADDR(index));
+	if (adapter)
+		btd_adapter_class_changed(adapter, CURRENT_COD(index));
+
+	update_ext_inquiry_response(index);
+
+	if (WANTED_COD(index) == CURRENT_COD(index))
+		return;
+
+	if (WANTED_COD(index) & LIMITED_BIT &&
+			!(CURRENT_COD(index) & LIMITED_BIT))
+		hciops_set_limited_discoverable(index, TRUE);
+	else if (!(WANTED_COD(index) & LIMITED_BIT) &&
+					(CURRENT_COD(index) & LIMITED_BIT))
+		hciops_set_limited_discoverable(index, FALSE);
+	else
+		hciops_set_class(index, WANTED_COD(index));
+}
+
 static inline void cmd_complete(int index, void *ptr)
 {
 	evt_cmd_complete *evt = ptr;
@@ -1077,7 +1403,7 @@
 		read_scan_complete(index, status, ptr);
 		break;
 	case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV):
-		adapter_set_class_complete(&BDADDR(index), status);
+		write_class_complete(index, status);
 		break;
 	case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SIMPLE_PAIRING_MODE):
 		if (!status)
@@ -1787,6 +2113,8 @@
 	case HCI_DEV_DOWN:
 		info("HCI dev %d down", index);
 		UP(index) = FALSE;
+		PENDING_COD(index) = 0;
+		CACHE_ENABLE(index) = TRUE;
 		if (!PENDING(index)) {
 			manager_stop_adapter(index);
 			init_pending(index);
@@ -2066,43 +2394,27 @@
 	return 0;
 }
 
-static int hciops_set_class(int index, uint32_t class)
+static int hciops_set_dev_class(int index, uint8_t major, uint8_t minor)
 {
-	write_class_of_dev_cp cp;
+	int err;
 
-	DBG("hci%d class 0x%06x", index, class);
+	/* Update only the major and minor class bits keeping remaining bits
+	 * intact*/
+	WANTED_COD(index) &= 0xffe000;
+	WANTED_COD(index) |= ((major & 0x1f) << 8) | minor;
 
-	memcpy(cp.dev_class, &class, 3);
+	if (WANTED_COD(index) == CURRENT_COD(index) ||
+			CACHE_ENABLE(index) || PENDING_COD(index))
+		return 0;
 
-	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV,
-					WRITE_CLASS_OF_DEV_CP_SIZE, &cp) < 0)
-		return -errno;
+	DBG("Changing Major/Minor class to 0x%06x", WANTED_COD(index));
 
-	return 0;
-}
+	err = hciops_set_class(index, WANTED_COD(index));
+	if (err < 0)
+		error("Adapter class update failed: %s (%d)",
+						strerror(-err), -err);
 
-static int hciops_set_limited_discoverable(int index, uint32_t class,
-							gboolean limited)
-{
-	int num = (limited ? 2 : 1);
-	uint8_t lap[] = { 0x33, 0x8b, 0x9e, 0x00, 0x8b, 0x9e };
-	write_current_iac_lap_cp cp;
-
-	DBG("hci%d, class %06x limited %d", index, class, limited);
-
-	/*
-	 * 1: giac
-	 * 2: giac + liac
-	 */
-	memset(&cp, 0, sizeof(cp));
-	cp.num_current_iac = num;
-	memcpy(&cp.lap, lap, num * 3);
-
-	if (hci_send_cmd(SK(index), OGF_HOST_CTL, OCF_WRITE_CURRENT_IAC_LAP,
-						(num * 3 + 1), &cp) < 0)
-		return -errno;
-
-	return hciops_set_class(index, class);
+	return err;
 }
 
 static int hciops_start_inquiry(int index, uint8_t length, gboolean periodic)
@@ -2241,6 +2553,9 @@
 				CHANGE_LOCAL_NAME_CP_SIZE, &cp) < 0)
 		return -errno;
 
+	memcpy(NAME(index), cp.name, 248);
+	update_ext_inquiry_response(index);
+
 	return 0;
 }
 
@@ -2328,23 +2643,6 @@
 	return err;
 }
 
-static int hciops_write_eir_data(int index, uint8_t *data)
-{
-	write_ext_inquiry_response_cp cp;
-
-	DBG("hci%d", index);
-
-	memset(&cp, 0, sizeof(cp));
-	memcpy(cp.data, data, 240);
-
-	if (hci_send_cmd(SK(index), OGF_HOST_CTL,
-				OCF_WRITE_EXT_INQUIRY_RESPONSE,
-				WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE, &cp) < 0)
-		return -errno;
-
-	return 0;
-}
-
 static int hciops_read_bdaddr(int index, bdaddr_t *bdaddr)
 {
 	DBG("hci%d", index);
@@ -2666,6 +2964,124 @@
 	return 0;
 }
 
+static int set_service_classes(int index, uint8_t value)
+{
+	int err;
+
+	/* Update only the service class, keep the limited bit,
+	 * major/minor class bits intact */
+	WANTED_COD(index) &= 0x00ffff;
+	WANTED_COD(index) |= (value << 16);
+
+	/* If the cache is enabled or an existing CoD write is in progress
+	 * just bail out */
+	if (CACHE_ENABLE(index) || PENDING_COD(index))
+		return 0;
+
+	/* If we already have the CoD we want, update EIR and return */
+	if (CURRENT_COD(index) == WANTED_COD(index)) {
+		update_ext_inquiry_response(index);
+		return 0;
+	}
+
+	DBG("Changing service classes to 0x%06x", WANTED_COD(index));
+
+	err = hciops_set_class(index, WANTED_COD(index));
+	if (err < 0)
+		error("Adapter class update failed: %s (%d)",
+						strerror(-err), -err);
+
+	return err;
+}
+
+static int hciops_services_updated(int index)
+{
+	struct btd_adapter *adapter;
+	sdp_list_t *list;
+	uint8_t val = 0;
+
+	DBG("hci%d", index);
+
+	adapter = manager_find_adapter(&BDADDR(index));
+	if (adapter == NULL)
+		return -ENODEV;
+
+	for (list = adapter_get_services(adapter); list; list = list->next) {
+		sdp_record_t *rec = list->data;
+
+		if (rec->svclass.type != SDP_UUID16)
+			continue;
+
+		switch (rec->svclass.value.uuid16) {
+		case DIALUP_NET_SVCLASS_ID:
+		case CIP_SVCLASS_ID:
+			val |= 0x42;	/* Telephony & Networking */
+			break;
+		case IRMC_SYNC_SVCLASS_ID:
+		case OBEX_OBJPUSH_SVCLASS_ID:
+		case OBEX_FILETRANS_SVCLASS_ID:
+		case IRMC_SYNC_CMD_SVCLASS_ID:
+		case PBAP_PSE_SVCLASS_ID:
+			val |= 0x10;	/* Object Transfer */
+			break;
+		case HEADSET_SVCLASS_ID:
+		case HANDSFREE_SVCLASS_ID:
+			val |= 0x20;	/* Audio */
+			break;
+		case CORDLESS_TELEPHONY_SVCLASS_ID:
+		case INTERCOM_SVCLASS_ID:
+		case FAX_SVCLASS_ID:
+		case SAP_SVCLASS_ID:
+		/*
+		 * Setting the telephony bit for the handsfree audio gateway
+		 * role is not required by the HFP specification, but the
+		 * Nokia 616 carkit is just plain broken! It will refuse
+		 * pairing without this bit set.
+		 */
+		case HANDSFREE_AGW_SVCLASS_ID:
+			val |= 0x40;	/* Telephony */
+			break;
+		case AUDIO_SOURCE_SVCLASS_ID:
+		case VIDEO_SOURCE_SVCLASS_ID:
+			val |= 0x08;	/* Capturing */
+			break;
+		case AUDIO_SINK_SVCLASS_ID:
+		case VIDEO_SINK_SVCLASS_ID:
+			val |= 0x04;	/* Rendering */
+			break;
+		case PANU_SVCLASS_ID:
+		case NAP_SVCLASS_ID:
+		case GN_SVCLASS_ID:
+			val |= 0x02;	/* Networking */
+			break;
+		}
+	}
+
+	return set_service_classes(index, val);
+}
+
+static int hciops_disable_cod_cache(int index)
+{
+	DBG("hci%d cache_enable %d", index, CACHE_ENABLE(index));
+
+	if (!CACHE_ENABLE(index))
+		return 0;
+
+	DBG("hci%d current_cod 0x%06x wanted_cod 0x%06x", index,
+					CURRENT_COD(index), WANTED_COD(index));
+
+	/* Disable and flush svc cache. All successive service class
+	 * updates * will be written to the device */
+	CACHE_ENABLE(index) = FALSE;
+
+	if (CURRENT_COD(index) == WANTED_COD(index)) {
+		update_ext_inquiry_response(index);
+		return 0;
+	}
+
+	return hciops_set_class(index, WANTED_COD(index));
+}
+
 static struct btd_adapter_ops hci_ops = {
 	.setup = hciops_setup,
 	.cleanup = hciops_cleanup,
@@ -2682,11 +3098,10 @@
 	.resolve_name = hciops_resolve_name,
 	.cancel_resolve_name = hciops_cancel_resolve_name,
 	.set_name = hciops_set_name,
-	.set_class = hciops_set_class,
+	.set_dev_class = hciops_set_dev_class,
 	.set_fast_connectable = hciops_fast_connectable,
 	.read_clock = hciops_read_clock,
 	.get_conn_handle = hciops_conn_handle,
-	.write_eir_data = hciops_write_eir_data,
 	.read_bdaddr = hciops_read_bdaddr,
 	.block_device = hciops_block_device,
 	.unblock_device = hciops_unblock_device,
@@ -2705,6 +3120,9 @@
 	.write_le_host = hciops_write_le_host,
 	.get_remote_version = hciops_get_remote_version,
 	.encrypt_link = hciops_encrypt_link,
+	.set_did = hciops_set_did,
+	.services_updated = hciops_services_updated,
+	.disable_cod_cache = hciops_disable_cod_cache,
 };
 
 static int hciops_init(void)
diff --git a/plugins/mgmtops.c b/plugins/mgmtops.c
index 97853f9..3dfcf8e 100644
--- a/plugins/mgmtops.c
+++ b/plugins/mgmtops.c
@@ -464,16 +464,15 @@
 	return -ENOSYS;
 }
 
-static int mgmt_set_class(int index, uint32_t class)
+static int mgmt_set_dev_class(int index, uint8_t major, uint8_t minor)
 {
-	DBG("index %d class %u", index, class);
+	DBG("index %d major %u minor %u", index, major, minor);
 	return -ENOSYS;
 }
 
-static int mgmt_set_limited_discoverable(int index, uint32_t class,
-							gboolean limited)
+static int mgmt_set_limited_discoverable(int index, gboolean limited)
 {
-	DBG("index %d class %u, limited %d", index, class, limited);
+	DBG("index %d limited %d", index, limited);
 	return -ENOSYS;
 }
 
@@ -551,12 +550,6 @@
 	return -ENOSYS;
 }
 
-static int mgmt_write_eir_data(int index, uint8_t *data)
-{
-	DBG("index %d", index);
-	return -ENOSYS;
-}
-
 static int mgmt_read_bdaddr(int index, bdaddr_t *bdaddr)
 {
 	char addr[18];
@@ -744,11 +737,10 @@
 	.resolve_name = mgmt_resolve_name,
 	.cancel_resolve_name = mgmt_cancel_resolve_name,
 	.set_name = mgmt_set_name,
-	.set_class = mgmt_set_class,
+	.set_dev_class = mgmt_set_dev_class,
 	.set_fast_connectable = mgmt_fast_connectable,
 	.read_clock = mgmt_read_clock,
 	.get_conn_handle = mgmt_conn_handle,
-	.write_eir_data = mgmt_write_eir_data,
 	.read_bdaddr = mgmt_read_bdaddr,
 	.block_device = mgmt_block_device,
 	.unblock_device = mgmt_unblock_device,
diff --git a/src/adapter.c b/src/adapter.c
index 8e715dc..e37b200 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -65,9 +65,6 @@
 #define IO_CAPABILITY_NOINPUTNOOUTPUT	0x03
 #define IO_CAPABILITY_INVALID		0xFF
 
-/* Limited Discoverable bit mask in CoD */
-#define LIMITED_BIT			0x002000
-
 #define check_address(address) bachk(address)
 
 static DBusConnection *connection = NULL;
@@ -100,6 +97,7 @@
 	int up;
 	char *path;			/* adapter object path */
 	bdaddr_t bdaddr;		/* adapter Bluetooth Address */
+	uint32_t dev_class;		/* Class of Device */
 	guint discov_timeout_id;	/* discoverable timeout id */
 	guint stop_discov_id;		/* stop inquiry/scanning id */
 	uint32_t discov_timeout;	/* discoverable time(sec) */
@@ -125,7 +123,6 @@
 	sdp_list_t *services;		/* Services associated to adapter */
 
 	struct hci_dev dev;		/* hci info */
-	int8_t tx_power;		/* inq response tx power level */
 	gboolean pairable;		/* pairable state */
 
 	gboolean initialized;
@@ -133,12 +130,6 @@
 
 	gboolean off_requested;		/* DEVDOWN ioctl was called */
 
-	uint32_t current_cod;		/* Adapter's current class */
-	uint32_t pending_cod;
-	uint32_t wanted_cod;		/* CoD cache */
-
-	gboolean cache_enable;
-
 	gint ref;
 
 	GSList *powered_callbacks;
@@ -255,83 +246,10 @@
 	return dst;
 }
 
-static void update_ext_inquiry_response(struct btd_adapter *adapter)
-{
-	uint8_t data[240];
-	struct hci_dev *dev = &adapter->dev;
-	int ret;
-
-	if (!(dev->features[6] & LMP_EXT_INQ))
-		return;
-
-	memset(data, 0, sizeof(data));
-
-	if (dev->ssp_mode > 0)
-		create_ext_inquiry_response(dev->name, adapter->tx_power,
-						adapter->services, data);
-
-	ret = adapter_ops->write_eir_data(adapter->dev_id, data);
-	if (ret < 0)
-		error("Can't write extended inquiry response: %s (%d)",
-						strerror(-ret), -ret);
-}
-
-int adapter_set_service_classes(struct btd_adapter *adapter, uint8_t value)
-{
-	int err;
-
-	/* Update only the service class, keep the limited bit,
-	 * major/minor class bits intact */
-	adapter->wanted_cod &= 0x00ffff;
-	adapter->wanted_cod |= (value << 16);
-
-	/* If the cache is enabled or an existing CoD write is in progress
-	 * just bail out */
-	if (adapter->cache_enable || adapter->pending_cod)
-		return 0;
-
-	/* If we already have the CoD we want, update EIR and return */
-	if (adapter->current_cod == adapter->wanted_cod) {
-		update_ext_inquiry_response(adapter);
-		return 0;
-	}
-
-	DBG("Changing service classes to 0x%06x", adapter->wanted_cod);
-
-	err = adapter_ops->set_class(adapter->dev_id, adapter->wanted_cod);
-	if (err < 0)
-		error("Adapter class update failed: %s (%d)",
-						strerror(-err), -err);
-	else
-		adapter->pending_cod = adapter->wanted_cod;
-
-	return err;
-}
-
 int btd_adapter_set_class(struct btd_adapter *adapter, uint8_t major,
 								uint8_t minor)
 {
-	int err;
-
-	/* Update only the major and minor class bits keeping remaining bits
-	 * intact*/
-	adapter->wanted_cod &= 0xffe000;
-	adapter->wanted_cod |= ((major & 0x1f) << 8) | minor;
-
-	if (adapter->wanted_cod == adapter->current_cod ||
-			adapter->cache_enable || adapter->pending_cod)
-		return 0;
-
-	DBG("Changing Major/Minor class to 0x%06x", adapter->wanted_cod);
-
-	err = adapter_ops->set_class(adapter->dev_id, adapter->wanted_cod);
-	if (err < 0)
-		error("Adapter class update failed: %s (%d)",
-						strerror(-err), -err);
-	else
-		adapter->pending_cod = adapter->wanted_cod;
-
-	return err;
+	return adapter_ops->set_dev_class(adapter->dev_id, major, minor);
 }
 
 static int pending_remote_name_cancel(struct btd_adapter *adapter)
@@ -431,20 +349,7 @@
 {
 	DBG("%s", limited ? "TRUE" : "FALSE");
 
-	/* Check if limited bit needs to be set/reset */
-	if (limited)
-		adapter->wanted_cod |= LIMITED_BIT;
-	else
-		adapter->wanted_cod &= ~LIMITED_BIT;
-
-	/* If we dont need the toggling, save an unnecessary CoD write */
-	if (adapter->pending_cod ||
-			adapter->wanted_cod == adapter->current_cod)
-		return;
-
-	if (adapter_ops->set_limited_discoverable(adapter->dev_id,
-					adapter->wanted_cod, limited) == 0)
-		adapter->pending_cod = adapter->wanted_cod;
+	adapter_ops->set_limited_discoverable(adapter->dev_id, limited);
 }
 
 static void adapter_remove_discov_timeout(struct btd_adapter *adapter)
@@ -937,65 +842,21 @@
 	return dbus_message_new_method_return(msg);
 }
 
-void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status)
+void btd_adapter_class_changed(struct btd_adapter *adapter, uint32_t new_class)
 {
 	uint8_t class[3];
-	struct btd_adapter *adapter;
-	int err;
 
-	if (status)
-		return;
-
-	adapter = manager_find_adapter(bdaddr);
-	if (!adapter) {
-		error("Unable to find matching adapter");
-		return;
-	}
-
-	if (adapter->pending_cod == 0)
-		return;
-
-	adapter->current_cod = adapter->pending_cod;
-	adapter->pending_cod = 0;
-
-	class[2] = (adapter->current_cod >> 16) & 0xff;
-	class[1] = (adapter->current_cod >> 8) & 0xff;
-	class[0] = adapter->current_cod & 0xff;
+	class[2] = (new_class >> 16) & 0xff;
+	class[1] = (new_class >> 8) & 0xff;
+	class[0] = new_class & 0xff;
 
 	write_local_class(&adapter->bdaddr, class);
 
+	adapter->dev_class = new_class;
+
 	emit_property_changed(connection, adapter->path,
 				ADAPTER_INTERFACE, "Class",
-				DBUS_TYPE_UINT32, &adapter->current_cod);
-
-	update_ext_inquiry_response(adapter);
-
-	if (adapter->wanted_cod == adapter->current_cod)
-		return;
-
-	if (adapter->wanted_cod & LIMITED_BIT &&
-			!(adapter->current_cod & LIMITED_BIT))
-		err = adapter_ops->set_limited_discoverable(adapter->dev_id,
-						adapter->wanted_cod, TRUE);
-	else if (!(adapter->wanted_cod & LIMITED_BIT) &&
-					adapter->current_cod & LIMITED_BIT)
-		err = adapter_ops->set_limited_discoverable(adapter->dev_id,
-						adapter->wanted_cod, FALSE);
-	else
-		err = adapter_ops->set_class(adapter->dev_id,
-							adapter->wanted_cod);
-
-	if (err == 0)
-		adapter->pending_cod = adapter->wanted_cod;
-}
-
-void adapter_update_tx_power(struct btd_adapter *adapter, int8_t tx_power)
-{
-	adapter->tx_power = tx_power;
-
-	DBG("inquiry respone tx power level is %d", adapter->tx_power);
-
-	update_ext_inquiry_response(adapter);
+				DBUS_TYPE_UINT32, &new_class);
 }
 
 void adapter_update_local_name(struct btd_adapter *adapter, const char *name)
@@ -1019,8 +880,6 @@
 	}
 
 	adapter->name_stored = FALSE;
-
-	update_ext_inquiry_response(adapter);
 }
 
 static DBusMessage *set_name(DBusConnection *conn, DBusMessage *msg,
@@ -1050,7 +909,6 @@
 			return failed_strerror(msg, err);
 
 		adapter->name_stored = TRUE;
-		update_ext_inquiry_response(adapter);
 	}
 
 done:
@@ -1407,7 +1265,7 @@
 
 	/* Class */
 	dict_append_entry(&dict, "Class",
-				DBUS_TYPE_UINT32, &adapter->current_cod);
+				DBUS_TYPE_UINT32, &adapter->dev_class);
 
 	/* Powered */
 	value = (adapter->up && !adapter->off_requested) ? TRUE : FALSE;
@@ -2023,11 +1881,10 @@
 	if (g_str_equal(mode, "off"))
 		strncpy((char *) adapter->dev.name, name, MAX_NAME_LENGTH);
 
-	/* Set device class */
-	if (adapter->initialized && adapter->wanted_cod) {
-		cls[1] = (adapter->wanted_cod >> 8) & 0xff;
-		cls[0] = adapter->wanted_cod & 0xff;
-	} else if (read_local_class(&adapter->bdaddr, cls) < 0) {
+	if (adapter->initialized)
+		return 0;
+
+	if (read_local_class(&adapter->bdaddr, cls) < 0) {
 		uint32_t class = htobl(main_opts.class);
 		if (class)
 			memcpy(cls, &class, 3);
@@ -2212,31 +2069,6 @@
 	return main_opts.pairto;
 }
 
-static void adapter_disable_cod_cache(struct btd_adapter *adapter)
-{
-	int err;
-
-	if (!adapter)
-		return;
-
-	if (!adapter->cache_enable)
-		return;
-
-	/* Disable and flush svc cache. All successive service class updates
-	   will be written to the device */
-	adapter->cache_enable = FALSE;
-
-	if (adapter->current_cod == adapter->wanted_cod)
-		return;
-
-	err = adapter_ops->set_class(adapter->dev_id, adapter->wanted_cod);
-	if (err < 0)
-		error("Adapter class update failed: %s (%d)",
-						strerror(-err), -err);
-	else
-		adapter->pending_cod = adapter->wanted_cod;
-}
-
 static void call_adapter_powered_callbacks(struct btd_adapter *adapter,
 						gboolean powered)
 {
@@ -2323,7 +2155,6 @@
 	adapter->pairable_timeout = get_pairable_timeout(srcaddr);
 	adapter->state = STATE_IDLE;
 	adapter->mode = MODE_CONNECTABLE;
-	adapter->cache_enable = TRUE;
 	powered = TRUE;
 
 	/* Set pairable mode */
@@ -2358,6 +2189,7 @@
 
 	if (adapter->initialized == FALSE) {
 		sdp_init_services_list(&adapter->bdaddr);
+		btd_adapter_services_updated(adapter);
 		load_drivers(adapter);
 		clear_blocked(adapter);
 		load_devices(adapter);
@@ -2383,7 +2215,7 @@
 
 	call_adapter_powered_callbacks(adapter, TRUE);
 
-	adapter_disable_cod_cache(adapter);
+	adapter_ops->disable_cod_cache(adapter->dev_id);
 
 	return 0;
 }
@@ -2436,7 +2268,7 @@
 
 	memcpy(dev->features, features, 8);
 
-	adapter->current_cod = 0;
+	adapter->dev_class = 0;
 
 	adapter_setup(adapter, mode);
 
@@ -2487,6 +2319,8 @@
 	const char *modestr;
 	int err;
 
+	DBG("");
+
 	if (adapter->pending_mode == NULL)
 		return;
 
@@ -2569,8 +2403,6 @@
 	adapter->scan_mode = SCAN_DISABLED;
 	adapter->mode = MODE_OFF;
 	adapter->state = STATE_IDLE;
-	adapter->cache_enable = TRUE;
-	adapter->pending_cod = 0;
 	adapter->off_requested = FALSE;
 	adapter->name_stored = FALSE;
 
@@ -2589,8 +2421,6 @@
 
 	dev->ssp_mode = mode;
 
-	update_ext_inquiry_response(adapter);
-
 	return 0;
 }
 
@@ -2661,8 +2491,6 @@
 	adapter->path = g_strdup(path);
 	adapter->already_up = devup;
 
-	adapter->tx_power = 0;
-
 	if (!g_dbus_register_interface(conn, path, ADAPTER_INTERFACE,
 			adapter_methods, adapter_signals, NULL,
 			adapter, adapter_free)) {
@@ -3759,3 +3587,14 @@
 {
 	return adapter_ops->encrypt_link(adapter->dev_id, bdaddr, cb, user_data);
 }
+
+int btd_adapter_set_did(struct btd_adapter *adapter, uint16_t vendor,
+					uint16_t product, uint16_t version)
+{
+	return adapter_ops->set_did(adapter->dev_id, vendor, product, version);
+}
+
+int btd_adapter_services_updated(struct btd_adapter *adapter)
+{
+	return adapter_ops->services_updated(adapter->dev_id);
+}
diff --git a/src/adapter.h b/src/adapter.h
index a9f72e3..a02f61c 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -134,12 +134,12 @@
 				struct remote_dev_info *dev,
 				uint8_t *eir_data, size_t eir_length);
 void adapter_mode_changed(struct btd_adapter *adapter, uint8_t scan_mode);
-void adapter_update_tx_power(struct btd_adapter *adapter, int8_t tx_power);
 void adapter_update_local_name(struct btd_adapter *adapter, const char *name);
 void adapter_service_insert(const bdaddr_t *bdaddr, void *rec);
 void adapter_service_remove(const bdaddr_t *bdaddr, void *rec);
 sdp_list_t *adapter_get_services(struct btd_adapter *adapter);
-void adapter_set_class_complete(bdaddr_t *bdaddr, uint8_t status);
+void btd_adapter_class_changed(struct btd_adapter *adapter,
+							uint32_t new_class);
 
 struct agent *adapter_get_agent(struct btd_adapter *adapter);
 void adapter_add_connection(struct btd_adapter *adapter,
@@ -192,8 +192,7 @@
 	int (*set_powered) (int index, gboolean powered);
 	int (*set_connectable) (int index);
 	int (*set_discoverable) (int index);
-	int (*set_limited_discoverable) (int index, uint32_t class,
-						gboolean limited);
+	int (*set_limited_discoverable) (int index, gboolean limited);
 	int (*start_inquiry) (int index, uint8_t length, gboolean periodic);
 	int (*stop_inquiry) (int index);
 	int (*start_scanning) (int index);
@@ -202,12 +201,11 @@
 	int (*resolve_name) (int index, bdaddr_t *bdaddr);
 	int (*cancel_resolve_name) (int index, bdaddr_t *bdaddr);
 	int (*set_name) (int index, const char *name);
-	int (*set_class) (int index, uint32_t class);
+	int (*set_dev_class) (int index, uint8_t major, uint8_t minor);
 	int (*set_fast_connectable) (int index, gboolean enable);
 	int (*read_clock) (int index, int handle, int which, int timeout,
 					uint32_t *clock, uint16_t *accuracy);
 	int (*get_conn_handle) (int index, const bdaddr_t *bdaddr, int *handle);
-	int (*write_eir_data) (int index, uint8_t *data);
 	int (*read_bdaddr) (int index, bdaddr_t *bdaddr);
 	int (*block_device) (int index, bdaddr_t *bdaddr);
 	int (*unblock_device) (int index, bdaddr_t *bdaddr);
@@ -228,6 +226,10 @@
 						gboolean delayed);
 	int (*encrypt_link) (int index, bdaddr_t *bdaddr, bt_hci_result_t cb,
 							gpointer user_data);
+	int (*set_did) (int index, uint16_t vendor, uint16_t product,
+							uint16_t version);
+	int (*services_updated) (int index);
+	int (*disable_cod_cache) (int index);
 };
 
 int btd_register_adapter_ops(struct btd_adapter_ops *ops, gboolean priority);
@@ -287,3 +289,8 @@
 
 int btd_adapter_encrypt_link(struct btd_adapter *adapter, bdaddr_t *bdaddr,
 				bt_hci_result_t cb, gpointer user_data);
+
+int btd_adapter_set_did(struct btd_adapter *adapter, uint16_t vendor,
+					uint16_t product, uint16_t version);
+
+int btd_adapter_services_updated(struct btd_adapter *adapter);
diff --git a/src/manager.c b/src/manager.c
index 939a563..ccaa1a2 100644
--- a/src/manager.c
+++ b/src/manager.c
@@ -59,11 +59,6 @@
 	return base_path;
 }
 
-void manager_update_svc(struct btd_adapter* adapter, uint8_t svc)
-{
-	adapter_set_service_classes(adapter, svc);
-}
-
 static inline DBusMessage *no_such_adapter(DBusMessage *msg)
 {
 	return g_dbus_create_error(msg,
@@ -504,3 +499,14 @@
 			btd_adapter_restore_powered(adapter);
 	}
 }
+
+void btd_manager_set_did(uint16_t vendor, uint16_t product, uint16_t version)
+{
+	GSList *l;
+
+	for (l = adapters; l != NULL; l = g_slist_next(l)) {
+		struct btd_adapter *adapter = l->data;
+
+		btd_adapter_set_did(adapter, vendor, product, version);
+	}
+}
diff --git a/src/manager.h b/src/manager.h
index 6bf3e76..e6d5dd9 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -45,3 +45,4 @@
 void manager_set_default_adapter(int id);
 void manager_update_svc(struct btd_adapter *adapter, uint8_t svc);
 void btd_manager_set_offline(gboolean offline);
+void btd_manager_set_did(uint16_t vendor, uint16_t product, uint16_t version);
diff --git a/src/sdpd-database.c b/src/sdpd-database.c
index 882d567..a75b1a8 100644
--- a/src/sdpd-database.c
+++ b/src/sdpd-database.c
@@ -311,7 +311,7 @@
 {
 	sdp_list_t *p;
 
-	SDPDBG("");
+	DBG("");
 
 	for (p = access_db; p != NULL; p = p->next) {
 		sdp_access_t *access = p->data;
diff --git a/src/sdpd-service.c b/src/sdpd-service.c
index 60f3847..905a412 100644
--- a/src/sdpd-service.c
+++ b/src/sdpd-service.c
@@ -49,14 +49,8 @@
 #include "manager.h"
 #include "adapter.h"
 
-#define SIZEOF_UUID128 16
-
 static sdp_record_t *server = NULL;
 
-static uint16_t did_vendor = 0x0000;
-static uint16_t did_product = 0x0000;
-static uint16_t did_version = 0x0000;
-
 /*
  * List of version numbers supported by the SDP server.
  * Add to this list when newer versions are supported.
@@ -99,67 +93,6 @@
 	sdp_attr_replace(server, SDP_ATTR_SVCDB_STATE, d);
 }
 
-static void update_adapter_svclass_list(struct btd_adapter *adapter)
-{
-	sdp_list_t *list = adapter_get_services(adapter);
-	uint8_t val = 0;
-
-	for (; list; list = list->next) {
-		sdp_record_t *rec = list->data;
-
-		if (rec->svclass.type != SDP_UUID16)
-			continue;
-
-		switch (rec->svclass.value.uuid16) {
-		case DIALUP_NET_SVCLASS_ID:
-		case CIP_SVCLASS_ID:
-			val |= 0x42;	/* Telephony & Networking */
-			break;
-		case IRMC_SYNC_SVCLASS_ID:
-		case OBEX_OBJPUSH_SVCLASS_ID:
-		case OBEX_FILETRANS_SVCLASS_ID:
-		case IRMC_SYNC_CMD_SVCLASS_ID:
-		case PBAP_PSE_SVCLASS_ID:
-			val |= 0x10;	/* Object Transfer */
-			break;
-		case HEADSET_SVCLASS_ID:
-		case HANDSFREE_SVCLASS_ID:
-			val |= 0x20;	/* Audio */
-			break;
-		case CORDLESS_TELEPHONY_SVCLASS_ID:
-		case INTERCOM_SVCLASS_ID:
-		case FAX_SVCLASS_ID:
-		case SAP_SVCLASS_ID:
-		/*
-		 * Setting the telephony bit for the handsfree audio gateway
-		 * role is not required by the HFP specification, but the
-		 * Nokia 616 carkit is just plain broken! It will refuse
-		 * pairing without this bit set.
-		 */
-		case HANDSFREE_AGW_SVCLASS_ID:
-			val |= 0x40;	/* Telephony */
-			break;
-		case AUDIO_SOURCE_SVCLASS_ID:
-		case VIDEO_SOURCE_SVCLASS_ID:
-			val |= 0x08;	/* Capturing */
-			break;
-		case AUDIO_SINK_SVCLASS_ID:
-		case VIDEO_SINK_SVCLASS_ID:
-			val |= 0x04;	/* Rendering */
-			break;
-		case PANU_SVCLASS_ID:
-		case NAP_SVCLASS_ID:
-		case GN_SVCLASS_ID:
-			val |= 0x02;	/* Networking */
-			break;
-		}
-	}
-
-	SDPDBG("Service classes 0x%02x", val);
-
-	manager_update_svc(adapter, val);
-}
-
 static void update_svclass_list(const bdaddr_t *src)
 {
 	GSList *adapters = manager_get_adapters();
@@ -171,171 +104,11 @@
 		adapter_get_address(adapter, &bdaddr);
 
 		if (bacmp(src, BDADDR_ANY) == 0 || bacmp(src, &bdaddr) == 0)
-			update_adapter_svclass_list(adapter);
+			btd_adapter_services_updated(adapter);
 	}
 
 }
 
-static void eir_generate_uuid128(sdp_list_t *list,
-					uint8_t *ptr, uint16_t *eir_len)
-{
-	int i, k, index = 0;
-	uint16_t len = *eir_len;
-	uint8_t *uuid128;
-	gboolean truncated = FALSE;
-
-	/* Store UUIDs in place, skip 2 bytes to write type and length later */
-	uuid128 = ptr + 2;
-
-	for (; list; list = list->next) {
-		sdp_record_t *rec = list->data;
-		uint8_t *uuid128_data = rec->svclass.value.uuid128.data;
-
-		if (rec->svclass.type != SDP_UUID128)
-			continue;
-
-		/* Stop if not enough space to put next UUID128 */
-		if ((len + 2 + SIZEOF_UUID128) > EIR_DATA_LENGTH) {
-			truncated = TRUE;
-			break;
-		}
-
-		/* Check for duplicates, EIR data is Little Endian */
-		for (i = 0; i < index; i++) {
-			for (k = 0; k < SIZEOF_UUID128; k++) {
-				if (uuid128[i * SIZEOF_UUID128 + k] !=
-					uuid128_data[SIZEOF_UUID128 - 1 - k])
-					break;
-			}
-			if (k == SIZEOF_UUID128)
-				break;
-		}
-
-		if (i < index)
-			continue;
-
-		/* EIR data is Little Endian */
-		for (k = 0; k < SIZEOF_UUID128; k++)
-			uuid128[index * SIZEOF_UUID128 + k] =
-				uuid128_data[SIZEOF_UUID128 - 1 - k];
-
-		len += SIZEOF_UUID128;
-		index++;
-	}
-
-	if (index > 0 || truncated) {
-		/* EIR Data length */
-		ptr[0] = (index * SIZEOF_UUID128) + 1;
-		/* EIR Data type */
-		ptr[1] = truncated ? EIR_UUID128_SOME : EIR_UUID128_ALL;
-		len += 2;
-		*eir_len = len;
-	}
-}
-
-void create_ext_inquiry_response(const char *name,
-					int8_t tx_power, sdp_list_t *services,
-					uint8_t *data)
-{
-	sdp_list_t *list = services;
-	uint8_t *ptr = data;
-	uint16_t eir_len = 0;
-	uint16_t uuid16[EIR_DATA_LENGTH / 2];
-	int i, index = 0;
-	gboolean truncated = FALSE;
-
-	if (name) {
-		int len = strlen(name);
-
-		/* EIR Data type */
-		if (len > 48) {
-			len = 48;
-			ptr[1] = EIR_NAME_SHORT;
-		} else
-			ptr[1] = EIR_NAME_COMPLETE;
-
-		/* EIR Data length */
-		ptr[0] = len + 1;
-
-		memcpy(ptr + 2, name, len);
-
-		eir_len += (len + 2);
-		ptr += (len + 2);
-	}
-
-	if (tx_power != 0) {
-		*ptr++ = 2;
-		*ptr++ = EIR_TX_POWER;
-		*ptr++ = (uint8_t) tx_power;
-		eir_len += 3;
-	}
-
-	if (did_vendor != 0x0000) {
-		uint16_t source = 0x0002;
-		*ptr++ = 9;
-		*ptr++ = EIR_DEVICE_ID;
-		*ptr++ = (source & 0x00ff);
-		*ptr++ = (source & 0xff00) >> 8;
-		*ptr++ = (did_vendor & 0x00ff);
-		*ptr++ = (did_vendor & 0xff00) >> 8;
-		*ptr++ = (did_product & 0x00ff);
-		*ptr++ = (did_product & 0xff00) >> 8;
-		*ptr++ = (did_version & 0x00ff);
-		*ptr++ = (did_version & 0xff00) >> 8;
-		eir_len += 10;
-	}
-
-	/* Group all UUID16 types */
-	for (; list; list = list->next) {
-		sdp_record_t *rec = list->data;
-
-		if (rec->svclass.type != SDP_UUID16)
-			continue;
-
-		if (rec->svclass.value.uuid16 < 0x1100)
-			continue;
-
-		if (rec->svclass.value.uuid16 == PNP_INFO_SVCLASS_ID)
-			continue;
-
-		/* Stop if not enough space to put next UUID16 */
-		if ((eir_len + 2 + sizeof(uint16_t)) > EIR_DATA_LENGTH) {
-			truncated = TRUE;
-			break;
-		}
-
-		/* Check for duplicates */
-		for (i = 0; i < index; i++)
-			if (uuid16[i] == rec->svclass.value.uuid16)
-				break;
-
-		if (i < index)
-			continue;
-
-		uuid16[index++] = rec->svclass.value.uuid16;
-		eir_len += sizeof(uint16_t);
-	}
-
-	if (index > 0) {
-		/* EIR Data length */
-		ptr[0] = (index * sizeof(uint16_t)) + 1;
-		/* EIR Data type */
-		ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL;
-
-		ptr += 2;
-		eir_len += 2;
-
-		for (i = 0; i < index; i++) {
-			*ptr++ = (uuid16[i] & 0x00ff);
-			*ptr++ = (uuid16[i] & 0xff00) >> 8;
-		}
-	}
-
-	/* Group all UUID128 types */
-	if (eir_len <= EIR_DATA_LENGTH - 2)
-		eir_generate_uuid128(services, ptr, &eir_len);
-}
-
 void register_public_browse_group(void)
 {
 	sdp_list_t *browselist;
@@ -430,9 +203,7 @@
 
 	info("Adding device id record for %04x:%04x", vendor, product);
 
-	did_vendor = vendor;
-	did_product = product;
-	did_version = version;
+	btd_manager_set_did(vendor, product, version);
 
 	record->handle = sdp_next_handle();
 
diff --git a/src/sdpd.h b/src/sdpd.h
index 0e3dddf..98e5b20 100644
--- a/src/sdpd.h
+++ b/src/sdpd.h
@@ -103,8 +103,4 @@
 int add_record_to_server(const bdaddr_t *src, sdp_record_t *rec);
 int remove_record_from_server(uint32_t handle);
 
-void create_ext_inquiry_response(const char *name,
-					int8_t tx_power, sdp_list_t *services,
-					uint8_t *data);
-
 void sdp_init_services_list(bdaddr_t *device);