blob: 8d1f5e1c69c46148ff3300ae3502d6e713bd74eb [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 1999-2012 Broadcom Corporation
The Android Open Source Project5738f832012-12-12 16:00:35 -08004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 * this file contains GATT interface functions
22 *
23 ******************************************************************************/
24#include "bt_target.h"
25
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070026#include <base/strings/string_number_conversions.h>
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -070027#include <base/strings/stringprintf.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080028#include <stdio.h>
29#include <string.h>
Myles Watson911d1ae2016-11-28 16:44:40 -080030#include "bt_common.h"
31#include "btm_int.h"
Jakub Pawlowski96fb2732017-03-24 17:52:02 -070032#include "device/include/controller.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080033#include "gatt_api.h"
34#include "gatt_int.h"
35#include "l2c_api.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080036
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -070037using base::StringPrintf;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -070038using bluetooth::Uuid;
The Android Open Source Project5738f832012-12-12 16:00:35 -080039
Jakub Pawlowski6395f152017-05-09 05:02:38 -070040/**
41 * Add an service handle range to the list in decending order of the start
42 * handle. Return reference to the newly added element.
43 **/
44tGATT_HDL_LIST_ELEM& gatt_add_an_item_to_list(uint16_t s_handle) {
45 auto lst_ptr = gatt_cb.hdl_list_info;
46 auto it = lst_ptr->begin();
47 for (; it != lst_ptr->end(); it++) {
48 if (s_handle > it->asgn_range.s_handle) break;
49 }
50
51 auto rit = lst_ptr->emplace(it);
52 return *rit;
53}
54
The Android Open Source Project5738f832012-12-12 16:00:35 -080055/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080056 *
57 * GATT SERVER API
58 *
59 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080060/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080061 *
62 * Function GATTS_AddHandleRange
63 *
Myles Watson9ca07092016-11-28 16:41:53 -080064 * Description This function add the allocated handles range for the
65 * specified application UUID, service UUID and service
66 * instance
Myles Watsonee96a3c2016-11-23 14:49:54 -080067 *
68 * Parameter p_hndl_range: pointer to allocated handles information
69 *
Jakub Pawlowski6395f152017-05-09 05:02:38 -070070 **/
The Android Open Source Project5738f832012-12-12 16:00:35 -080071
Jakub Pawlowski6395f152017-05-09 05:02:38 -070072void GATTS_AddHandleRange(tGATTS_HNDL_RANGE* p_hndl_range) {
73 gatt_add_an_item_to_list(p_hndl_range->s_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -080074}
75
The Android Open Source Project5738f832012-12-12 16:00:35 -080076/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080077 *
78 * Function GATTS_NVRegister
79 *
80 * Description Application manager calls this function to register for
81 * NV save callback function. There can be one and only one
82 * NV save callback function.
83 *
84 * Parameter p_cb_info : callback informaiton
85 *
86 * Returns true if registered OK, else false
87 *
88 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -080089bool GATTS_NVRegister(tGATT_APPL_INFO* p_cb_info) {
90 bool status = false;
91 if (p_cb_info) {
92 gatt_cb.cb_info = *p_cb_info;
93 status = true;
94 gatt_init_srv_chg();
95 }
The Android Open Source Project5738f832012-12-12 16:00:35 -080096
Myles Watson911d1ae2016-11-28 16:44:40 -080097 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -080098}
99
Myles Watson911d1ae2016-11-28 16:44:40 -0800100static uint16_t compute_service_size(btgatt_db_element_t* service, int count) {
101 int db_size = 0;
102 btgatt_db_element_t* el = service;
Jakub Pawlowski7680a0b2016-11-08 17:23:11 -0800103
Myles Watson911d1ae2016-11-28 16:44:40 -0800104 for (int i = 0; i < count; i++, el++)
105 if (el->type == BTGATT_DB_PRIMARY_SERVICE ||
106 el->type == BTGATT_DB_SECONDARY_SERVICE ||
107 el->type == BTGATT_DB_DESCRIPTOR ||
108 el->type == BTGATT_DB_INCLUDED_SERVICE)
109 db_size += 1;
110 else if (el->type == BTGATT_DB_CHARACTERISTIC)
111 db_size += 2;
112 else
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700113 LOG(ERROR) << __func__ << ": Unknown element type: " << el->type;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700114
Myles Watson911d1ae2016-11-28 16:44:40 -0800115 return db_size;
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700116}
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700117
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700118static bool is_gatt_attr_type(const Uuid& uuid) {
119 if (uuid == Uuid::From16Bit(GATT_UUID_PRI_SERVICE) ||
120 uuid == Uuid::From16Bit(GATT_UUID_SEC_SERVICE) ||
121 uuid == Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE) ||
122 uuid == Uuid::From16Bit(GATT_UUID_CHAR_DECLARE)) {
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700123 return true;
124 }
125 return false;
126}
127
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700128/** Update the the last primary info for the service list info */
129static void gatt_update_last_pri_srv_info() {
130 gatt_cb.last_primary_s_handle = 0;
131
132 for (tGATT_SRV_LIST_ELEM& el : *gatt_cb.srv_list_info)
133 if (el.is_primary) gatt_cb.last_primary_s_handle = el.s_hdl;
134}
135
The Android Open Source Project5738f832012-12-12 16:00:35 -0800136/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800137 *
138 * Function GATTS_AddService
139 *
140 * Description This function is called to add GATT service.
141 *
142 * Parameter gatt_if : application if
143 * service : pseudo-representation of service and it's content
144 * count : size of service
145 *
146 * Returns on success GATT_SERVICE_STARTED is returned, and
147 * attribute_handle field inside service elements are filled.
148 * on error error status is returned.
149 *
150 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800151uint16_t GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service,
152 int count) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800153 uint16_t s_hdl = 0;
154 bool save_hdl = false;
155 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800156
Myles Watson911d1ae2016-11-28 16:44:40 -0800157 bool is_pri = (service->type == BTGATT_DB_PRIMARY_SERVICE) ? true : false;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700158 Uuid svc_uuid = service->uuid;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800159
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700160 LOG(INFO) << __func__;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800161
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700162 if (!p_reg) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700163 LOG(ERROR) << "Inavlid gatt_if=" << +gatt_if;
Myles Watson911d1ae2016-11-28 16:44:40 -0800164 return GATT_INTERNAL_ERROR;
165 }
166
Myles Watson911d1ae2016-11-28 16:44:40 -0800167 uint16_t num_handles = compute_service_size(service, count);
168
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700169 if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800170 s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700171 } else if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800172 s_hdl = gatt_cb.hdl_cfg.gap_start_hdl;
173 } else {
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700174 if (!gatt_cb.hdl_list_info->empty()) {
175 s_hdl = gatt_cb.hdl_list_info->front().asgn_range.e_handle + 1;
176 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800177
178 if (s_hdl < gatt_cb.hdl_cfg.app_start_hdl)
179 s_hdl = gatt_cb.hdl_cfg.app_start_hdl;
180
181 save_hdl = true;
182 }
183
184 /* check for space */
185 if (num_handles > (0xFFFF - s_hdl + 1)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700186 LOG(ERROR) << StringPrintf(
187 "GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u", s_hdl,
188 num_handles);
Myles Watson911d1ae2016-11-28 16:44:40 -0800189 return GATT_INTERNAL_ERROR;
190 }
191
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700192 tGATT_HDL_LIST_ELEM& list = gatt_add_an_item_to_list(s_hdl);
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700193 list.asgn_range.app_uuid128 = p_reg->app_uuid128;
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700194 list.asgn_range.svc_uuid = svc_uuid;
195 list.asgn_range.s_handle = s_hdl;
196 list.asgn_range.e_handle = s_hdl + num_handles - 1;
197 list.asgn_range.is_primary = is_pri;
Myles Watson911d1ae2016-11-28 16:44:40 -0800198
199 if (save_hdl) {
200 if (gatt_cb.cb_info.p_nv_save_callback)
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700201 (*gatt_cb.cb_info.p_nv_save_callback)(true, &list.asgn_range);
Myles Watson911d1ae2016-11-28 16:44:40 -0800202 }
203
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700204 gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles);
Myles Watson911d1ae2016-11-28 16:44:40 -0800205
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700206 VLOG(1) << StringPrintf(
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700207 "%s: handles needed:%u s_hdl=%u e_hdl=%u %s is_primary=%d", __func__,
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700208 num_handles, list.asgn_range.s_handle, list.asgn_range.e_handle,
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700209 list.asgn_range.svc_uuid.ToString().c_str(), list.asgn_range.is_primary);
Myles Watson911d1ae2016-11-28 16:44:40 -0800210
211 service->attribute_handle = s_hdl;
212
213 btgatt_db_element_t* el = service + 1;
214 for (int i = 0; i < count - 1; i++, el++) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700215 const Uuid& uuid = el->uuid;
Myles Watson911d1ae2016-11-28 16:44:40 -0800216
217 if (el->type == BTGATT_DB_CHARACTERISTIC) {
218 /* data validity checking */
219 if (((el->properties & GATT_CHAR_PROP_BIT_AUTH) &&
220 !(el->permissions & GATT_WRITE_SIGNED_PERM)) ||
221 ((el->permissions & GATT_WRITE_SIGNED_PERM) &&
222 !(el->properties & GATT_CHAR_PROP_BIT_AUTH))) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700223 VLOG(1) << StringPrintf(
224 "Invalid configuration property=0x%02x perm=0x%04x ",
225 el->properties, el->permissions);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700226 return GATT_INTERNAL_ERROR;
Myles Watson911d1ae2016-11-28 16:44:40 -0800227 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800228
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700229 if (is_gatt_attr_type(uuid)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700230 LOG(ERROR) << StringPrintf(
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700231 "%s: attept to add characteristic with UUID equal to GATT "
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700232 "Attribute Type %s ",
233 __func__, uuid.ToString().c_str());
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700234 return GATT_INTERNAL_ERROR;
235 }
236
Myles Watson911d1ae2016-11-28 16:44:40 -0800237 el->attribute_handle = gatts_add_characteristic(
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700238 list.svc_db, el->permissions, el->properties, uuid);
Myles Watson911d1ae2016-11-28 16:44:40 -0800239 } else if (el->type == BTGATT_DB_DESCRIPTOR) {
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700240 if (is_gatt_attr_type(uuid)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700241 LOG(ERROR) << StringPrintf(
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700242 "%s: attept to add descriptor with UUID equal to GATT "
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700243 "Attribute Type %s",
244 __func__, uuid.ToString().c_str());
Jakub Pawlowski671ad662017-05-10 04:39:26 -0700245 return GATT_INTERNAL_ERROR;
246 }
247
Myles Watson911d1ae2016-11-28 16:44:40 -0800248 el->attribute_handle =
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700249 gatts_add_char_descr(list.svc_db, el->permissions, uuid);
Myles Watson911d1ae2016-11-28 16:44:40 -0800250 } else if (el->type == BTGATT_DB_INCLUDED_SERVICE) {
251 tGATT_HDL_LIST_ELEM* p_incl_decl;
252 p_incl_decl = gatt_find_hdl_buffer_by_handle(el->attribute_handle);
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700253 if (p_incl_decl == nullptr) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700254 VLOG(1) << "Included Service not created";
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700255 return GATT_INTERNAL_ERROR;
Myles Watson911d1ae2016-11-28 16:44:40 -0800256 }
257
258 el->attribute_handle = gatts_add_included_service(
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700259 list.svc_db, p_incl_decl->asgn_range.s_handle,
Myles Watson911d1ae2016-11-28 16:44:40 -0800260 p_incl_decl->asgn_range.e_handle, p_incl_decl->asgn_range.svc_uuid);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700261 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800262 }
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700263
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700264 LOG(INFO) << __func__ << ": service parsed correctly, now starting";
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700265
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700266 /*this is a new application service start */
267
268 // find a place for this service in the list
269 auto lst_ptr = gatt_cb.srv_list_info;
270 auto it = lst_ptr->begin();
271 for (; it != lst_ptr->end(); it++) {
272 if (list.asgn_range.s_handle < it->s_hdl) break;
273 }
274 auto rit = lst_ptr->emplace(it);
275
276 tGATT_SRV_LIST_ELEM& elem = *rit;
277 elem.gatt_if = gatt_if;
278 elem.s_hdl = list.asgn_range.s_handle;
279 elem.e_hdl = list.asgn_range.e_handle;
280 elem.p_db = &list.svc_db;
281 elem.is_primary = list.asgn_range.is_primary;
282
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700283 elem.app_uuid = list.asgn_range.app_uuid128;
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700284 elem.type = list.asgn_range.is_primary ? GATT_UUID_PRI_SERVICE
285 : GATT_UUID_SEC_SERVICE;
286
287 if (elem.type == GATT_UUID_PRI_SERVICE) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700288 Uuid* p_uuid = gatts_get_service_uuid(elem.p_db);
289 elem.sdp_handle = gatt_add_sdp_record(*p_uuid, elem.s_hdl, elem.e_hdl);
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700290 } else {
291 elem.sdp_handle = 0;
Myles Watson911d1ae2016-11-28 16:44:40 -0800292 }
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700293
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700294 gatt_update_last_pri_srv_info();
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700295
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700296 VLOG(1) << StringPrintf(
297 "%s: allocated el: s_hdl=%d e_hdl=%d type=0x%x sdp_hdl=0x%x", __func__,
298 elem.s_hdl, elem.e_hdl, elem.type, elem.sdp_handle);
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700299
Myles Watson911d1ae2016-11-28 16:44:40 -0800300 gatt_proc_srv_chg();
Jakub Pawlowskia641b6f2016-03-26 00:47:23 -0700301
Myles Watson911d1ae2016-11-28 16:44:40 -0800302 return GATT_SERVICE_STARTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800303}
304
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700305bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid,
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700306 uint16_t start_handle) {
307 for (auto& info : *gatt_cb.srv_list_info) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700308 Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db);
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700309
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700310 if (p_this_uuid && app_uuid128 == info.app_uuid &&
311 *p_svc_uuid == *p_this_uuid && (start_handle == info.s_hdl)) {
312 LOG(ERROR) << "Active Service Found: " << *p_svc_uuid;
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700313 return true;
314 }
315 }
316 return false;
317}
318
The Android Open Source Project5738f832012-12-12 16:00:35 -0800319/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800320 *
321 * Function GATTS_DeleteService
322 *
323 * Description This function is called to delete a service.
324 *
325 * Parameter gatt_if : application interface
326 * p_svc_uuid : service UUID
327 * start_handle : start handle of the service
328 *
Myles Watson9ca07092016-11-28 16:41:53 -0800329 * Returns true if the operation succeeded, false if the handle block
330 * was not found.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800331 *
332 ******************************************************************************/
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700333bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid,
Myles Watson911d1ae2016-11-28 16:44:40 -0800334 uint16_t svc_inst) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700335 VLOG(1) << __func__;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800336
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700337 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
Myles Watson911d1ae2016-11-28 16:44:40 -0800338 if (p_reg == NULL) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700339 LOG(ERROR) << "Applicaiton not foud";
Myles Watson911d1ae2016-11-28 16:44:40 -0800340 return false;
341 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800342
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700343 auto it =
344 gatt_find_hdl_buffer_by_app_id(p_reg->app_uuid128, p_svc_uuid, svc_inst);
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700345 if (it == gatt_cb.hdl_list_info->end()) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700346 LOG(ERROR) << "No Service found";
Myles Watson911d1ae2016-11-28 16:44:40 -0800347 return false;
348 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800349
Myles Watson911d1ae2016-11-28 16:44:40 -0800350 gatt_proc_srv_chg();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800351
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700352 if (is_active_service(p_reg->app_uuid128, p_svc_uuid, svc_inst)) {
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700353 GATTS_StopService(it->asgn_range.s_handle);
Myles Watson911d1ae2016-11-28 16:44:40 -0800354 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800355
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700356 VLOG(1) << StringPrintf("released handles s_hdl=%u e_hdl=%u",
357 it->asgn_range.s_handle, it->asgn_range.e_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800358
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700359 if ((it->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl) &&
Myles Watson911d1ae2016-11-28 16:44:40 -0800360 gatt_cb.cb_info.p_nv_save_callback)
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700361 (*gatt_cb.cb_info.p_nv_save_callback)(false, &it->asgn_range);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800362
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700363 gatt_cb.hdl_list_info->erase(it);
Myles Watson911d1ae2016-11-28 16:44:40 -0800364 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800365}
366
367/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800368 *
369 * Function GATTS_StopService
370 *
371 * Description This function is called to stop a service
372 *
373 * Parameter service_handle : this is the start handle of a service
374 *
375 * Returns None.
376 *
377 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800378void GATTS_StopService(uint16_t service_handle) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700379 LOG(INFO) << __func__ << ": 0x" << std::hex << +service_handle;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800380
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700381 auto it = gatt_sr_find_i_rcb_by_handle(service_handle);
382 if (it == gatt_cb.srv_list_info->end()) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700383 LOG(ERROR) << StringPrintf("%s: service_handle: %u is not in use", __func__,
384 service_handle);
Myles Watson911d1ae2016-11-28 16:44:40 -0800385 }
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700386
387 if (it->sdp_handle) {
388 SDP_DeleteRecord(it->sdp_handle);
389 }
390
391 gatt_cb.srv_list_info->erase(it);
392 gatt_update_last_pri_srv_info();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800393}
394/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800395 *
396 * Function GATTs_HandleValueIndication
397 *
398 * Description This function sends a handle value indication to a client.
399 *
400 * Parameter conn_id: connection identifier.
Myles Watson9ca07092016-11-28 16:41:53 -0800401 * attr_handle: Attribute handle of this handle value
402 * indication.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800403 * val_len: Length of the indicated attribute value.
404 * p_val: Pointer to the indicated attribute value data.
405 *
Myles Watson9ca07092016-11-28 16:41:53 -0800406 * Returns GATT_SUCCESS if sucessfully sent or queued; otherwise error
407 * code.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800408 *
409 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800410tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
411 uint16_t val_len, uint8_t* p_val) {
412 tGATT_STATUS cmd_status = GATT_NO_RESOURCES;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800413
Myles Watson911d1ae2016-11-28 16:44:40 -0800414 tGATT_VALUE indication;
415 BT_HDR* p_msg;
416 tGATT_VALUE* p_buf;
417 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
418 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
419 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
420 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800421
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700422 VLOG(1) << __func__;
Myles Watson911d1ae2016-11-28 16:44:40 -0800423 if ((p_reg == NULL) || (p_tcb == NULL)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700424 LOG(ERROR) << __func__ << ": Unknown conn_id: " << +conn_id;
Myles Watson911d1ae2016-11-28 16:44:40 -0800425 return (tGATT_STATUS)GATT_INVALID_CONN_ID;
426 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800427
Myles Watson911d1ae2016-11-28 16:44:40 -0800428 if (!GATT_HANDLE_IS_VALID(attr_handle)) return GATT_ILLEGAL_PARAMETER;
429
430 indication.conn_id = conn_id;
431 indication.handle = attr_handle;
432 indication.len = val_len;
433 memcpy(indication.value, p_val, val_len);
434 indication.auth_req = GATT_AUTH_REQ_NONE;
435
436 if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700437 VLOG(1) << "Add a pending indication";
Myles Watson911d1ae2016-11-28 16:44:40 -0800438 p_buf = gatt_add_pending_ind(p_tcb, &indication);
439 if (p_buf != NULL) {
440 cmd_status = GATT_SUCCESS;
441 } else {
442 cmd_status = GATT_NO_RESOURCES;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800443 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800444 } else {
Myles Watson8d749042017-09-19 10:01:28 -0700445 tGATT_SR_MSG gatt_sr_msg;
446 gatt_sr_msg.attr_value = indication;
447 p_msg = attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
Myles Watson911d1ae2016-11-28 16:44:40 -0800448 if (p_msg != NULL) {
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700449 cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
Andre Eisenbach17b04bd2014-03-28 14:54:22 -0700450
Myles Watson911d1ae2016-11-28 16:44:40 -0800451 if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
452 p_tcb->indicate_handle = indication.handle;
453 gatt_start_conf_timer(p_tcb);
454 }
Andre Eisenbach17b04bd2014-03-28 14:54:22 -0700455 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800456 }
457 return cmd_status;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800458}
459
460/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800461 *
462 * Function GATTS_HandleValueNotification
463 *
464 * Description This function sends a handle value notification to a client.
465 *
466 * Parameter conn_id: connection identifier.
Myles Watson9ca07092016-11-28 16:41:53 -0800467 * attr_handle: Attribute handle of this handle value
468 * indication.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800469 * val_len: Length of the indicated attribute value.
470 * p_val: Pointer to the indicated attribute value data.
471 *
472 * Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
473 *
474 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800475tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id,
476 uint16_t attr_handle,
477 uint16_t val_len, uint8_t* p_val) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800478 tGATT_VALUE notif;
479 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
480 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
481 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
482 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800483
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700484 VLOG(1) << __func__;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800485
Myles Watson911d1ae2016-11-28 16:44:40 -0800486 if ((p_reg == NULL) || (p_tcb == NULL)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700487 LOG(ERROR) << __func__ << "Unknown conn_id: " << conn_id;
Myles Watson911d1ae2016-11-28 16:44:40 -0800488 return (tGATT_STATUS)GATT_INVALID_CONN_ID;
489 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800490
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700491 if (!GATT_HANDLE_IS_VALID(attr_handle)) {
492 return GATT_ILLEGAL_PARAMETER;
Myles Watson911d1ae2016-11-28 16:44:40 -0800493 }
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700494
495 notif.handle = attr_handle;
496 notif.len = val_len;
497 memcpy(notif.value, p_val, val_len);
498 notif.auth_req = GATT_AUTH_REQ_NONE;
499
500 tGATT_STATUS cmd_sent;
Myles Watson8d749042017-09-19 10:01:28 -0700501 tGATT_SR_MSG gatt_sr_msg;
502 gatt_sr_msg.attr_value = notif;
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700503 BT_HDR* p_buf =
Myles Watson8d749042017-09-19 10:01:28 -0700504 attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg);
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700505 if (p_buf != NULL) {
506 cmd_sent = attp_send_sr_msg(*p_tcb, p_buf);
507 } else
508 cmd_sent = GATT_NO_RESOURCES;
Myles Watson911d1ae2016-11-28 16:44:40 -0800509 return cmd_sent;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800510}
511
512/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800513 *
514 * Function GATTS_SendRsp
515 *
516 * Description This function sends the server response to client.
517 *
518 * Parameter conn_id: connection identifier.
519 * trans_id: transaction id
520 * status: response status
521 * p_msg: pointer to message parameters structure.
522 *
523 * Returns GATT_SUCCESS if sucessfully sent; otherwise error code.
524 *
525 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800526tGATT_STATUS GATTS_SendRsp(uint16_t conn_id, uint32_t trans_id,
527 tGATT_STATUS status, tGATTS_RSP* p_msg) {
528 tGATT_STATUS cmd_sent = GATT_ILLEGAL_PARAMETER;
529 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
530 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
531 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
532 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800533
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700534 VLOG(1) << __func__
535 << StringPrintf(": conn_id: %u trans_id: %u Status: 0x%04x",
536 conn_id, trans_id, status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800537
Myles Watson911d1ae2016-11-28 16:44:40 -0800538 if ((p_reg == NULL) || (p_tcb == NULL)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700539 LOG(ERROR) << StringPrintf("Unknown conn_id: %u ", conn_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800540 return (tGATT_STATUS)GATT_INVALID_CONN_ID;
541 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800542
Myles Watson911d1ae2016-11-28 16:44:40 -0800543 if (p_tcb->sr_cmd.trans_id != trans_id) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700544 LOG(ERROR) << StringPrintf("conn_id: %u waiting for op_code = %02x",
545 conn_id, p_tcb->sr_cmd.op_code);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800546
Myles Watson911d1ae2016-11-28 16:44:40 -0800547 return (GATT_WRONG_STATE);
548 }
549 /* Process App response */
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700550 cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id,
Myles Watson911d1ae2016-11-28 16:44:40 -0800551 p_tcb->sr_cmd.op_code, status, p_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800552
Myles Watson911d1ae2016-11-28 16:44:40 -0800553 return cmd_sent;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800554}
555
Myles Watsonee96a3c2016-11-23 14:49:54 -0800556/******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800557/* GATT Profile Srvr Functions */
Myles Watsonee96a3c2016-11-23 14:49:54 -0800558/******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800559
Myles Watsonee96a3c2016-11-23 14:49:54 -0800560/******************************************************************************/
Myles Watson9ca07092016-11-28 16:41:53 -0800561/* */
562/* GATT CLIENT APIs */
563/* */
Myles Watsonee96a3c2016-11-23 14:49:54 -0800564/******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800565
The Android Open Source Project5738f832012-12-12 16:00:35 -0800566/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800567 *
568 * Function GATTC_ConfigureMTU
569 *
570 * Description This function is called to configure the ATT MTU size.
571 *
572 * Parameters conn_id: connection identifier.
573 * mtu - attribute MTU size..
574 *
575 * Returns GATT_SUCCESS if command started successfully.
576 *
577 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800578tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800579 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
580 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
581 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
582 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800583
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700584 VLOG(1) << __func__ << StringPrintf("conn_id=%d mtu=%d", conn_id, mtu);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800585
Myles Watson911d1ae2016-11-28 16:44:40 -0800586 if ((p_tcb == NULL) || (p_reg == NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) ||
587 (mtu > GATT_MAX_MTU_SIZE)) {
588 return GATT_ILLEGAL_PARAMETER;
589 }
liuchao18738c32016-11-14 16:13:10 +0800590
Myles Watson911d1ae2016-11-28 16:44:40 -0800591 /* Validate that the link is BLE, not BR/EDR */
592 if (p_tcb->transport != BT_TRANSPORT_LE) {
593 return GATT_ERROR;
594 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800595
Myles Watson911d1ae2016-11-28 16:44:40 -0800596 if (gatt_is_clcb_allocated(conn_id)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700597 LOG(ERROR) << "GATT_BUSY conn_id = " << +conn_id;
Myles Watson911d1ae2016-11-28 16:44:40 -0800598 return GATT_BUSY;
599 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800600
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700601 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
602 if (!p_clcb) return GATT_NO_RESOURCES;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800603
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700604 p_clcb->p_tcb->payload_size = mtu;
605 p_clcb->operation = GATTC_OPTYPE_CONFIG;
Myles Watson8d749042017-09-19 10:01:28 -0700606 tGATT_CL_MSG gatt_cl_msg;
607 gatt_cl_msg.mtu = mtu;
608 return attp_send_cl_msg(*p_clcb->p_tcb, p_clcb, GATT_REQ_MTU, &gatt_cl_msg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800609}
610
611/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800612 *
613 * Function GATTC_Discover
614 *
Myles Watson9ca07092016-11-28 16:41:53 -0800615 * Description This function is called to do a discovery procedure on ATT
616 * server.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800617 *
618 * Parameters conn_id: connection identifier.
619 * disc_type:discovery type.
620 * p_param: parameters of discovery requirement.
621 *
622 * Returns GATT_SUCCESS if command received/sent successfully.
623 *
624 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800625tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
626 tGATT_DISC_PARAM* p_param) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800627 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
628 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
629 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
630 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800631
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700632 LOG(INFO) << __func__
633 << StringPrintf(" conn_id=%d disc_type=%d", conn_id, disc_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800634
Myles Watson911d1ae2016-11-28 16:44:40 -0800635 if ((p_tcb == NULL) || (p_reg == NULL) || (p_param == NULL) ||
636 (disc_type >= GATT_DISC_MAX)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700637 LOG(ERROR) << StringPrintf("Illegal param: disc_type %d conn_id = %d",
638 disc_type, conn_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800639 return GATT_ILLEGAL_PARAMETER;
640 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800641
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700642 if (!GATT_HANDLE_IS_VALID(p_param->s_handle) ||
643 !GATT_HANDLE_IS_VALID(p_param->e_handle) ||
644 /* search by type does not have a valid UUID param */
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700645 (disc_type == GATT_DISC_SRVC_BY_UUID && p_param->service.IsEmpty())) {
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700646 return GATT_ILLEGAL_PARAMETER;
647 }
648
Myles Watson911d1ae2016-11-28 16:44:40 -0800649 if (gatt_is_clcb_allocated(conn_id)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700650 LOG(ERROR) << __func__ << "GATT_BUSY conn_id = " << +conn_id;
Myles Watson911d1ae2016-11-28 16:44:40 -0800651 return GATT_BUSY;
652 }
653
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700654 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
655 if (!p_clcb) return GATT_NO_RESOURCES;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800656
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700657 p_clcb->operation = GATTC_OPTYPE_DISCOVERY;
658 p_clcb->op_subtype = disc_type;
659 p_clcb->s_handle = p_param->s_handle;
660 p_clcb->e_handle = p_param->e_handle;
661 p_clcb->uuid = p_param->service;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800662
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700663 gatt_act_discovery(p_clcb);
664 return GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800665}
666
667/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800668 *
669 * Function GATTC_Read
670 *
Myles Watson9ca07092016-11-28 16:41:53 -0800671 * Description This function is called to read the value of an attribute
672 * from the server.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800673 *
674 * Parameters conn_id: connection identifier.
675 * type - attribute read type.
676 * p_read - read operation parameters.
677 *
678 * Returns GATT_SUCCESS if command started successfully.
679 *
680 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800681tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type,
682 tGATT_READ_PARAM* p_read) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800683 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
684 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
685 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
686 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800687
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700688 VLOG(1) << __func__ << StringPrintf(" conn_id=%d type=%d", conn_id, type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800689
Myles Watson911d1ae2016-11-28 16:44:40 -0800690 if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) ||
691 ((type >= GATT_READ_MAX) || (type == 0))) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700692 LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id,
693 type);
Myles Watson911d1ae2016-11-28 16:44:40 -0800694 return GATT_ILLEGAL_PARAMETER;
695 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800696
Myles Watson911d1ae2016-11-28 16:44:40 -0800697 if (gatt_is_clcb_allocated(conn_id)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700698 LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800699 return GATT_BUSY;
700 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800701
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700702 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
703 if (!p_clcb) return GATT_NO_RESOURCES;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800704
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700705 p_clcb->operation = GATTC_OPTYPE_READ;
706 p_clcb->op_subtype = type;
707 p_clcb->auth_req = p_read->by_handle.auth_req;
708 p_clcb->counter = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800709
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700710 switch (type) {
711 case GATT_READ_BY_TYPE:
712 case GATT_READ_CHAR_VALUE:
713 p_clcb->s_handle = p_read->service.s_handle;
714 p_clcb->e_handle = p_read->service.e_handle;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700715 p_clcb->uuid = p_read->service.uuid;
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700716 break;
717 case GATT_READ_MULTIPLE: {
718 p_clcb->s_handle = 0;
719 /* copy multiple handles in CB */
720 tGATT_READ_MULTI* p_read_multi =
721 (tGATT_READ_MULTI*)osi_malloc(sizeof(tGATT_READ_MULTI));
722 p_clcb->p_attr_buf = (uint8_t*)p_read_multi;
723 memcpy(p_read_multi, &p_read->read_multiple, sizeof(tGATT_READ_MULTI));
724 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800725 }
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700726 case GATT_READ_BY_HANDLE:
727 case GATT_READ_PARTIAL:
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700728 p_clcb->uuid = Uuid::kEmpty;
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700729 p_clcb->s_handle = p_read->by_handle.handle;
730
731 if (type == GATT_READ_PARTIAL) {
732 p_clcb->counter = p_read->partial.offset;
733 }
734
735 break;
736 default:
737 break;
Myles Watson911d1ae2016-11-28 16:44:40 -0800738 }
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700739
740 /* start security check */
741 gatt_security_check_start(p_clcb);
742 return GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800743}
744
745/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800746 *
747 * Function GATTC_Write
748 *
Myles Watson9ca07092016-11-28 16:41:53 -0800749 * Description This function is called to write the value of an attribute
750 * to the server.
Myles Watsonee96a3c2016-11-23 14:49:54 -0800751 *
752 * Parameters conn_id: connection identifier.
753 * type - attribute write type.
754 * p_write - write operation parameters.
755 *
756 * Returns GATT_SUCCESS if command started successfully.
757 *
758 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800759tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type,
760 tGATT_VALUE* p_write) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800761 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
762 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
763 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
764 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800765
Myles Watson911d1ae2016-11-28 16:44:40 -0800766 if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
767 ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
768 (type != GATT_WRITE_NO_RSP))) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700769 LOG(ERROR) << __func__
770 << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id,
771 type);
Myles Watson911d1ae2016-11-28 16:44:40 -0800772 return GATT_ILLEGAL_PARAMETER;
773 }
774
775 if (gatt_is_clcb_allocated(conn_id)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700776 LOG(ERROR) << StringPrintf("GATT_BUSY conn_id = %d", conn_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800777 return GATT_BUSY;
778 }
779
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700780 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
781 if (!p_clcb) return GATT_NO_RESOURCES;
Myles Watson911d1ae2016-11-28 16:44:40 -0800782
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700783 p_clcb->operation = GATTC_OPTYPE_WRITE;
784 p_clcb->op_subtype = type;
785 p_clcb->auth_req = p_write->auth_req;
Myles Watson911d1ae2016-11-28 16:44:40 -0800786
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700787 p_clcb->p_attr_buf = (uint8_t*)osi_malloc(sizeof(tGATT_VALUE));
788 memcpy(p_clcb->p_attr_buf, (void*)p_write, sizeof(tGATT_VALUE));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800789
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700790 tGATT_VALUE* p = (tGATT_VALUE*)p_clcb->p_attr_buf;
791 if (type == GATT_WRITE_PREPARE) {
792 p_clcb->start_offset = p_write->offset;
793 p->offset = 0;
Myles Watson911d1ae2016-11-28 16:44:40 -0800794 }
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700795
796 gatt_security_check_start(p_clcb);
797 return GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800798}
799
The Android Open Source Project5738f832012-12-12 16:00:35 -0800800/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800801 *
802 * Function GATTC_ExecuteWrite
803 *
804 * Description This function is called to send an Execute write request to
805 * the server.
806 *
807 * Parameters conn_id: connection identifier.
Myles Watson9ca07092016-11-28 16:41:53 -0800808 * is_execute - to execute or cancel the prepared write
809 * request(s)
Myles Watsonee96a3c2016-11-23 14:49:54 -0800810 *
811 * Returns GATT_SUCCESS if command started successfully.
812 *
813 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800814tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800815 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
816 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
817 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
818 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700820 VLOG(1) << __func__
821 << StringPrintf(": conn_id=%d is_execute=%d", conn_id, is_execute);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800822
Myles Watson911d1ae2016-11-28 16:44:40 -0800823 if ((p_tcb == NULL) || (p_reg == NULL)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700824 LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d", conn_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800825 return GATT_ILLEGAL_PARAMETER;
826 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800827
Myles Watson911d1ae2016-11-28 16:44:40 -0800828 if (gatt_is_clcb_allocated(conn_id)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700829 LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id);
Myles Watson911d1ae2016-11-28 16:44:40 -0800830 return GATT_BUSY;
831 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800832
Jakub Pawlowski1ad90382017-06-08 12:27:30 -0700833 tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id);
834 if (!p_clcb) return GATT_NO_RESOURCES;
835
836 p_clcb->operation = GATTC_OPTYPE_EXE_WRITE;
837 tGATT_EXEC_FLAG flag =
838 is_execute ? GATT_PREP_WRITE_EXEC : GATT_PREP_WRITE_CANCEL;
839 gatt_send_queue_write_cancel(*p_clcb->p_tcb, p_clcb, flag);
840 return GATT_SUCCESS;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800841}
842
843/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800844 *
845 * Function GATTC_SendHandleValueConfirm
846 *
847 * Description This function is called to send a handle value confirmation
848 * as response to a handle value notification from server.
849 *
850 * Parameters conn_id: connection identifier.
851 * handle: the handle of the attribute confirmation.
852 *
853 * Returns GATT_SUCCESS if command started successfully.
854 *
855 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800856tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) {
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700857 VLOG(1) << __func__
858 << StringPrintf(" conn_id=%d handle=0x%x", conn_id, handle);
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700859
Myles Watson911d1ae2016-11-28 16:44:40 -0800860 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700861 if (!p_tcb) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700862 LOG(ERROR) << StringPrintf(" Unknown conn_id: %u", conn_id);
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700863 return GATT_ILLEGAL_PARAMETER;
Myles Watson911d1ae2016-11-28 16:44:40 -0800864 }
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700865
866 if (p_tcb->ind_count == 0) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700867 VLOG(1) << " conn_id: " << +conn_id
868 << " ignored not waiting for indicaiton ack";
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700869 return GATT_SUCCESS;
870 }
871
872 alarm_cancel(p_tcb->ind_ack_timer);
873
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700874 VLOG(1) << "notif_count= " << p_tcb->ind_count;
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700875 /* send confirmation now */
Myles Watson8d749042017-09-19 10:01:28 -0700876 tGATT_CL_MSG gatt_cl_msg;
877 gatt_cl_msg.handle = handle;
878 tGATT_STATUS ret =
879 attp_send_cl_msg(*p_tcb, nullptr, GATT_HANDLE_VALUE_CONF, &gatt_cl_msg);
Jakub Pawlowskif4c02922017-05-30 11:21:04 -0700880
881 p_tcb->ind_count = 0;
882
Myles Watson911d1ae2016-11-28 16:44:40 -0800883 return ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800884}
885
Myles Watsonee96a3c2016-11-23 14:49:54 -0800886/******************************************************************************/
Myles Watson9ca07092016-11-28 16:41:53 -0800887/* */
888/* GATT APIs */
889/* */
Myles Watsonee96a3c2016-11-23 14:49:54 -0800890/******************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800891/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800892 *
893 * Function GATT_SetIdleTimeout
894 *
Myles Watson9ca07092016-11-28 16:41:53 -0800895 * Description This function (common to both client and server) sets the
896 * idle timeout for a tansport connection
Myles Watsonee96a3c2016-11-23 14:49:54 -0800897 *
898 * Parameter bd_addr: target device bd address.
899 * idle_tout: timeout value in seconds.
900 *
901 * Returns void
902 *
903 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -0700904void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout,
Myles Watson911d1ae2016-11-28 16:44:40 -0800905 tBT_TRANSPORT transport) {
906 tGATT_TCB* p_tcb;
907 bool status = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800908
Myles Watson911d1ae2016-11-28 16:44:40 -0800909 p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
910 if (p_tcb != NULL) {
911 if (p_tcb->att_lcid == L2CAP_ATT_CID) {
912 status = L2CA_SetFixedChannelTout(bd_addr, L2CAP_ATT_CID, idle_tout);
Satya Calloji444a8da2015-03-06 10:38:22 -0800913
Myles Watson911d1ae2016-11-28 16:44:40 -0800914 if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
915 L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
916 GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
917 BT_TRANSPORT_LE);
918 } else {
919 status = L2CA_SetIdleTimeout(p_tcb->att_lcid, idle_tout, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800920 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800921 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800922
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700923 VLOG(1) << __func__
924 << StringPrintf(" idle_tout=%d status=%d(1-OK 0-not performed)",
925 idle_tout, status);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800926}
927
The Android Open Source Project5738f832012-12-12 16:00:35 -0800928/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800929 *
930 * Function GATT_Register
931 *
932 * Description This function is called to register an application
933 * with GATT
934 *
935 * Parameter p_app_uuid128: Application UUID
936 * p_cb_info: callback functions.
937 *
Myles Watson9ca07092016-11-28 16:41:53 -0800938 * Returns 0 for error, otherwise the index of the client registered
939 * with GATT
Myles Watsonee96a3c2016-11-23 14:49:54 -0800940 *
941 ******************************************************************************/
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700942tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800943 tGATT_REG* p_reg;
944 uint8_t i_gatt_if = 0;
945 tGATT_IF gatt_if = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800946
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700947 LOG(INFO) << __func__ << app_uuid128;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800948
Myles Watson911d1ae2016-11-28 16:44:40 -0800949 for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
950 i_gatt_if++, p_reg++) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700951 if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700952 LOG(ERROR) << "application already registered.";
Myles Watson911d1ae2016-11-28 16:44:40 -0800953 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800954 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800955 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800956
Myles Watson911d1ae2016-11-28 16:44:40 -0800957 for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS;
958 i_gatt_if++, p_reg++) {
959 if (!p_reg->in_use) {
960 memset(p_reg, 0, sizeof(tGATT_REG));
961 i_gatt_if++; /* one based number */
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700962 p_reg->app_uuid128 = app_uuid128;
Myles Watson911d1ae2016-11-28 16:44:40 -0800963 gatt_if = p_reg->gatt_if = (tGATT_IF)i_gatt_if;
964 p_reg->app_cb = *p_cb_info;
965 p_reg->in_use = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800966
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700967 LOG(INFO) << "allocated gatt_if=" << +gatt_if;
Myles Watson911d1ae2016-11-28 16:44:40 -0800968 return gatt_if;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800969 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800970 }
Jakub Pawlowskidb4ec762016-05-13 13:09:08 -0700971
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700972 LOG(ERROR) << "can't Register GATT client, MAX client reached: "
973 << GATT_MAX_APPS;
Myles Watson911d1ae2016-11-28 16:44:40 -0800974 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800975}
976
The Android Open Source Project5738f832012-12-12 16:00:35 -0800977/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800978 *
979 * Function GATT_Deregister
980 *
981 * Description This function deregistered the application from GATT.
982 *
983 * Parameters gatt_if: applicaiton interface.
984 *
985 * Returns None.
986 *
987 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800988void GATT_Deregister(tGATT_IF gatt_if) {
Jakub Pawlowskief65d642017-09-06 08:41:46 -0700989 VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
Jakub Pawlowski6395f152017-05-09 05:02:38 -0700990
991 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
Myles Watson911d1ae2016-11-28 16:44:40 -0800992 /* Index 0 is GAP and is never deregistered */
993 if ((gatt_if == 0) || (p_reg == NULL)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -0700994 LOG(ERROR) << "invalid gatt_if: " << +gatt_if;
Myles Watson911d1ae2016-11-28 16:44:40 -0800995 return;
996 }
997
998 /* stop all services */
999 /* todo an applcaiton can not be deregistered if its services is also used by
1000 other application
1001 deregisteration need to bed performed in an orderly fashion
1002 no check for now */
Chao Quana5aca8f2017-07-24 19:46:53 +08001003 for (auto it = gatt_cb.srv_list_info->begin(); it != gatt_cb.srv_list_info->end(); ) {
1004 if (it->gatt_if == gatt_if) {
1005 GATTS_StopService(it++->s_hdl);
1006 } else {
1007 ++it;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001008 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001009 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001010
Myles Watson911d1ae2016-11-28 16:44:40 -08001011 /* free all services db buffers if owned by this application */
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -07001012 gatt_free_srvc_db_buffer_app_id(p_reg->app_uuid128);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001013
Myles Watson911d1ae2016-11-28 16:44:40 -08001014 /* When an application deregisters, check remove the link associated with the
1015 * app */
Jakub Pawlowski6395f152017-05-09 05:02:38 -07001016 tGATT_TCB* p_tcb;
1017 int i, j;
Myles Watson911d1ae2016-11-28 16:44:40 -08001018 for (i = 0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++) {
1019 if (p_tcb->in_use) {
1020 if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
1021 gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1022 }
1023
Jakub Pawlowski6395f152017-05-09 05:02:38 -07001024 tGATT_CLCB* p_clcb;
Myles Watson911d1ae2016-11-28 16:44:40 -08001025 for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB;
1026 j++, p_clcb++) {
1027 if (p_clcb->in_use && (p_clcb->p_reg->gatt_if == gatt_if) &&
1028 (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
1029 alarm_cancel(p_clcb->gatt_rsp_timer_ent);
1030 gatt_clcb_dealloc(p_clcb);
1031 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001032 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001033 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001034 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001035 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001036
Myles Watson911d1ae2016-11-28 16:44:40 -08001037 gatt_deregister_bgdev_list(gatt_if);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001038
Myles Watson911d1ae2016-11-28 16:44:40 -08001039 memset(p_reg, 0, sizeof(tGATT_REG));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001040}
1041
The Android Open Source Project5738f832012-12-12 16:00:35 -08001042/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001043 *
1044 * Function GATT_StartIf
1045 *
Myles Watson9ca07092016-11-28 16:41:53 -08001046 * Description This function is called after registration to start
1047 * receiving callbacks for registered interface. Function may
1048 * call back with connection status and queued notifications
Myles Watsonee96a3c2016-11-23 14:49:54 -08001049 *
1050 * Parameter gatt_if: applicaiton interface.
1051 *
1052 * Returns None.
1053 *
1054 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001055void GATT_StartIf(tGATT_IF gatt_if) {
1056 tGATT_REG* p_reg;
1057 tGATT_TCB* p_tcb;
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001058 RawAddress bda;
Myles Watson911d1ae2016-11-28 16:44:40 -08001059 uint8_t start_idx, found_idx;
1060 uint16_t conn_id;
1061 tGATT_TRANSPORT transport;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001062
Jakub Pawlowskief65d642017-09-06 08:41:46 -07001063 VLOG(1) << __func__ << " gatt_if=" << gatt_if;
Myles Watson911d1ae2016-11-28 16:44:40 -08001064 p_reg = gatt_get_regcb(gatt_if);
1065 if (p_reg != NULL) {
1066 start_idx = 0;
1067 while (
1068 gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
1069 p_tcb = gatt_find_tcb_by_addr(bda, transport);
1070 if (p_reg->app_cb.p_conn_cb && p_tcb) {
1071 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1072 (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, true, 0, transport);
1073 }
1074 start_idx = ++found_idx;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001075 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001076 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001077}
1078
The Android Open Source Project5738f832012-12-12 16:00:35 -08001079/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001080 *
1081 * Function GATT_Connect
1082 *
Myles Watson9ca07092016-11-28 16:41:53 -08001083 * Description This function initiate a connecttion to a remote device on
1084 * GATT channel.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001085 *
1086 * Parameters gatt_if: applicaiton interface
1087 * bd_addr: peer device address.
Myles Watson9ca07092016-11-28 16:41:53 -08001088 * is_direct: is a direct conenection or a background auto
1089 * connection
Myles Watsonee96a3c2016-11-23 14:49:54 -08001090 *
Myles Watson9ca07092016-11-28 16:41:53 -08001091 * Returns true if connection started; false if connection start
1092 * failure.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001093 *
1094 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001095bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
Myles Watson911d1ae2016-11-28 16:44:40 -08001096 tBT_TRANSPORT transport, bool opportunistic) {
Jakub Pawlowski96fb2732017-03-24 17:52:02 -07001097 uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
1098 return GATT_Connect(gatt_if, bd_addr, is_direct, transport, opportunistic,
1099 phy);
1100}
1101
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001102bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
Jakub Pawlowski96fb2732017-03-24 17:52:02 -07001103 tBT_TRANSPORT transport, bool opportunistic,
1104 uint8_t initiating_phys) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001105 tGATT_REG* p_reg;
1106 bool status = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001107
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001108 LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << " " << bd_addr;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001109
Myles Watson911d1ae2016-11-28 16:44:40 -08001110 /* Make sure app is registered */
1111 p_reg = gatt_get_regcb(gatt_if);
1112 if (p_reg == NULL) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001113 LOG(ERROR) << "gatt_if = " << gatt_if << " is not registered";
Myles Watson911d1ae2016-11-28 16:44:40 -08001114 return (false);
1115 }
1116
1117 if (is_direct)
Jakub Pawlowski96fb2732017-03-24 17:52:02 -07001118 status = gatt_act_connect(p_reg, bd_addr, transport, opportunistic,
1119 initiating_phys);
Myles Watson911d1ae2016-11-28 16:44:40 -08001120 else {
1121 if (transport == BT_TRANSPORT_LE)
1122 status = gatt_update_auto_connect_dev(gatt_if, true, bd_addr);
1123 else {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001124 LOG(ERROR) << "Unsupported transport for background connection";
The Android Open Source Project5738f832012-12-12 16:00:35 -08001125 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001126 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001127
Myles Watson911d1ae2016-11-28 16:44:40 -08001128 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001129}
1130
1131/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001132 *
1133 * Function GATT_CancelConnect
1134 *
Myles Watson9ca07092016-11-28 16:41:53 -08001135 * Description This function terminate the connection initaition to a
1136 * remote device on GATT channel.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001137 *
Myles Watson9ca07092016-11-28 16:41:53 -08001138 * Parameters gatt_if: client interface. If 0 used as unconditionally
1139 * disconnect, typically used for direct connection
1140 * cancellation.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001141 * bd_addr: peer device address.
1142 *
Myles Watson9ca07092016-11-28 16:41:53 -08001143 * Returns true if the connection started; false otherwise.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001144 *
1145 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001146bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001147 bool is_direct) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001148 LOG(INFO) << __func__ << ": gatt_if=" << +gatt_if;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001149
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001150 if (gatt_if && !gatt_get_regcb(gatt_if)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001151 LOG(ERROR) << "gatt_if =" << +gatt_if << " is not registered";
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001152 return false;
Myles Watson911d1ae2016-11-28 16:44:40 -08001153 }
1154
1155 if (is_direct) {
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001156 if (gatt_if) {
1157 return gatt_cancel_open(gatt_if, bd_addr);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001158 }
Jakub Pawlowski7cfd8392017-06-06 10:03:07 -07001159
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001160 VLOG(1) << " unconditional";
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001161 /* only LE connection can be cancelled */
1162 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
1163 if (!p_tcb || p_tcb->app_hold_link.empty()) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001164 LOG(ERROR) << __func__ << " no app found";
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001165 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001166 }
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001167
1168 for (auto it = p_tcb->app_hold_link.begin();
1169 it != p_tcb->app_hold_link.end();) {
1170 auto next = std::next(it);
1171 // gatt_cancel_open modifies the app_hold_link.
1172 if (!gatt_cancel_open(*it, bd_addr)) return false;
1173
1174 it = next;
1175 }
1176
1177 return true;
1178 }
1179 // is not direct
1180
1181 if (gatt_if) return gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
1182
1183 if (!gatt_clear_bg_dev_for_addr(bd_addr)) {
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001184 LOG(ERROR)
1185 << __func__
1186 << ": no app associated with the bg device for unconditional removal";
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001187 return false;
Myles Watson911d1ae2016-11-28 16:44:40 -08001188 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001189
Jakub Pawlowski3dda8982017-06-05 15:23:32 -07001190 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001191}
1192
1193/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001194 *
1195 * Function GATT_Disconnect
1196 *
Myles Watson9ca07092016-11-28 16:41:53 -08001197 * Description This function disconnects the GATT channel for this
1198 * registered application.
Myles Watsonee96a3c2016-11-23 14:49:54 -08001199 *
1200 * Parameters conn_id: connection identifier.
1201 *
1202 * Returns GATT_SUCCESS if disconnected.
1203 *
1204 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001205tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
1206 tGATT_STATUS ret = GATT_ILLEGAL_PARAMETER;
1207 tGATT_TCB* p_tcb = NULL;
1208 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1209 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001210
Jakub Pawlowskid8be0e52017-06-08 17:04:47 -07001211 LOG(INFO) << __func__ << " conn_id=" << +conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001212
Myles Watson911d1ae2016-11-28 16:44:40 -08001213 p_tcb = gatt_get_tcb_by_idx(tcb_idx);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001214
Myles Watson911d1ae2016-11-28 16:44:40 -08001215 if (p_tcb) {
1216 gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
1217 ret = GATT_SUCCESS;
1218 }
1219 return ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001220}
1221
The Android Open Source Project5738f832012-12-12 16:00:35 -08001222/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001223 *
1224 * Function GATT_GetConnectionInfor
1225 *
Myles Watson9ca07092016-11-28 16:41:53 -08001226 * Description This function uses conn_id to find its associated BD address
1227 * and application interface
Myles Watsonee96a3c2016-11-23 14:49:54 -08001228 *
1229 * Parameters conn_id: connection id (input)
1230 * p_gatt_if: applicaiton interface (output)
1231 * bd_addr: peer device address. (output)
1232 *
1233 * Returns true the ligical link information is found for conn_id
1234 *
1235 ******************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -08001236bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if,
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001237 RawAddress& bd_addr, tBT_TRANSPORT* p_transport) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001238 tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
1239 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1240 uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1241 tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
1242 bool status = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001243
Jakub Pawlowskief65d642017-09-06 08:41:46 -07001244 VLOG(1) << __func__ << " conn_id=" << +conn_id;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001245
Myles Watson911d1ae2016-11-28 16:44:40 -08001246 if (p_tcb && p_reg) {
Jakub Pawlowskic2276b02017-06-09 16:00:25 -07001247 bd_addr = p_tcb->peer_bda;
Myles Watson911d1ae2016-11-28 16:44:40 -08001248 *p_gatt_if = gatt_if;
1249 *p_transport = p_tcb->transport;
1250 status = true;
1251 }
1252 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001253}
1254
The Android Open Source Project5738f832012-12-12 16:00:35 -08001255/*******************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -08001256 *
1257 * Function GATT_GetConnIdIfConnected
1258 *
Myles Watson9ca07092016-11-28 16:41:53 -08001259 * Description This function find the conn_id if the logical link for BD
1260 * address and applciation interface is connected
Myles Watsonee96a3c2016-11-23 14:49:54 -08001261 *
1262 * Parameters gatt_if: applicaiton interface (input)
1263 * bd_addr: peer device address. (input)
1264 * p_conn_id: connection id (output)
1265 * transport: transport option
1266 *
1267 * Returns true the logical link is connected
1268 *
1269 ******************************************************************************/
Jakub Pawlowskia484a882017-06-24 17:30:18 -07001270bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr,
Myles Watson911d1ae2016-11-28 16:44:40 -08001271 uint16_t* p_conn_id, tBT_TRANSPORT transport) {
1272 tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
1273 tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
1274 bool status = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001275
Myles Watson911d1ae2016-11-28 16:44:40 -08001276 if (p_reg && p_tcb && (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)) {
1277 *p_conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
1278 status = true;
1279 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001280
Jakub Pawlowskief65d642017-09-06 08:41:46 -07001281 VLOG(1) << __func__ << " status= " << +status;
Myles Watson911d1ae2016-11-28 16:44:40 -08001282 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001283}