[PATCH BlueZ] gatt: Fix assuming writes to CCC will always contain 2 bytes

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

 



From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>

The spec actually allows writing just 1 byte:

BLUETOOTH CORE SPECIFICATION Version 5.1 | Vol 3, Part F
page 2320:

  'If the attribute value has a fixed length and the Attribute Value
   parameter length is less than or equal to the length of the attribute
   value, the octets of the attribute value parameter length shall be
   written; all other octets in this attribute value shall be
   unchanged.'
---
 src/gatt-database.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/src/gatt-database.c b/src/gatt-database.c
index 1753df513..262503e61 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -186,7 +186,7 @@ typedef void (*btd_gatt_database_destroy_t) (void *data);
 
 struct ccc_state {
 	uint16_t handle;
-	uint8_t value[2];
+	uint16_t value;
 };
 
 struct ccc_cb_data {
@@ -304,7 +304,7 @@ static void clear_ccc_state(void *data, void *user_data)
 	struct btd_gatt_database *db = user_data;
 	struct ccc_cb_data *ccc_cb;
 
-	if (!ccc->value[0])
+	if (!ccc->value)
 		return;
 
 	ccc_cb = queue_find(db->ccc_callbacks, ccc_cb_match_handle,
@@ -340,7 +340,7 @@ static void att_disconnected(int err, void *user_data)
 		ccc = find_ccc_state(state, handle);
 		if (ccc)
 			device_store_svc_chng_ccc(device, state->bdaddr_type,
-								ccc->value[0]);
+								ccc->value);
 
 		return;
 	}
@@ -872,7 +872,7 @@ static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
 
 	DBG("CCC read called for handle: 0x%04x", handle);
 
-	if (offset > 2) {
+	if (offset) {
 		ecode = BT_ATT_ERROR_INVALID_OFFSET;
 		goto done;
 	}
@@ -883,8 +883,8 @@ static void gatt_ccc_read_cb(struct gatt_db_attribute *attrib,
 		goto done;
 	}
 
-	len = 2 - offset;
-	value = len ? &ccc->value[offset] : NULL;
+	len = sizeof(ccc->value);
+	value = (void *) &ccc->value;
 
 done:
 	gatt_db_attribute_read_result(attrib, id, ecode, value, len);
@@ -969,14 +969,14 @@ static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
 	struct btd_gatt_database *database = user_data;
 	struct ccc_state *ccc;
 	struct ccc_cb_data *ccc_cb;
-	uint16_t handle;
+	uint16_t handle, val;
 	uint8_t ecode = 0;
 
 	handle = gatt_db_attribute_get_handle(attrib);
 
 	DBG("CCC write called for handle: 0x%04x", handle);
 
-	if (!value || len != 2) {
+	if (!value || len > 2) {
 		ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
 		goto done;
 	}
@@ -999,8 +999,13 @@ static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
 		goto done;
 	}
 
+	if (len == 1)
+		val = *value;
+	else
+		val = get_le16(value);
+
 	/* If value is identical, then just succeed */
-	if (ccc->value[0] == value[0] && ccc->value[1] == value[1])
+	if (val == ccc->value)
 		goto done;
 
 	if (ccc_cb->callback) {
@@ -1018,10 +1023,8 @@ static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
 			pending_op_free(op);
 	}
 
-	if (!ecode) {
-		ccc->value[0] = value[0];
-		ccc->value[1] = value[1];
-	}
+	if (!ecode)
+		ccc->value = val;
 
 done:
 	gatt_db_attribute_write_result(attrib, id, ecode);
@@ -1309,7 +1312,7 @@ static void send_notification_to_device(void *data, void *user_data)
 	if (!ccc)
 		return;
 
-	if (!ccc->value[0] || (notify->conf && !(ccc->value[0] & 0x02)))
+	if (!ccc->value || (notify->conf && !(ccc->value & 0x0002)))
 		return;
 
 	device = btd_adapter_get_device(notify->database->adapter,
@@ -3709,7 +3712,7 @@ static void restore_ccc(struct btd_gatt_database *database,
 
 	ccc = new0(struct ccc_state, 1);
 	ccc->handle = gatt_db_attribute_get_handle(database->svc_chngd_ccc);
-	memcpy(ccc->value, &value, sizeof(ccc->value));
+	ccc->value = value;
 	queue_push_tail(dev_state->ccc_states, ccc);
 }
 
-- 
2.21.0




[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