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 37d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowskiusing base::StringPrintf; 38ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************* 399ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * L O C A L F U N C T I O N P R O T O T Y P E S * 40ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 416395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskistatic tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid, 426395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_PERM perm); 43911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGATT_STATUS gatts_send_app_read_request( 44f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset, 45911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type); 465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 476395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski/** 486395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski * Initialize a memory space to be a service database. 496395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski */ 506395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskivoid gatts_init_service_db(tGATT_SVC_DB& db, tBT_UUID* p_service, bool is_pri, 51911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t s_hdl, uint16_t num_handle) { 526395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski db.attr_list.reserve(num_handle); 535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 54d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << StringPrintf("%s: s_hdl= %d num_handle= %d", __func__, s_hdl, 55d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski num_handle); 565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 57911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* update service database information */ 586395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski db.next_handle = s_hdl; 596395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski db.end_handle = s_hdl + num_handle; 605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 616395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* add service declration record */ 626395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tBT_UUID uuid = {LEN_UUID_16, {0}}; 636395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski uuid.uu.uuid16 = is_pri ? GATT_UUID_PRI_SERVICE : GATT_UUID_SEC_SERVICE; 646395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ); 656395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.p_value.reset((tGATT_ATTR_VALUE*)(new tBT_UUID)); 666395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski memcpy(&attr.p_value->uuid, p_service, sizeof(tBT_UUID)); 675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 69911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontBT_UUID* gatts_get_service_uuid(tGATT_SVC_DB* p_db) { 706395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (!p_db || p_db->attr_list.empty()) { 71d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << "service DB empty"; 72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return NULL; 73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 746395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return &p_db->attr_list[0].p_value->uuid; 75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 786395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski/** Check attribute readability. Returns status of operation. */ 796395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskistatic tGATT_STATUS gatts_check_attr_readability(const tGATT_ATTR& attr, 80d35a648d39710bbc5ac59f8add85166455af5af7Myles Watson UNUSED_ATTR uint16_t offset, 81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bool read_long, 825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tGATT_SEC_FLAG sec_flag, 83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t key_size) { 84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t min_key_size; 856395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_PERM perm = attr.permission; 86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12)); 88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (min_key_size != 0) { 89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson min_key_size += 6; 90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!(perm & GATT_READ_ALLOWED)) { 93d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_READ_NOT_PERMIT"; 94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_READ_NOT_PERMIT; 95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((perm & GATT_READ_AUTH_REQUIRED) && 98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) && 99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(sec_flag & BTM_SEC_FLAG_ENCRYPTED)) { 100d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION"; 101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_INSUF_AUTHENTICATION; 102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((perm & GATT_READ_MITM_REQUIRED) && 105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { 106d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION: MITM Required"; 107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_INSUF_AUTHENTICATION; 108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((perm & GATT_READ_ENCRYPTED_REQUIRED) && 111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { 112d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_ENCRYPTION"; 113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_INSUF_ENCRYPTION; 114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((perm & GATT_READ_ENCRYPTED_REQUIRED) && 117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) { 118d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_KEY_SIZE"; 119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_INSUF_KEY_SIZE; 120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1226395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (read_long && attr.uuid.len == LEN_UUID_16) { 1236395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski switch (attr.uuid.uu.uuid16) { 124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_PRI_SERVICE: 125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_SEC_SERVICE: 126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_CHAR_DECLARE: 127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_INCLUDE_SERVICE: 128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_CHAR_EXT_PROP: 129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_CHAR_CLIENT_CONFIG: 130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_CHAR_SRVR_CONFIG: 131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson case GATT_UUID_CHAR_PRESENT_FORMAT: 132d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_NOT_LONG"; 133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_NOT_LONG; 134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson default: 136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_SUCCESS; 1415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 1425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function read_attr_value 146ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Utility function to read an attribute value. 148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 149ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_attr: pointer to the attribute to read. 150ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * offset: read offset. 151ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_value: output parameter to carry out the attribute value. 152ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_len: output parameter to carry out the attribute length. 153ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * read_long: this is a read blob request. 154ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * mtu: MTU 155ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * sec_flag: current link security status. 156ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * key_size: encryption key size. 157ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 158ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns status of operation. 159ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 160ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1616395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskistatic tGATT_STATUS read_attr_value(tGATT_ATTR& attr16, uint16_t offset, 162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t** p_data, bool read_long, 163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t mtu, uint16_t* p_len, 164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGATT_SEC_FLAG sec_flag, uint8_t key_size) { 165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t len = 0, uuid16 = 0; 166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p = *p_data; 167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 168d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) 169d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski << __func__ 170d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski << StringPrintf( 171d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski " uuid=0x%04x perm=0x%02x sec_flag=0x%x offset=%d read_long=%d", 172d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski attr16.uuid.uu.uuid16, attr16.permission, sec_flag, offset, 173d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski read_long); 174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1756395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_STATUS status = gatts_check_attr_readability(attr16, offset, read_long, 1766395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski sec_flag, key_size); 177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (status != GATT_SUCCESS) return status; 179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1806395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (attr16.uuid.len == LEN_UUID_16) uuid16 = attr16.uuid.uu.uuid16; 181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_NO_RESOURCES; 183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (uuid16 == GATT_UUID_PRI_SERVICE || uuid16 == GATT_UUID_SEC_SERVICE) { 1856395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski len = attr16.p_value->uuid.len; 1866395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (mtu >= attr16.p_value->uuid.len) { 1876395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski gatt_build_uuid_to_stream(&p, attr16.p_value->uuid); 188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_SUCCESS; 189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (uuid16 == GATT_UUID_CHAR_DECLARE) { 1916395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR* val_attr = &attr16 + 1; 1926395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski len = (val_attr->uuid.len == LEN_UUID_16) ? 5 : 19; 193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (mtu >= len) { 1956395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT8_TO_STREAM(p, attr16.p_value->char_decl.property); 1966395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT16_TO_STREAM(p, attr16.p_value->char_decl.char_val_handle); 197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1986395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (val_attr->uuid.len == LEN_UUID_16) { 1996395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT16_TO_STREAM(p, val_attr->uuid.uu.uuid16); 200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* convert a 32bits UUID to 128 bits */ 2026395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski else if (val_attr->uuid.len == LEN_UUID_32) { 2036395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski gatt_convert_uuid32_to_uuid128(p, val_attr->uuid.uu.uuid32); 204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p += LEN_UUID_128; 205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2066395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski ARRAY_TO_STREAM(p, val_attr->uuid.uu.uuid128, LEN_UUID_128); 207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_SUCCESS; 2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (uuid16 == GATT_UUID_INCLUDE_SERVICE) { 2126395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16) 213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len = 6; 214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson len = 4; 2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (mtu >= len) { 2186395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT16_TO_STREAM(p, attr16.p_value->incl_handle.s_handle); 2196395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT16_TO_STREAM(p, attr16.p_value->incl_handle.e_handle); 2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2216395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16) { 2226395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT16_TO_STREAM(p, attr16.p_value->incl_handle.service_type.uu.uuid16); 223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_SUCCESS; 2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else /* characteristic description or characteristic value */ 227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson { 228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_PENDING; 229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_len = len; 232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_data = p; 233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return status; 2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 237ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 238ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_db_read_attr_value_by_type 239ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Query attribute value by attribute type. 241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_db: pointer to the attribute database. 243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_rsp: Read By type response data. 244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * s_handle: starting handle of the range we are looking for. 245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * e_handle: ending handle of the range we are looking for. 246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * type: Attribute type. 247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * mtu: MTU. 248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * sec_flag: current link security status. 249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * key_size: encryption key size. 250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of the operation. 252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 254911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_db_read_attr_value_by_type( 255f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp, 256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t s_handle, uint16_t e_handle, tBT_UUID type, uint16_t* p_len, 257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id, 258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t* p_cur_handle) { 259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGATT_STATUS status = GATT_NOT_FOUND; 260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t len = 0; 261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p = (uint8_t*)(p_rsp + 1) + p_rsp->len + L2CAP_MIN_OFFSET; 262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2636395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (p_db) { 2646395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski for (tGATT_ATTR& attr : p_db->attr_list) { 2656395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tBT_UUID attr_uuid = attr.uuid; 266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2676395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (attr.handle >= s_handle && gatt_uuid_compare(type, attr_uuid)) { 268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (*p_len <= 2) { 269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_NO_RESOURCES; 270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 2736395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski UINT16_TO_STREAM(p, attr.handle); 274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 2756395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = read_attr_value(attr, 0, &p, false, (uint16_t)(*p_len - 2), 2766395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski &len, sec_flag, key_size); 277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (status == GATT_PENDING) { 279f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski status = gatts_send_app_read_request(tcb, op_code, attr.handle, 0, 2806395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski trans_id, attr.gatt_type); 281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* one callback at a time */ 283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (status == GATT_SUCCESS) { 285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_rsp->offset == 0) p_rsp->offset = len + 2; 286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_rsp->offset == len + 2) { 288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_rsp->len += (len + 2); 289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_len -= (len + 2); 290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 291d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << "format mismatch"; 292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_NO_RESOURCES; 293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 2966395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski *p_cur_handle = attr.handle; 297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 2985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 303d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BLE_DELAY_REQUEST_ENC == TRUE) 304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t flag = 0; 305f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski if (BTM_GetSecurityFlags(tcb.peer_bda, &flag)) { 306f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski if ((tcb.att_lcid == L2CAP_ATT_CID) && (status == GATT_PENDING) && 307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (type.uu.uuid16 == GATT_UUID_GAP_DEVICE_NAME)) { 308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((flag & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_FLAG_ENCRYPTED)) == 309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BTM_SEC_LINK_KEY_KNOWN) { 310f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski tACL_CONN* p = btm_bda_to_acl(tcb.peer_bda, BT_TRANSPORT_LE); 311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p != NULL) && (p->link_role == BTM_ROLE_MASTER)) 312f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski btm_ble_set_encryption(tcb.peer_bda, BTM_BLE_SEC_ENCRYPT, 313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p->link_role); 314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3155702d5c6197404823f5e594764e2c67cf2416da1Zhihai Xu } 316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3175702d5c6197404823f5e594764e2c67cf2416da1Zhihai Xu#endif 318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return status; 3195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3216395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski/** 3226395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski * This function adds an included service into a database. 323ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3246395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski * Parameter db: database pointer. 325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * inc_srvc_type: included service type. 326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of the operation. 328ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3296395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski */ 3306395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskiuint16_t gatts_add_included_service(tGATT_SVC_DB& db, uint16_t s_handle, 331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t e_handle, tBT_UUID service) { 332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_INCLUDE_SERVICE}}; 3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 334d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << StringPrintf("%s: s_hdl = 0x%04x e_hdl = 0x%04x uuid = 0x%04x", 335d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski __func__, s_handle, e_handle, service.uu.uuid16); 3365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (service.len == 0 || s_handle == 0 || e_handle == 0) { 338d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": Illegal Params."; 339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return 0; 340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3426395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ); 343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3446395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_INCL_SRVC)); 3456395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.p_value->incl_handle.s_handle = s_handle; 3466395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.p_value->incl_handle.e_handle = e_handle; 3476395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski memcpy(&attr.p_value->incl_handle.service_type, &service, sizeof(tBT_UUID)); 3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3496395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return attr.handle; 3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_add_characteristic 355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function add a characteristics and its descriptor into 357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * a servce identified by the service database pointer. 358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3596395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski * Parameter db: database. 360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * perm: permission (authentication and key size requirements) 361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * property: property of the characteristic. 362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_char: characteristic value information. 363ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 364ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of te operation. 365ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 366ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 3676395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskiuint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm, 368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGATT_CHAR_PROP property, 3696395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tBT_UUID& char_uuid) { 370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}}; 371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 372d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << StringPrintf("%s: perm=0x%0x property=0x%0x", __func__, perm, 373d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski property); 374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 3756395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR& char_decl = allocate_attr_in_db(db, uuid, GATT_PERM_READ); 3766395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR& char_val = allocate_attr_in_db(db, char_uuid, perm); 3775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3786395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski char_decl.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_CHAR_DECL)); 3796395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski char_decl.p_value->char_decl.property = property; 3806395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski char_decl.p_value->char_decl.char_val_handle = char_val.handle; 3816395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski char_val.gatt_type = BTGATT_DB_CHARACTERISTIC; 3826395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return char_val.handle; 3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 386ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 387ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatt_convertchar_descr_type 388ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3899ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Convert a char descript UUID into descriptor type. 390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns descriptor type. 392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t gatt_convertchar_descr_type(tBT_UUID* p_descr_uuid) { 395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tBT_UUID std_descr = {LEN_UUID_16, {GATT_UUID_CHAR_EXT_PROP}}; 3965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_DESCR_EXT_DSCPTOR; 3995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson std_descr.uu.uuid16++; 401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_DESCR_USER_DSCPTOR; 4035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson std_descr.uu.uuid16++; 405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_CLT_CONFIG; 4065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson std_descr.uu.uuid16++; 408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_SVR_CONFIG; 4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson std_descr.uu.uuid16++; 411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_DESCR_PRES_FORMAT; 4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson std_descr.uu.uuid16++; 415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_DESCR_AGGR_FORMAT; 4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson std_descr.uu.uuid16++; 419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_DESCR_VALID_RANGE; 4215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_DESCR_UNKNOWN; 4235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 426ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 427ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_add_char_descr 428ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 429ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function add a characteristics descriptor. 430ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 431ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_db: database pointer. 432ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * perm: characteristic descriptor permission type. 433ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * char_dscp_tpye: the characteristic descriptor masks. 434ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_dscp_params: characteristic descriptors values. 435ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 436ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of the operation. 437ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 438ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 4396395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskiuint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm, 4406395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tBT_UUID& descr_uuid) { 441d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << StringPrintf("gatts_add_char_descr uuid=0x%04x", 442d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski descr_uuid.uu.uuid16); 443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Add characteristic descriptors */ 4456395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR& char_dscptr = allocate_attr_in_db(db, descr_uuid, perm); 4466395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski char_dscptr.gatt_type = BTGATT_DB_DESCRIPTOR; 4476395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return char_dscptr.handle; 4485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 450ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************/ 4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Service Attribute Database Query Utility Functions */ 452ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************/ 4536395f1547ed6179dcdeed392bd9909d18772fb25Jakub PawlowskitGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) { 4546395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (!p_db) return nullptr; 4556395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 4566395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski for (auto& attr : p_db->attr_list) { 4576395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (attr.handle == handle) return &attr; 4586395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (attr.handle > handle) return nullptr; 4596395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 4606395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 4616395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return nullptr; 4626395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski} 4636395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 465ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 466ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_read_attr_value_by_handle 467ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 468ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Query attribute value by attribute handle. 469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_db: pointer to the attribute database. 471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * handle: Attribute handle to read. 472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * offset: Read offset. 473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_value: output parameter to carry out the attribute value. 474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_len: output parameter as attribute length read. 475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * read_long: this is a read blob request. 476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * mtu: MTU. 477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * sec_flag: current link security status. 478ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * key_size: encryption key size 479ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 480ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of operation. 481ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 482ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 483911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_read_attr_value_by_handle( 484f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, 485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu, 486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) { 4876395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); 4886395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (!p_attr) return GATT_NOT_FOUND; 489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 4906395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski uint8_t* pp = p_value; 4916395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_STATUS status = read_attr_value(*p_attr, offset, &pp, 4926395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (bool)(op_code == GATT_REQ_READ_BLOB), 4936395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski mtu, p_len, sec_flag, key_size); 494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 4956395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (status == GATT_PENDING) { 496f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski status = gatts_send_app_read_request(tcb, op_code, p_attr->handle, offset, 4976395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski trans_id, p_attr->gatt_type); 498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return status; 5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 5015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 503ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 504ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_read_attr_perm_check 505ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 506ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Check attribute readability. 507ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 508ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_db: pointer to the attribute database. 509ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * handle: Attribute handle to read. 510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * offset: Read offset. 511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_value: output parameter to carry out the attribute value. 512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_len: output parameter as attribute length read. 513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * read_long: this is a read blob request. 514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * mtu: MTU. 515ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * sec_flag: current link security status. 516ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * key_size: encryption key size 517ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 518ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of operation. 519ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 520ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 521911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long, 522d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen uint16_t handle, 5235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project tGATT_SEC_FLAG sec_flag, 524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t key_size) { 5256395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); 5266395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (!p_attr) return GATT_NOT_FOUND; 5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 5286395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return gatts_check_attr_readability(*p_attr, 0, is_long, sec_flag, key_size); 5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 5306395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_write_attr_perm_check 534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Write attribute value into database. 536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_db: pointer to the attribute database. 538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * op_code:op code of this write. 539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * handle: handle of the attribute to write. 540ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * offset: Write offset if write op code is write blob. 541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_data: Attribute value to write. 542ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * len: attribute data length. 543ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * sec_flag: current link security status. 544ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * key_size: encryption key size 545ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 546ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns Status of the operation. 547ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 548ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 549911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code, 550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t handle, uint16_t offset, 551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t* p_data, uint16_t len, 552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGATT_SEC_FLAG sec_flag, 553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t key_size) { 554d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << StringPrintf( 555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "%s: op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x " 556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "key_size=%d", 557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson __func__, op_code, handle, offset, len, sec_flag, key_size); 558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 5596395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); 5606395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (!p_attr) return GATT_NOT_FOUND; 561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 5626395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_PERM perm = p_attr->permission; 5636395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski uint16_t min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12)); 5646395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (min_key_size != 0) { 5656395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski min_key_size += 6; 5666395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 567d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << StringPrintf("%s: p_attr->permission =0x%04x min_key_size==0x%04x", 568d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski __func__, p_attr->permission, min_key_size); 5696395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 5706395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE) && 5716395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (perm & GATT_WRITE_SIGNED_PERM)) { 5726395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* use the rules for the mixed security see section 10.2.3*/ 5736395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* use security mode 1 level 2 when the following condition follows */ 5746395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* LE security mode 2 level 1 and LE security mode 1 level 2 */ 5756395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if ((perm & GATT_PERM_WRITE_SIGNED) && (perm & GATT_PERM_WRITE_ENCRYPTED)) { 5766395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski perm = GATT_PERM_WRITE_ENCRYPTED; 5776395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 5786395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* use security mode 1 level 3 when the following condition follows */ 5796395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* LE security mode 2 level 2 and security mode 1 and LE */ 5806395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski else if (((perm & GATT_PERM_WRITE_SIGNED_MITM) && 5816395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (perm & GATT_PERM_WRITE_ENCRYPTED)) || 5826395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* LE security mode 2 and security mode 1 level 3 */ 5836395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski ((perm & GATT_WRITE_SIGNED_PERM) && 5846395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (perm & GATT_PERM_WRITE_ENC_MITM))) { 5856395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski perm = GATT_PERM_WRITE_ENC_MITM; 5866395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 5876395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 5896395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_STATUS status = GATT_NOT_FOUND; 5906395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM)) { 5916395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_WRITE_NOT_PERMIT; 592d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski VLOG(1) << __func__ << ": sign cmd write not allowed"; 5936395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 5946395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if ((op_code == GATT_SIGN_CMD_WRITE) && 5956395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { 5966395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INVALID_PDU; 597d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ 598d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski << ": Error!! sign cmd write sent on a encypted link"; 5996395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else if (!(perm & GATT_WRITE_ALLOWED)) { 6006395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_WRITE_NOT_PERMIT; 601d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_WRITE_NOT_PERMIT"; 6026395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 6036395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* require authentication, but not been authenticated */ 6046395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski else if ((perm & GATT_WRITE_AUTH_REQUIRED) && 6056395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED)) { 6066395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INSUF_AUTHENTICATION; 607d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION"; 6086395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else if ((perm & GATT_WRITE_MITM_REQUIRED) && 6096395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { 6106395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INSUF_AUTHENTICATION; 611d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION: MITM required"; 6126395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else if ((perm & GATT_WRITE_ENCRYPTED_PERM) && 6136395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { 6146395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INSUF_ENCRYPTION; 615d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_ENCRYPTION"; 6166395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else if ((perm & GATT_WRITE_ENCRYPTED_PERM) && 6176395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && 6186395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (key_size < min_key_size)) { 6196395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INSUF_KEY_SIZE; 620d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INSUF_KEY_SIZE"; 6216395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 6226395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* LE security mode 2 attribute */ 6236395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && 6246395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) && 6256395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (perm & GATT_WRITE_ALLOWED) == 0) { 6266395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INSUF_AUTHENTICATION; 627d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ 628d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski << ": GATT_INSUF_AUTHENTICATION: LE security mode 2 required"; 6296395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else /* writable: must be char value declaration or char descritpors 6306395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski */ 6316395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski { 6326395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski uint16_t max_size = 0; 6336395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 6346395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (p_attr->uuid.len == LEN_UUID_16) { 6356395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski switch (p_attr->uuid.uu.uuid16) { 6366395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_PRESENT_FORMAT: /* should be readable only */ 6376395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_EXT_PROP: /* should be readable only */ 6386395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_AGG_FORMAT: /* should be readable only */ 6396395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_VALID_RANGE: 640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = GATT_WRITE_NOT_PERMIT; 6416395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski break; 642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 6436395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_CLIENT_CONFIG: 6446395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* fall through */ 6456395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_SRVR_CONFIG: 6466395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski max_size = 2; 6476395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* fall through */ 6486395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski case GATT_UUID_CHAR_DESCRIPTION: 6496395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski default: /* any other must be character value declaration */ 6506395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_SUCCESS; 6516395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski break; 6526395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 6536395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else if (p_attr->uuid.len == LEN_UUID_128 || 6546395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski p_attr->uuid.len == LEN_UUID_32) { 6556395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_SUCCESS; 6566395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else { 6576395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INVALID_PDU; 6586395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 6596395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski 6606395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (p_data == NULL && len > 0) { 6616395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INVALID_PDU; 6626395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 6636395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski /* these attribute does not allow write blob */ 6646395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski else if ((p_attr->uuid.len == LEN_UUID_16) && 6656395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski (p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG || 6666395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_SRVR_CONFIG)) { 6676395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (op_code == GATT_REQ_PREPARE_WRITE && 6686395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski offset != 0) /* does not allow write blob */ 6696395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski { 6706395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_NOT_LONG; 671d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_NOT_LONG"; 6726395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else if (len != max_size) /* data does not match the required format */ 6736395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski { 6746395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_INVALID_ATTR_LEN; 675d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ << ": GATT_INVALID_PDU"; 6766395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } else { 6776395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski status = GATT_SUCCESS; 6786395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski } 6795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 6815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return status; 6835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 6845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void uuid_to_str(const tBT_UUID bt_uuid, char* str_buf, size_t buf_len) { 686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (bt_uuid.len == LEN_UUID_16) { 687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf(str_buf, buf_len, "0x%04x", bt_uuid.uu.uuid16); 688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (bt_uuid.len == LEN_UUID_32) { 689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf(str_buf, buf_len, "0x%08x", bt_uuid.uu.uuid32); 690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (bt_uuid.len == LEN_UUID_128) { 691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int x = snprintf(str_buf, buf_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-", 692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14], 693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12], 694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10], 695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]); 696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf(&str_buf[x], buf_len - x, "%02x%02x-%02x%02x%02x%02x%02x%02x", 697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6], 698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4], 699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2], 700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]); 701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson snprintf(str_buf, buf_len, "Unknown (len=%d)", bt_uuid.len); 703c88b20a599a52228c7b29d03751b7f13868d417aJakub Pawlowski} 704c88b20a599a52228c7b29d03751b7f13868d417aJakub Pawlowski 7056395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski/** 706ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Allocate a memory space for a new attribute, and link this 707ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * attribute into the database attribute list. 708ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 709ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 710ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameter p_db : database pointer. 7116395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski * uuid: attribute UUID 712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 713ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns pointer to the newly allocated attribute. 714ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 7156395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski */ 7166395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowskistatic tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid, 7176395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_PERM perm) { 7186395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski if (db.next_handle >= db.end_handle) { 7196395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski LOG(FATAL) << __func__ 7206395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski << " wrong number of handles! handle_max = " << +db.end_handle 7216395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski << ", next_handle = " << +db.next_handle; 722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 7246395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski db.attr_list.emplace_back(); 7256395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_ATTR& attr = db.attr_list.back(); 7266395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.handle = db.next_handle++; 7276395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.uuid = uuid; 7286395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski attr.permission = perm; 7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson char uuid_str[37]; 7316395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski uuid_to_str(attr.uuid, uuid_str, sizeof(uuid_str)); 7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7336395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski return attr; 7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 7355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************* 737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gatts_send_app_read_request 739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Send application read request callback 741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns status of operation. 743ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 744ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGATT_STATUS gatts_send_app_read_request( 746f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset, 747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) { 7486395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATT_SRV_LIST_ELEM& el = *gatt_sr_find_i_rcb_by_handle(handle); 749f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski uint16_t conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if); 750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (trans_id == 0) { 752f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle); 753f4c0292c63085cd4d0f5c001974b6503aeaf8ed3Jakub Pawlowski gatt_sr_update_cback_cnt(tcb, el.gatt_if, true, true); 754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (trans_id != 0) { 7576395f1547ed6179dcdeed392bd9909d18772fb25Jakub Pawlowski tGATTS_DATA sr_data; 758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(&sr_data, 0, sizeof(tGATTS_DATA)); 759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson sr_data.read_req.handle = handle; 761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson sr_data.read_req.is_long = (bool)(op_code == GATT_REQ_READ_BLOB); 762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson sr_data.read_req.offset = offset; 763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t opcode; 765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (gatt_type == BTGATT_DB_DESCRIPTOR) { 766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson opcode = GATTS_REQ_TYPE_READ_DESCRIPTOR; 767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) { 768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson opcode = GATTS_REQ_TYPE_READ_CHARACTERISTIC; 769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 770d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski LOG(ERROR) << __func__ 771d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski << ": Attempt to read attribute that's not tied with " 772d8be0e590aa1efe1c33a8acfea0d7e14fd1a8030Jakub Pawlowski "characteristic or descriptor value."; 773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return GATT_ERROR; 7745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project } 7755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project 776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data); 777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (tGATT_STATUS)GATT_PENDING; 778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (tGATT_STATUS)GATT_BUSY; /* max pending command, application error */ 7805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} 781