gatt: Fix assuming writes to CCC will always contain 2 bytes
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 6 Sep 2019 11:52:34 +0000 (14:52 +0300)
committerhimanshu <h.himanshu@samsung.com>
Tue, 11 Feb 2020 08:57:59 +0000 (14:27 +0530)
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.'

Change-Id: I845531fbd44262a5ab29c2353f63c16ed98480bc
Signed-off-by: himanshu <h.himanshu@samsung.com>
src/gatt-database.c

index eb268e3..7f2845b 100644 (file)
@@ -195,7 +195,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 {
@@ -323,7 +323,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,
@@ -359,7 +359,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;
        }
@@ -1019,7 +1019,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;
        }
@@ -1030,8 +1030,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);
@@ -1116,7 +1116,7 @@ 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;
 
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
@@ -1128,7 +1128,7 @@ static void gatt_ccc_write_cb(struct gatt_db_attribute *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;
        }
@@ -1158,8 +1158,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) {
@@ -1177,10 +1182,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);
@@ -1630,7 +1633,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,
@@ -4232,7 +4235,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);
 }