[PATCH] Fix not setting class of device in adapter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Set class of device in adapter when new class is received from kernel.
This fix adapters property Class being always zero.
---
 lib/mgmt.h    |    4 ++++
 src/adapter.c |   23 ++++++++++++++---------
 src/adapter.h |    2 +-
 src/mgmt.c    |   33 +++++++++++++++++++++++++++++++--
 4 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/lib/mgmt.h b/lib/mgmt.h
index a58915b..83dcd84 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -109,6 +109,10 @@ struct mgmt_mode {
 	uint8_t val;
 } __packed;
 
+struct mgmt_cod {
+	uint8_t val[3];
+} __packed;
+
 #define MGMT_OP_SET_POWERED		0x0005
 
 #define MGMT_OP_SET_DISCOVERABLE	0x0006
diff --git a/src/adapter.c b/src/adapter.c
index 8820e27..ada11f3 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -684,27 +684,32 @@ static DBusMessage *set_pairable_timeout(DBusConnection *conn,
 	return dbus_message_new_method_return(msg);
 }
 
-void btd_adapter_class_changed(struct btd_adapter *adapter, uint32_t new_class)
+void btd_adapter_class_changed(struct btd_adapter *adapter, uint8_t *new_class)
 {
-	uint8_t class[3];
+	uint32_t class;
 
-	class[2] = (new_class >> 16) & 0xff;
-	class[1] = (new_class >> 8) & 0xff;
-	class[0] = new_class & 0xff;
+	class = new_class[0] | (new_class[1] << 8) | (new_class[2] << 16);
 
-	write_local_class(&adapter->bdaddr, class);
+	if (class == adapter->dev_class)
+		return;
+
+	write_local_class(&adapter->bdaddr, new_class);
 
 	adapter->dev_class = new_class;
 
 	if (main_opts.gatt_enabled) {
+		uint8_t cls[3];
+
+		memcpy(cls, new_class, sizeof(cls));
+
 		/* Removes service class */
-		class[1] = class[1] & 0x1f;
-		attrib_gap_set(adapter, GATT_CHARAC_APPEARANCE, class, 2);
+		cls[1] = cls[1] & 0x1f;
+		attrib_gap_set(adapter, GATT_CHARAC_APPEARANCE, cls, 2);
 	}
 
 	emit_property_changed(connection, adapter->path,
 				ADAPTER_INTERFACE, "Class",
-				DBUS_TYPE_UINT32, &new_class);
+				DBUS_TYPE_UINT32, &class);
 }
 
 void adapter_name_changed(struct btd_adapter *adapter, const char *name)
diff --git a/src/adapter.h b/src/adapter.h
index 602bb6f..d8a1bb1 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -120,7 +120,7 @@ void adapter_name_changed(struct btd_adapter *adapter, const char *name);
 void adapter_service_insert(struct btd_adapter *adapter, void *rec);
 void adapter_service_remove(struct btd_adapter *adapter, void *rec);
 void btd_adapter_class_changed(struct btd_adapter *adapter,
-							uint32_t new_class);
+							uint8_t *new_class);
 void btd_adapter_pairable_changed(struct btd_adapter *adapter,
 							gboolean pairable);
 
diff --git a/src/mgmt.c b/src/mgmt.c
index c55b1a8..c893972 100644
--- a/src/mgmt.c
+++ b/src/mgmt.c
@@ -1308,6 +1308,30 @@ static void handle_pending_uuids(uint16_t index)
 	g_free(pending);
 }
 
+static void mgmt_update_cod(uint16_t index, void *buf, size_t len)
+{
+	struct mgmt_cod *rp = buf;
+	struct controller_info *info;
+	struct btd_adapter *adapter;
+
+	DBG("index %d", index);
+
+	if (len < sizeof(*rp)) {
+		error("Too small class of device reply");
+		return;
+	}
+
+	info = &controllers[index];
+
+	adapter = manager_find_adapter(&info->bdaddr);
+	if (adapter == NULL) {
+		DBG("Adapter not found");
+		return;
+	}
+
+	btd_adapter_class_changed(adapter, rp->val);
+}
+
 static void mgmt_add_uuid_complete(int sk, uint16_t index, void *buf,
 								size_t len)
 {
@@ -1318,6 +1342,7 @@ static void mgmt_add_uuid_complete(int sk, uint16_t index, void *buf,
 		return;
 	}
 
+	mgmt_update_cod(index, buf, len);
 	handle_pending_uuids(index);
 }
 
@@ -1370,9 +1395,11 @@ static void mgmt_cmd_complete(int sk, uint16_t index, void *buf, size_t len)
 		break;
 	case MGMT_OP_REMOVE_UUID:
 		DBG("remove_uuid complete");
+		mgmt_update_cod(index, buf, len);
 		break;
 	case MGMT_OP_SET_DEV_CLASS:
 		DBG("set_dev_class complete");
+		mgmt_update_cod(index, buf, len);
 		break;
 	case MGMT_OP_LOAD_LINK_KEYS:
 		DBG("load_link_keys complete");
@@ -1735,7 +1762,7 @@ static void mgmt_new_ltk(int sk, uint16_t index, void *buf, size_t len)
 		bonding_complete(info, &ev->key.addr.bdaddr, 0);
 }
 
-static void mgmt_cod_changed(int sk, uint16_t index)
+static void mgmt_cod_changed(int sk, uint16_t index, void *buf, size_t len)
 {
 	struct controller_info *info;
 
@@ -1752,6 +1779,8 @@ static void mgmt_cod_changed(int sk, uint16_t index)
 		info->pending_cod_change = FALSE;
 		handle_pending_uuids(index);
 	}
+
+	mgmt_update_cod(index, buf, len);
 }
 
 static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data)
@@ -1817,7 +1846,7 @@ static gboolean mgmt_event(GIOChannel *io, GIOCondition cond, gpointer user_data
 		mgmt_new_settings(sk, index, buf + MGMT_HDR_SIZE, len);
 		break;
 	case MGMT_EV_CLASS_OF_DEV_CHANGED:
-		mgmt_cod_changed(sk, index);
+		mgmt_cod_changed(sk, index, buf + MGMT_HDR_SIZE, len);
 		break;
 	case MGMT_EV_NEW_LINK_KEY:
 		mgmt_new_link_key(sk, index, buf + MGMT_HDR_SIZE, len);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux