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