15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2009-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  this file contains GATT database building and query functions
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_target.h"
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_trace.h"
287fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta#include "bt_utils.h"
295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdio.h>
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
32911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btm_int.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "gatt_int.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_api.h"
35d7ffd64accbd50a27289a388856e56244ccbb5daMyles Watson#include "osi/include/osi.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
37ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/*******************************************************************************
389ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *             L O C A L    F U N C T I O N     P R O T O T Y P E S            *
39ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
40ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskistatic tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid,
41ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                       tGATT_PERM perm);
42911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGATT_STATUS gatts_send_app_read_request(
43911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tGATT_TCB* p_tcb, uint8_t op_code, uint16_t handle, uint16_t offset,
44911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type);
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
46ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski/**
47ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski * Initialize a memory space to be a service database.
48ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski */
49ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskivoid gatts_init_service_db(tGATT_SVC_DB& db, tBT_UUID* p_service, bool is_pri,
50911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           uint16_t s_hdl, uint16_t num_handle) {
51ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  db.attr_list.reserve(num_handle);
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
53ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  GATT_TRACE_DEBUG("%s: s_hdl= %d num_handle= %d", __func__, s_hdl, num_handle);
545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
55911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* update service database information */
56ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  db.next_handle = s_hdl;
57ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  db.end_handle = s_hdl + num_handle;
585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
59ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  /* add service declration record */
60ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tBT_UUID uuid = {LEN_UUID_16, {0}};
61ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  uuid.uu.uuid16 = is_pri ? GATT_UUID_PRI_SERVICE : GATT_UUID_SEC_SERVICE;
62ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ);
63ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.p_value.reset((tGATT_ATTR_VALUE*)(new tBT_UUID));
64ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  memcpy(&attr.p_value->uuid, p_service, sizeof(tBT_UUID));
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
67911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontBT_UUID* gatts_get_service_uuid(tGATT_SVC_DB* p_db) {
68ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (!p_db || p_db->attr_list.empty()) {
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("service DB empty");
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return NULL;
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
72ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    return &p_db->attr_list[0].p_value->uuid;
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
76ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski/** Check attribute readability. Returns status of operation. */
77ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskistatic tGATT_STATUS gatts_check_attr_readability(const tGATT_ATTR& attr,
78d35a648d39710bbc5ac59f8add85166455af5af7Myles Watson                                                 UNUSED_ATTR uint16_t offset,
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 bool read_long,
805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                                 tGATT_SEC_FLAG sec_flag,
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 uint8_t key_size) {
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t min_key_size;
83ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_PERM perm = attr.permission;
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12));
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (min_key_size != 0) {
87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    min_key_size += 6;
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!(perm & GATT_READ_ALLOWED)) {
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("%s: GATT_READ_NOT_PERMIT", __func__);
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_READ_NOT_PERMIT;
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((perm & GATT_READ_AUTH_REQUIRED) &&
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      !(sec_flag & BTM_SEC_FLAG_ENCRYPTED)) {
98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION", __func__);
99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_INSUF_AUTHENTICATION;
100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((perm & GATT_READ_MITM_REQUIRED) &&
103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) {
104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION: MITM Required", __func__);
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_INSUF_AUTHENTICATION;
106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((perm & GATT_READ_ENCRYPTED_REQUIRED) &&
109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("%s: GATT_INSUF_ENCRYPTION", __func__);
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_INSUF_ENCRYPTION;
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((perm & GATT_READ_ENCRYPTED_REQUIRED) &&
115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) {
116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    GATT_TRACE_ERROR("%s: GATT_INSUF_KEY_SIZE", __func__);
117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_INSUF_KEY_SIZE;
118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
120ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (read_long && attr.uuid.len == LEN_UUID_16) {
121ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    switch (attr.uuid.uu.uuid16) {
122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_PRI_SERVICE:
123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_SEC_SERVICE:
124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_CHAR_DECLARE:
125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_INCLUDE_SERVICE:
126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_CHAR_EXT_PROP:
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_CHAR_CLIENT_CONFIG:
128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_CHAR_SRVR_CONFIG:
129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case GATT_UUID_CHAR_PRESENT_FORMAT:
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        GATT_TRACE_ERROR("%s: GATT_NOT_LONG", __func__);
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return GATT_NOT_LONG;
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      default:
134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return GATT_SUCCESS;
1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         read_attr_value
144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Utility function to read an attribute value.
146ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_attr: pointer to the attribute to read.
148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  offset: read offset.
149ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_value: output parameter to carry out the attribute value.
150ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_len: output parameter to carry out the attribute length.
151ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  read_long: this is a read blob request.
152ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  mtu: MTU
153ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  sec_flag: current link security status.
154ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  key_size: encryption key size.
155ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
156ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          status of operation.
157ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
158ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
159ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskistatic tGATT_STATUS read_attr_value(tGATT_ATTR& attr16, uint16_t offset,
160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                    uint8_t** p_data, bool read_long,
161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                    uint16_t mtu, uint16_t* p_len,
162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                    tGATT_SEC_FLAG sec_flag, uint8_t key_size) {
163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len = 0, uuid16 = 0;
164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p = *p_data;
165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  GATT_TRACE_DEBUG(
167ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      "%s: uuid=0x%04x perm=0x%02x sec_flag=0x%x offset=%d read_long=%d",
168ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      __func__, attr16.uuid, attr16.permission, sec_flag, offset, read_long);
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
170ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_STATUS status = gatts_check_attr_readability(attr16, offset, read_long,
171ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                                     sec_flag, key_size);
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (status != GATT_SUCCESS) return status;
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
175ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (attr16.uuid.len == LEN_UUID_16) uuid16 = attr16.uuid.uu.uuid16;
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  status = GATT_NO_RESOURCES;
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (uuid16 == GATT_UUID_PRI_SERVICE || uuid16 == GATT_UUID_SEC_SERVICE) {
180ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    len = attr16.p_value->uuid.len;
181ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if (mtu >= attr16.p_value->uuid.len) {
182ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      gatt_build_uuid_to_stream(&p, attr16.p_value->uuid);
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      status = GATT_SUCCESS;
184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (uuid16 == GATT_UUID_CHAR_DECLARE) {
186ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    tGATT_ATTR* val_attr = &attr16 + 1;
187ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    len = (val_attr->uuid.len == LEN_UUID_16) ? 5 : 19;
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (mtu >= len) {
190ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      UINT8_TO_STREAM(p, attr16.p_value->char_decl.property);
191ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      UINT16_TO_STREAM(p, attr16.p_value->char_decl.char_val_handle);
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
193ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      if (val_attr->uuid.len == LEN_UUID_16) {
194ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        UINT16_TO_STREAM(p, val_attr->uuid.uu.uuid16);
195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* convert a 32bits UUID to 128 bits */
197ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      else if (val_attr->uuid.len == LEN_UUID_32) {
198ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        gatt_convert_uuid32_to_uuid128(p, val_attr->uuid.uu.uuid32);
199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p += LEN_UUID_128;
200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
201ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        ARRAY_TO_STREAM(p, val_attr->uuid.uu.uuid128, LEN_UUID_128);
202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      status = GATT_SUCCESS;
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (uuid16 == GATT_UUID_INCLUDE_SERVICE) {
207ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16)
208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      len = 6;
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      len = 4;
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (mtu >= len) {
213ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      UINT16_TO_STREAM(p, attr16.p_value->incl_handle.s_handle);
214ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      UINT16_TO_STREAM(p, attr16.p_value->incl_handle.e_handle);
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
216ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16) {
217ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        UINT16_TO_STREAM(p, attr16.p_value->incl_handle.service_type.uu.uuid16);
218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      status = GATT_SUCCESS;
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else /* characteristic description or characteristic value */
222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    status = GATT_PENDING;
224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  *p_len = len;
227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  *p_data = p;
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
232ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
233ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_db_read_attr_value_by_type
234ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
235ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Query attribute value by attribute type.
236ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
237ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_db: pointer to the attribute database.
238ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_rsp: Read By type response data.
239ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  s_handle: starting handle of the range we are looking for.
240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  e_handle: ending handle of the range we are looking for.
241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  type: Attribute type.
242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  mtu: MTU.
243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  sec_flag: current link security status.
244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  key_size: encryption key size.
245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of the operation.
247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
249911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_db_read_attr_value_by_type(
250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tGATT_TCB* p_tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp,
251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t s_handle, uint16_t e_handle, tBT_UUID type, uint16_t* p_len,
252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id,
253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t* p_cur_handle) {
254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tGATT_STATUS status = GATT_NOT_FOUND;
255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len = 0;
256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p = (uint8_t*)(p_rsp + 1) + p_rsp->len + L2CAP_MIN_OFFSET;
257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
258ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (p_db) {
259ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    for (tGATT_ATTR& attr : p_db->attr_list) {
260ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      tBT_UUID attr_uuid = attr.uuid;
261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
262ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      if (attr.handle >= s_handle && gatt_uuid_compare(type, attr_uuid)) {
263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (*p_len <= 2) {
264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          status = GATT_NO_RESOURCES;
265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
2675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
268ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        UINT16_TO_STREAM(p, attr.handle);
269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
270ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        status = read_attr_value(attr, 0, &p, false, (uint16_t)(*p_len - 2),
271ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                 &len, sec_flag, key_size);
272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (status == GATT_PENDING) {
274ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          status = gatts_send_app_read_request(p_tcb, op_code, attr.handle, 0,
275ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                               trans_id, attr.gatt_type);
276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* one callback at a time */
278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        } else if (status == GATT_SUCCESS) {
280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_rsp->offset == 0) p_rsp->offset = len + 2;
281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_rsp->offset == len + 2) {
283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_rsp->len += (len + 2);
284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            *p_len -= (len + 2);
285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          } else {
286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            GATT_TRACE_ERROR("format mismatch");
287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            status = GATT_NO_RESOURCES;
288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            break;
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        } else {
291ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          *p_cur_handle = attr.handle;
292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
2935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
298d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BLE_DELAY_REQUEST_ENC == TRUE)
299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t flag = 0;
300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (BTM_GetSecurityFlags(p_tcb->peer_bda, &flag)) {
301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_tcb->att_lcid == L2CAP_ATT_CID) && (status == GATT_PENDING) &&
302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (type.uu.uuid16 == GATT_UUID_GAP_DEVICE_NAME)) {
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((flag & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_FLAG_ENCRYPTED)) ==
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          BTM_SEC_LINK_KEY_KNOWN) {
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        tACL_CONN* p = btm_bda_to_acl(p_tcb->peer_bda, BT_TRANSPORT_LE);
306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p != NULL) && (p->link_role == BTM_ROLE_MASTER))
307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          btm_ble_set_encryption(p_tcb->peer_bda, BTM_BLE_SEC_ENCRYPT,
308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                 p->link_role);
309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3105702d5c6197404823f5e594764e2c67cf2416da1Zhihai Xu    }
311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3125702d5c6197404823f5e594764e2c67cf2416da1Zhihai Xu#endif
313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
3145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
316ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski/**
317ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski * This function adds an included service into a database.
318ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
319ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski * Parameter        db: database pointer.
320ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  inc_srvc_type: included service type.
321ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
322ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of the operation.
323ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
324ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski */
325ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskiuint16_t gatts_add_included_service(tGATT_SVC_DB& db, uint16_t s_handle,
326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                    uint16_t e_handle, tBT_UUID service) {
327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_INCLUDE_SERVICE}};
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
329ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  GATT_TRACE_DEBUG("%s: s_hdl = 0x%04x e_hdl = 0x%04x uuid = 0x%04x", __func__,
330ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                   s_handle, e_handle, service.uu.uuid16);
3315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (service.len == 0 || s_handle == 0 || e_handle == 0) {
333ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: Illegal Params.", __func__);
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
337ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ);
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
339ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_INCL_SRVC));
340ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.p_value->incl_handle.s_handle = s_handle;
341ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.p_value->incl_handle.e_handle = e_handle;
342ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  memcpy(&attr.p_value->incl_handle.service_type, &service, sizeof(tBT_UUID));
3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
344ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  return attr.handle;
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
348ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
349ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_add_characteristic
350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function add a characteristics and its descriptor into
352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  a servce identified by the service database pointer.
353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
354ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski * Parameter        db: database.
355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  perm: permission (authentication and key size requirements)
356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  property: property of the characteristic.
357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_char: characteristic value information.
358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of te operation.
360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
362ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskiuint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm,
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  tGATT_CHAR_PROP property,
364ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                  tBT_UUID& char_uuid) {
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}};
366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  GATT_TRACE_DEBUG("%s: perm=0x%0x property=0x%0x", __func__, perm, property);
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
369ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR& char_decl = allocate_attr_in_db(db, uuid, GATT_PERM_READ);
370ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR& char_val = allocate_attr_in_db(db, char_uuid, perm);
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
372ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  char_decl.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_CHAR_DECL));
373ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  char_decl.p_value->char_decl.property = property;
374ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  char_decl.p_value->char_decl.char_val_handle = char_val.handle;
375ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  char_val.gatt_type = BTGATT_DB_CHARACTERISTIC;
376ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  return char_val.handle;
3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatt_convertchar_descr_type
382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3839ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Convert a char descript UUID into descriptor type.
384ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
385ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          descriptor type.
386ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
387ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t gatt_convertchar_descr_type(tBT_UUID* p_descr_uuid) {
389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_UUID std_descr = {LEN_UUID_16, {GATT_UUID_CHAR_EXT_PROP}};
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid))
392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_DESCR_EXT_DSCPTOR;
3935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  std_descr.uu.uuid16++;
395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid))
396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_DESCR_USER_DSCPTOR;
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  std_descr.uu.uuid16++;
399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_CLT_CONFIG;
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  std_descr.uu.uuid16++;
402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_SVR_CONFIG;
4035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  std_descr.uu.uuid16++;
405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid))
406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_DESCR_PRES_FORMAT;
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  std_descr.uu.uuid16++;
409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid))
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_DESCR_AGGR_FORMAT;
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  std_descr.uu.uuid16++;
413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (gatt_uuid_compare(std_descr, *p_descr_uuid))
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return GATT_DESCR_VALID_RANGE;
4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return GATT_DESCR_UNKNOWN;
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
420ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
421ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_add_char_descr
422ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
423ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function add a characteristics descriptor.
424ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
425ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_db: database pointer.
426ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  perm: characteristic descriptor permission type.
427ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  char_dscp_tpye: the characteristic descriptor masks.
428ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_dscp_params: characteristic descriptors values.
429ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
430ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of the operation.
431ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
432ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
433ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskiuint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm,
434ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                              tBT_UUID& descr_uuid) {
435ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  GATT_TRACE_DEBUG("gatts_add_char_descr uuid=0x%04x", descr_uuid.uu.uuid16);
436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Add characteristic descriptors */
438ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR& char_dscptr = allocate_attr_in_db(db, descr_uuid, perm);
439ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  char_dscptr.gatt_type = BTGATT_DB_DESCRIPTOR;
440ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  return char_dscptr.handle;
4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
443ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************/
4445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Service Attribute Database Query Utility Functions */
445ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************/
446ad3ab46b727119f3f7233e392d3d628909234e61Jakub PawlowskitGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) {
447ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (!p_db) return nullptr;
448ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
449ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  for (auto& attr : p_db->attr_list) {
450ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if (attr.handle == handle) return &attr;
451ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if (attr.handle > handle) return nullptr;
452ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  }
453ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
454ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  return nullptr;
455ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski}
456ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
4575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
458ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
459ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_read_attr_value_by_handle
460ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
461ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Query attribute value by attribute handle.
462ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
463ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_db: pointer to the attribute database.
464ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  handle: Attribute handle to read.
465ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  offset: Read offset.
466ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_value: output parameter to carry out the attribute value.
467ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_len: output parameter as attribute length read.
468ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  read_long: this is a read blob request.
469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  mtu: MTU.
470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  sec_flag: current link security status.
471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  key_size: encryption key size
472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of operation.
474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
476911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_read_attr_value_by_handle(
477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tGATT_TCB* p_tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle,
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu,
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) {
480ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle);
481ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (!p_attr) return GATT_NOT_FOUND;
482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
483ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  uint8_t* pp = p_value;
484ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_STATUS status = read_attr_value(*p_attr, offset, &pp,
485ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                        (bool)(op_code == GATT_REQ_READ_BLOB),
486ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                        mtu, p_len, sec_flag, key_size);
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
488ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (status == GATT_PENDING) {
489ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = gatts_send_app_read_request(p_tcb, op_code, p_attr->handle, offset,
490ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                         trans_id, p_attr->gatt_type);
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
496ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
497ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_read_attr_perm_check
498ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
499ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Check attribute readability.
500ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
501ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_db: pointer to the attribute database.
502ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  handle: Attribute handle to read.
503ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  offset: Read offset.
504ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_value: output parameter to carry out the attribute value.
505ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_len: output parameter as attribute length read.
506ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  read_long: this is a read blob request.
507ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  mtu: MTU.
508ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  sec_flag: current link security status.
509ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  key_size: encryption key size
510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of operation.
512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
514911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long,
515d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen                                        uint16_t handle,
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                                        tGATT_SEC_FLAG sec_flag,
517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                        uint8_t key_size) {
518ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle);
519ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (!p_attr) return GATT_NOT_FOUND;
5205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
521ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  return gatts_check_attr_readability(*p_attr, 0, is_long, sec_flag, key_size);
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
523ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
525ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_write_attr_perm_check
527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Write attribute value into database.
529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_db: pointer to the attribute database.
531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  op_code:op code of this write.
532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  handle: handle of the attribute to write.
533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  offset: Write offset if write op code is write blob.
534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_data: Attribute value to write.
535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  len: attribute data length.
536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  sec_flag: current link security status.
537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  key_size: encryption key size
538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Status of the operation.
540ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
542911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code,
543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         uint16_t handle, uint16_t offset,
544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         uint8_t* p_data, uint16_t len,
545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         tGATT_SEC_FLAG sec_flag,
546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         uint8_t key_size) {
547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  GATT_TRACE_DEBUG(
548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "%s: op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x "
549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "key_size=%d",
550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      __func__, op_code, handle, offset, len, sec_flag, key_size);
551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
552ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle);
553ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (!p_attr) return GATT_NOT_FOUND;
554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
555ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_PERM perm = p_attr->permission;
556ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  uint16_t min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12));
557ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (min_key_size != 0) {
558ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    min_key_size += 6;
559ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  }
560ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  GATT_TRACE_DEBUG("%s: p_attr->permission =0x%04x min_key_size==0x%04x",
561ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                   __func__, p_attr->permission, min_key_size);
562ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
563ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE) &&
564ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      (perm & GATT_WRITE_SIGNED_PERM)) {
565ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    /* use the rules for the mixed security see section 10.2.3*/
566ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    /* use security mode 1 level 2 when the following condition follows */
567ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    /* LE security mode 2 level 1 and LE security mode 1 level 2 */
568ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if ((perm & GATT_PERM_WRITE_SIGNED) && (perm & GATT_PERM_WRITE_ENCRYPTED)) {
569ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      perm = GATT_PERM_WRITE_ENCRYPTED;
570ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    }
571ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    /* use security mode 1 level 3 when the following condition follows */
572ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    /* LE security mode 2 level 2 and security mode 1 and LE */
573ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    else if (((perm & GATT_PERM_WRITE_SIGNED_MITM) &&
574ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski              (perm & GATT_PERM_WRITE_ENCRYPTED)) ||
575ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             /* LE security mode 2 and security mode 1 level 3 */
576ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             ((perm & GATT_WRITE_SIGNED_PERM) &&
577ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski              (perm & GATT_PERM_WRITE_ENC_MITM))) {
578ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      perm = GATT_PERM_WRITE_ENC_MITM;
579ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    }
580ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  }
581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
582ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_STATUS status = GATT_NOT_FOUND;
583ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM)) {
584ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_WRITE_NOT_PERMIT;
585ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_DEBUG("%s: sign cmd write not allowed", __func__);
586ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  }
587ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if ((op_code == GATT_SIGN_CMD_WRITE) &&
588ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      (sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
589ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_INVALID_PDU;
590ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: Error!! sign cmd write sent on a encypted link",
591ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                     __func__);
592ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  } else if (!(perm & GATT_WRITE_ALLOWED)) {
593ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_WRITE_NOT_PERMIT;
594ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: GATT_WRITE_NOT_PERMIT", __func__);
595ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  }
596ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  /* require authentication, but not been authenticated */
597ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  else if ((perm & GATT_WRITE_AUTH_REQUIRED) &&
598ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski           !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED)) {
599ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_INSUF_AUTHENTICATION;
600ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION", __func__);
601ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  } else if ((perm & GATT_WRITE_MITM_REQUIRED) &&
602ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) {
603ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_INSUF_AUTHENTICATION;
604ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: GATT_INSUF_AUTHENTICATION: MITM required", __func__);
605ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  } else if ((perm & GATT_WRITE_ENCRYPTED_PERM) &&
606ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) {
607ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_INSUF_ENCRYPTION;
608ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: GATT_INSUF_ENCRYPTION", __func__);
609ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  } else if ((perm & GATT_WRITE_ENCRYPTED_PERM) &&
610ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             (sec_flag & GATT_SEC_FLAG_ENCRYPTED) &&
611ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             (key_size < min_key_size)) {
612ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_INSUF_KEY_SIZE;
613ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR("%s: GATT_INSUF_KEY_SIZE", __func__);
614ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  }
615ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  /* LE security mode 2 attribute  */
616ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE &&
617ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski           !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) &&
618ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski           (perm & GATT_WRITE_ALLOWED) == 0) {
619ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    status = GATT_INSUF_AUTHENTICATION;
620ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    GATT_TRACE_ERROR(
621ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        "%s: GATT_INSUF_AUTHENTICATION: LE security mode 2 required", __func__);
622ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  } else /* writable: must be char value declaration or char descritpors
623ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski            */
624ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  {
625ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    uint16_t max_size = 0;
626ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
627ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if (p_attr->uuid.len == LEN_UUID_16) {
628ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      switch (p_attr->uuid.uu.uuid16) {
629ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_PRESENT_FORMAT: /* should be readable only */
630ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_EXT_PROP:       /* should be readable only */
631ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_AGG_FORMAT:     /* should be readable only */
632ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_VALID_RANGE:
633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          status = GATT_WRITE_NOT_PERMIT;
634ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          break;
635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
636ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_CLIENT_CONFIG:
637ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        /* fall through */
638ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_SRVR_CONFIG:
639ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          max_size = 2;
640ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        /* fall through */
641ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        case GATT_UUID_CHAR_DESCRIPTION:
642ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        default: /* any other must be character value declaration */
643ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          status = GATT_SUCCESS;
644ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          break;
645ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      }
646ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    } else if (p_attr->uuid.len == LEN_UUID_128 ||
647ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski               p_attr->uuid.len == LEN_UUID_32) {
648ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      status = GATT_SUCCESS;
649ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    } else {
650ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      status = GATT_INVALID_PDU;
651ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    }
652ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski
653ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    if (p_data == NULL && len > 0) {
654ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      status = GATT_INVALID_PDU;
655ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    }
656ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    /* these attribute does not allow write blob */
657ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    else if ((p_attr->uuid.len == LEN_UUID_16) &&
658ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski             (p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG ||
659ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski              p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_SRVR_CONFIG)) {
660ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      if (op_code == GATT_REQ_PREPARE_WRITE &&
661ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski          offset != 0) /* does not allow write blob */
662ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      {
663ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        status = GATT_NOT_LONG;
664ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        GATT_TRACE_ERROR("%s: GATT_NOT_LONG", __func__);
665ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      } else if (len != max_size) /* data does not match the required format */
666ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      {
667ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        status = GATT_INVALID_ATTR_LEN;
668ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        GATT_TRACE_ERROR("%s: GATT_INVALID_PDU", __func__);
669ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      } else {
670ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski        status = GATT_SUCCESS;
671ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski      }
6725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
6765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void uuid_to_str(const tBT_UUID bt_uuid, char* str_buf, size_t buf_len) {
679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (bt_uuid.len == LEN_UUID_16) {
680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    snprintf(str_buf, buf_len, "0x%04x", bt_uuid.uu.uuid16);
681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (bt_uuid.len == LEN_UUID_32) {
682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    snprintf(str_buf, buf_len, "0x%08x", bt_uuid.uu.uuid32);
683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (bt_uuid.len == LEN_UUID_128) {
684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    int x = snprintf(str_buf, buf_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-",
685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    snprintf(&str_buf[x], buf_len - x, "%02x%02x-%02x%02x%02x%02x%02x%02x",
690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    snprintf(str_buf, buf_len, "Unknown (len=%d)", bt_uuid.len);
696c88b20a599a52228c7b29d03751b7f13868d417aJakub Pawlowski}
697c88b20a599a52228c7b29d03751b7f13868d417aJakub Pawlowski
698ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski/**
699ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Allocate a memory space for a new attribute, and link this
700ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  attribute into the database attribute list.
701ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
702ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
703ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter        p_db    : database pointer.
704ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski *                  uuid:     attribute UUID
705ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
706ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to the newly allocated attribute.
707ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
708ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski */
709ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowskistatic tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid,
710ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski                                       tGATT_PERM perm) {
711ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  if (db.next_handle >= db.end_handle) {
712ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    LOG(FATAL) << __func__
713ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski               << " wrong number of handles! handle_max = " << +db.end_handle
714ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski               << ", next_handle = " << +db.next_handle;
715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
717ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  db.attr_list.emplace_back();
718ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_ATTR& attr = db.attr_list.back();
719ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.handle = db.next_handle++;
720ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.uuid = uuid;
721ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  attr.permission = perm;
7225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  char uuid_str[37];
724ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  uuid_to_str(attr.uuid, uuid_str, sizeof(uuid_str));
7255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
726ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  return attr;
7275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
730ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
731ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         gatts_send_app_read_request
732ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
733ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Send application read request callback
734ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          status of operation.
736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGATT_STATUS gatts_send_app_read_request(
739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tGATT_TCB* p_tcb, uint8_t op_code, uint16_t handle, uint16_t offset,
740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) {
741ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  tGATT_SRV_LIST_ELEM& el = *gatt_sr_find_i_rcb_by_handle(handle);
742ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski  uint16_t conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, el.gatt_if);
743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (trans_id == 0) {
745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    trans_id = gatt_sr_enqueue_cmd(p_tcb, op_code, handle);
746ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    gatt_sr_update_cback_cnt(p_tcb, el.gatt_if, true, true);
747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (trans_id != 0) {
750ad3ab46b727119f3f7233e392d3d628909234e61Jakub Pawlowski    tGATTS_DATA sr_data;
751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    memset(&sr_data, 0, sizeof(tGATTS_DATA));
752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    sr_data.read_req.handle = handle;
754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    sr_data.read_req.is_long = (bool)(op_code == GATT_REQ_READ_BLOB);
755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    sr_data.read_req.offset = offset;
756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint8_t opcode;
758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (gatt_type == BTGATT_DB_DESCRIPTOR) {
759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      opcode = GATTS_REQ_TYPE_READ_DESCRIPTOR;
760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) {
761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      opcode = GATTS_REQ_TYPE_READ_CHARACTERISTIC;
762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      GATT_TRACE_ERROR(
764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "%s: Attempt to read attribute that's not tied with"
765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          " characteristic or descriptor value.",
766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          __func__);
767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return GATT_ERROR;
7685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
7695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data);
771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (tGATT_STATUS)GATT_PENDING;
772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (tGATT_STATUS)GATT_BUSY; /* max pending command, application error */
7745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
775