summaryrefslogtreecommitdiff
path: root/src/gatt-database.c
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2019-09-06 14:52:34 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2019-09-11 16:34:06 +0300
commite60a6b7d9d0fa55fda5cd0457f6c763078949d87 (patch)
treeea02ecb94ad7046d80a0f0da41e6162c97da0f86 /src/gatt-database.c
parentafe196816af33c1e6c0f0d5fd09ebf8e796830ce (diff)
downloadbluez-e60a6b7d9d0fa55fda5cd0457f6c763078949d87.tar.gz
gatt: Fix assuming writes to CCC will always contain 2 bytes
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.'
Diffstat (limited to 'src/gatt-database.c')
-rw-r--r--src/gatt-database.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/src/gatt-database.c b/src/gatt-database.c
index d90927559..2bae8711a 100644
--- a/src/gatt-database.c
+++ b/src/gatt-database.c
@@ -192,7 +192,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 {
@@ -310,7 +310,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,
@@ -346,7 +346,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;
}
@@ -873,7 +873,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;
}
@@ -884,8 +884,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);
@@ -970,14 +970,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;
}
@@ -1000,8 +1000,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) {
@@ -1019,10 +1024,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);
@@ -1274,7 +1277,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,
@@ -3647,7 +3650,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);
}