Linux-Bluetooth Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH BlueZ] gatt: Fix assuming writes to CCC will always contain 2 bytes
@ 2019-09-06 12:40 Luiz Augusto von Dentz
  0 siblings, 0 replies; only message in thread
From: Luiz Augusto von Dentz @ 2019-09-06 12:40 UTC (permalink / raw)
  To: linux-bluetooth

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

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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, back to index

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-06 12:40 [PATCH BlueZ] gatt: Fix assuming writes to CCC will always contain 2 bytes Luiz Augusto von Dentz

Linux-Bluetooth Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-bluetooth/0 linux-bluetooth/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-bluetooth linux-bluetooth/ https://lore.kernel.org/linux-bluetooth \
		linux-bluetooth@vger.kernel.org linux-bluetooth@archiver.kernel.org
	public-inbox-index linux-bluetooth


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-bluetooth


AGPL code for this site: git clone https://public-inbox.org/ public-inbox