The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1 | /****************************************************************************** |
| 2 | * |
Jakub Pawlowski | 5b790fe | 2017-09-18 09:00:20 -0700 | [diff] [blame] | 3 | * Copyright 1999-2012 Broadcom Corporation |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 4 | * |
| 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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 26 | #include <base/strings/string_number_conversions.h> |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 27 | #include <base/strings/stringprintf.h> |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 28 | #include <stdio.h> |
| 29 | #include <string.h> |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 30 | #include "bt_common.h" |
| 31 | #include "btm_int.h" |
Jakub Pawlowski | 96fb273 | 2017-03-24 17:52:02 -0700 | [diff] [blame] | 32 | #include "device/include/controller.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 33 | #include "gatt_api.h" |
| 34 | #include "gatt_int.h" |
| 35 | #include "l2c_api.h" |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 36 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 37 | using base::StringPrintf; |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 38 | using bluetooth::Uuid; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 39 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 40 | /** |
| 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 | **/ |
| 44 | tGATT_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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 55 | /***************************************************************************** |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 56 | * |
| 57 | * GATT SERVER API |
| 58 | * |
| 59 | *****************************************************************************/ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 60 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 61 | * |
| 62 | * Function GATTS_AddHandleRange |
| 63 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 64 | * Description This function add the allocated handles range for the |
| 65 | * specified application UUID, service UUID and service |
| 66 | * instance |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 67 | * |
| 68 | * Parameter p_hndl_range: pointer to allocated handles information |
| 69 | * |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 70 | **/ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 71 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 72 | void GATTS_AddHandleRange(tGATTS_HNDL_RANGE* p_hndl_range) { |
| 73 | gatt_add_an_item_to_list(p_hndl_range->s_handle); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 74 | } |
| 75 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 76 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 77 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 89 | bool 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 96 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 97 | return status; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 98 | } |
| 99 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 100 | static 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 Pawlowski | 7680a0b | 2016-11-08 17:23:11 -0800 | [diff] [blame] | 103 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 104 | 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 113 | LOG(ERROR) << __func__ << ": Unknown element type: " << el->type; |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 114 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 115 | return db_size; |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 116 | } |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 117 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 118 | static 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 Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 123 | return true; |
| 124 | } |
| 125 | return false; |
| 126 | } |
| 127 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 128 | /** Update the the last primary info for the service list info */ |
| 129 | static 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 136 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 137 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 151 | uint16_t GATTS_AddService(tGATT_IF gatt_if, btgatt_db_element_t* service, |
| 152 | int count) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 153 | uint16_t s_hdl = 0; |
| 154 | bool save_hdl = false; |
| 155 | tGATT_REG* p_reg = gatt_get_regcb(gatt_if); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 156 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 157 | bool is_pri = (service->type == BTGATT_DB_PRIMARY_SERVICE) ? true : false; |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 158 | Uuid svc_uuid = service->uuid; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 159 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 160 | LOG(INFO) << __func__; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 161 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 162 | if (!p_reg) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 163 | LOG(ERROR) << "Inavlid gatt_if=" << +gatt_if; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 164 | return GATT_INTERNAL_ERROR; |
| 165 | } |
| 166 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 167 | uint16_t num_handles = compute_service_size(service, count); |
| 168 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 169 | if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 170 | s_hdl = gatt_cb.hdl_cfg.gatt_start_hdl; |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 171 | } else if (svc_uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 172 | s_hdl = gatt_cb.hdl_cfg.gap_start_hdl; |
| 173 | } else { |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 174 | if (!gatt_cb.hdl_list_info->empty()) { |
| 175 | s_hdl = gatt_cb.hdl_list_info->front().asgn_range.e_handle + 1; |
| 176 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 177 | |
| 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 186 | LOG(ERROR) << StringPrintf( |
| 187 | "GATTS_ReserveHandles: no handles, s_hdl: %u needed: %u", s_hdl, |
| 188 | num_handles); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 189 | return GATT_INTERNAL_ERROR; |
| 190 | } |
| 191 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 192 | tGATT_HDL_LIST_ELEM& list = gatt_add_an_item_to_list(s_hdl); |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 193 | list.asgn_range.app_uuid128 = p_reg->app_uuid128; |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 194 | 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 198 | |
| 199 | if (save_hdl) { |
| 200 | if (gatt_cb.cb_info.p_nv_save_callback) |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 201 | (*gatt_cb.cb_info.p_nv_save_callback)(true, &list.asgn_range); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 202 | } |
| 203 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 204 | gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 205 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 206 | VLOG(1) << StringPrintf( |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 207 | "%s: handles needed:%u s_hdl=%u e_hdl=%u %s is_primary=%d", __func__, |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 208 | num_handles, list.asgn_range.s_handle, list.asgn_range.e_handle, |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 209 | list.asgn_range.svc_uuid.ToString().c_str(), list.asgn_range.is_primary); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 210 | |
| 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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 215 | const Uuid& uuid = el->uuid; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 216 | |
| 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 223 | VLOG(1) << StringPrintf( |
| 224 | "Invalid configuration property=0x%02x perm=0x%04x ", |
| 225 | el->properties, el->permissions); |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 226 | return GATT_INTERNAL_ERROR; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 227 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 228 | |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 229 | if (is_gatt_attr_type(uuid)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 230 | LOG(ERROR) << StringPrintf( |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 231 | "%s: attept to add characteristic with UUID equal to GATT " |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 232 | "Attribute Type %s ", |
| 233 | __func__, uuid.ToString().c_str()); |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 234 | return GATT_INTERNAL_ERROR; |
| 235 | } |
| 236 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 237 | el->attribute_handle = gatts_add_characteristic( |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 238 | list.svc_db, el->permissions, el->properties, uuid); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 239 | } else if (el->type == BTGATT_DB_DESCRIPTOR) { |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 240 | if (is_gatt_attr_type(uuid)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 241 | LOG(ERROR) << StringPrintf( |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 242 | "%s: attept to add descriptor with UUID equal to GATT " |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 243 | "Attribute Type %s", |
| 244 | __func__, uuid.ToString().c_str()); |
Jakub Pawlowski | 671ad66 | 2017-05-10 04:39:26 -0700 | [diff] [blame] | 245 | return GATT_INTERNAL_ERROR; |
| 246 | } |
| 247 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 248 | el->attribute_handle = |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 249 | gatts_add_char_descr(list.svc_db, el->permissions, uuid); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 250 | } 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 Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 253 | if (p_incl_decl == nullptr) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 254 | VLOG(1) << "Included Service not created"; |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 255 | return GATT_INTERNAL_ERROR; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 256 | } |
| 257 | |
| 258 | el->attribute_handle = gatts_add_included_service( |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 259 | list.svc_db, p_incl_decl->asgn_range.s_handle, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 260 | p_incl_decl->asgn_range.e_handle, p_incl_decl->asgn_range.svc_uuid); |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 261 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 262 | } |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 263 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 264 | LOG(INFO) << __func__ << ": service parsed correctly, now starting"; |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 265 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 266 | /*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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 283 | elem.app_uuid = list.asgn_range.app_uuid128; |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 284 | 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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 288 | 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 Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 290 | } else { |
| 291 | elem.sdp_handle = 0; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 292 | } |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 293 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 294 | gatt_update_last_pri_srv_info(); |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 295 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 296 | 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 Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 299 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 300 | gatt_proc_srv_chg(); |
Jakub Pawlowski | a641b6f | 2016-03-26 00:47:23 -0700 | [diff] [blame] | 301 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 302 | return GATT_SERVICE_STARTED; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 303 | } |
| 304 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 305 | bool is_active_service(const Uuid& app_uuid128, Uuid* p_svc_uuid, |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 306 | uint16_t start_handle) { |
| 307 | for (auto& info : *gatt_cb.srv_list_info) { |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 308 | Uuid* p_this_uuid = gatts_get_service_uuid(info.p_db); |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 309 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 310 | 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 Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 313 | return true; |
| 314 | } |
| 315 | } |
| 316 | return false; |
| 317 | } |
| 318 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 319 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 320 | * |
| 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 Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 329 | * Returns true if the operation succeeded, false if the handle block |
| 330 | * was not found. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 331 | * |
| 332 | ******************************************************************************/ |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 333 | bool GATTS_DeleteService(tGATT_IF gatt_if, Uuid* p_svc_uuid, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 334 | uint16_t svc_inst) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 335 | VLOG(1) << __func__; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 336 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 337 | tGATT_REG* p_reg = gatt_get_regcb(gatt_if); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 338 | if (p_reg == NULL) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 339 | LOG(ERROR) << "Applicaiton not foud"; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 340 | return false; |
| 341 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 342 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 343 | auto it = |
| 344 | gatt_find_hdl_buffer_by_app_id(p_reg->app_uuid128, p_svc_uuid, svc_inst); |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 345 | if (it == gatt_cb.hdl_list_info->end()) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 346 | LOG(ERROR) << "No Service found"; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 347 | return false; |
| 348 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 349 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 350 | gatt_proc_srv_chg(); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 351 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 352 | if (is_active_service(p_reg->app_uuid128, p_svc_uuid, svc_inst)) { |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 353 | GATTS_StopService(it->asgn_range.s_handle); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 354 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 355 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 356 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 358 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 359 | if ((it->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl) && |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 360 | gatt_cb.cb_info.p_nv_save_callback) |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 361 | (*gatt_cb.cb_info.p_nv_save_callback)(false, &it->asgn_range); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 362 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 363 | gatt_cb.hdl_list_info->erase(it); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 364 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 365 | } |
| 366 | |
| 367 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 368 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 378 | void GATTS_StopService(uint16_t service_handle) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 379 | LOG(INFO) << __func__ << ": 0x" << std::hex << +service_handle; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 380 | |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 381 | auto it = gatt_sr_find_i_rcb_by_handle(service_handle); |
| 382 | if (it == gatt_cb.srv_list_info->end()) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 383 | LOG(ERROR) << StringPrintf("%s: service_handle: %u is not in use", __func__, |
| 384 | service_handle); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 385 | } |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 386 | |
| 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 393 | } |
| 394 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 395 | * |
| 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 Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 401 | * attr_handle: Attribute handle of this handle value |
| 402 | * indication. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 403 | * val_len: Length of the indicated attribute value. |
| 404 | * p_val: Pointer to the indicated attribute value data. |
| 405 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 406 | * Returns GATT_SUCCESS if sucessfully sent or queued; otherwise error |
| 407 | * code. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 408 | * |
| 409 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 410 | tGATT_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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 413 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 414 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 421 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 422 | VLOG(1) << __func__; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 423 | if ((p_reg == NULL) || (p_tcb == NULL)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 424 | LOG(ERROR) << __func__ << ": Unknown conn_id: " << +conn_id; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 425 | return (tGATT_STATUS)GATT_INVALID_CONN_ID; |
| 426 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 427 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 428 | 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 437 | VLOG(1) << "Add a pending indication"; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 438 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 443 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 444 | } else { |
Myles Watson | 8d74904 | 2017-09-19 10:01:28 -0700 | [diff] [blame] | 445 | 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 448 | if (p_msg != NULL) { |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 449 | cmd_status = attp_send_sr_msg(*p_tcb, p_msg); |
Andre Eisenbach | 17b04bd | 2014-03-28 14:54:22 -0700 | [diff] [blame] | 450 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 451 | 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 Eisenbach | 17b04bd | 2014-03-28 14:54:22 -0700 | [diff] [blame] | 455 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 456 | } |
| 457 | return cmd_status; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 458 | } |
| 459 | |
| 460 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 461 | * |
| 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 Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 467 | * attr_handle: Attribute handle of this handle value |
| 468 | * indication. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 469 | * 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 475 | tGATT_STATUS GATTS_HandleValueNotification(uint16_t conn_id, |
| 476 | uint16_t attr_handle, |
| 477 | uint16_t val_len, uint8_t* p_val) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 478 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 483 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 484 | VLOG(1) << __func__; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 485 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 486 | if ((p_reg == NULL) || (p_tcb == NULL)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 487 | LOG(ERROR) << __func__ << "Unknown conn_id: " << conn_id; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 488 | return (tGATT_STATUS)GATT_INVALID_CONN_ID; |
| 489 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 490 | |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 491 | if (!GATT_HANDLE_IS_VALID(attr_handle)) { |
| 492 | return GATT_ILLEGAL_PARAMETER; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 493 | } |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 494 | |
| 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 Watson | 8d74904 | 2017-09-19 10:01:28 -0700 | [diff] [blame] | 501 | tGATT_SR_MSG gatt_sr_msg; |
| 502 | gatt_sr_msg.attr_value = notif; |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 503 | BT_HDR* p_buf = |
Myles Watson | 8d74904 | 2017-09-19 10:01:28 -0700 | [diff] [blame] | 504 | attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_NOTIF, &gatt_sr_msg); |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 505 | if (p_buf != NULL) { |
| 506 | cmd_sent = attp_send_sr_msg(*p_tcb, p_buf); |
| 507 | } else |
| 508 | cmd_sent = GATT_NO_RESOURCES; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 509 | return cmd_sent; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 510 | } |
| 511 | |
| 512 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 513 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 526 | tGATT_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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 533 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 534 | VLOG(1) << __func__ |
| 535 | << StringPrintf(": conn_id: %u trans_id: %u Status: 0x%04x", |
| 536 | conn_id, trans_id, status); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 537 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 538 | if ((p_reg == NULL) || (p_tcb == NULL)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 539 | LOG(ERROR) << StringPrintf("Unknown conn_id: %u ", conn_id); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 540 | return (tGATT_STATUS)GATT_INVALID_CONN_ID; |
| 541 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 542 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 543 | if (p_tcb->sr_cmd.trans_id != trans_id) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 544 | LOG(ERROR) << StringPrintf("conn_id: %u waiting for op_code = %02x", |
| 545 | conn_id, p_tcb->sr_cmd.op_code); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 546 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 547 | return (GATT_WRONG_STATE); |
| 548 | } |
| 549 | /* Process App response */ |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 550 | cmd_sent = gatt_sr_process_app_rsp(*p_tcb, gatt_if, trans_id, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 551 | p_tcb->sr_cmd.op_code, status, p_msg); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 552 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 553 | return cmd_sent; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 554 | } |
| 555 | |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 556 | /******************************************************************************/ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 557 | /* GATT Profile Srvr Functions */ |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 558 | /******************************************************************************/ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 559 | |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 560 | /******************************************************************************/ |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 561 | /* */ |
| 562 | /* GATT CLIENT APIs */ |
| 563 | /* */ |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 564 | /******************************************************************************/ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 565 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 566 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 567 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 578 | tGATT_STATUS GATTC_ConfigureMTU(uint16_t conn_id, uint16_t mtu) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 579 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 583 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 584 | VLOG(1) << __func__ << StringPrintf("conn_id=%d mtu=%d", conn_id, mtu); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 585 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 586 | 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 | } |
liuchao | 18738c3 | 2016-11-14 16:13:10 +0800 | [diff] [blame] | 590 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 591 | /* 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 595 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 596 | if (gatt_is_clcb_allocated(conn_id)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 597 | LOG(ERROR) << "GATT_BUSY conn_id = " << +conn_id; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 598 | return GATT_BUSY; |
| 599 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 600 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 601 | tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id); |
| 602 | if (!p_clcb) return GATT_NO_RESOURCES; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 603 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 604 | p_clcb->p_tcb->payload_size = mtu; |
| 605 | p_clcb->operation = GATTC_OPTYPE_CONFIG; |
Myles Watson | 8d74904 | 2017-09-19 10:01:28 -0700 | [diff] [blame] | 606 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 609 | } |
| 610 | |
| 611 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 612 | * |
| 613 | * Function GATTC_Discover |
| 614 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 615 | * Description This function is called to do a discovery procedure on ATT |
| 616 | * server. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 617 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 625 | tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type, |
| 626 | tGATT_DISC_PARAM* p_param) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 627 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 631 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 632 | LOG(INFO) << __func__ |
| 633 | << StringPrintf(" conn_id=%d disc_type=%d", conn_id, disc_type); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 634 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 635 | if ((p_tcb == NULL) || (p_reg == NULL) || (p_param == NULL) || |
| 636 | (disc_type >= GATT_DISC_MAX)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 637 | LOG(ERROR) << StringPrintf("Illegal param: disc_type %d conn_id = %d", |
| 638 | disc_type, conn_id); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 639 | return GATT_ILLEGAL_PARAMETER; |
| 640 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 641 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 642 | 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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 645 | (disc_type == GATT_DISC_SRVC_BY_UUID && p_param->service.IsEmpty())) { |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 646 | return GATT_ILLEGAL_PARAMETER; |
| 647 | } |
| 648 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 649 | if (gatt_is_clcb_allocated(conn_id)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 650 | LOG(ERROR) << __func__ << "GATT_BUSY conn_id = " << +conn_id; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 651 | return GATT_BUSY; |
| 652 | } |
| 653 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 654 | tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id); |
| 655 | if (!p_clcb) return GATT_NO_RESOURCES; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 656 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 657 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 662 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 663 | gatt_act_discovery(p_clcb); |
| 664 | return GATT_SUCCESS; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 665 | } |
| 666 | |
| 667 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 668 | * |
| 669 | * Function GATTC_Read |
| 670 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 671 | * Description This function is called to read the value of an attribute |
| 672 | * from the server. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 673 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 681 | tGATT_STATUS GATTC_Read(uint16_t conn_id, tGATT_READ_TYPE type, |
| 682 | tGATT_READ_PARAM* p_read) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 683 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 687 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 688 | VLOG(1) << __func__ << StringPrintf(" conn_id=%d type=%d", conn_id, type); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 689 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 690 | if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) || |
| 691 | ((type >= GATT_READ_MAX) || (type == 0))) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 692 | LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id, |
| 693 | type); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 694 | return GATT_ILLEGAL_PARAMETER; |
| 695 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 696 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 697 | if (gatt_is_clcb_allocated(conn_id)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 698 | LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 699 | return GATT_BUSY; |
| 700 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 701 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 702 | tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id); |
| 703 | if (!p_clcb) return GATT_NO_RESOURCES; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 704 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 705 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 709 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 710 | 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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 715 | p_clcb->uuid = p_read->service.uuid; |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 716 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 725 | } |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 726 | case GATT_READ_BY_HANDLE: |
| 727 | case GATT_READ_PARTIAL: |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 728 | p_clcb->uuid = Uuid::kEmpty; |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 729 | 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 738 | } |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 739 | |
| 740 | /* start security check */ |
| 741 | gatt_security_check_start(p_clcb); |
| 742 | return GATT_SUCCESS; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 743 | } |
| 744 | |
| 745 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 746 | * |
| 747 | * Function GATTC_Write |
| 748 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 749 | * Description This function is called to write the value of an attribute |
| 750 | * to the server. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 751 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 759 | tGATT_STATUS GATTC_Write(uint16_t conn_id, tGATT_WRITE_TYPE type, |
| 760 | tGATT_VALUE* p_write) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 761 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 765 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 766 | 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 769 | LOG(ERROR) << __func__ |
| 770 | << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id, |
| 771 | type); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 772 | return GATT_ILLEGAL_PARAMETER; |
| 773 | } |
| 774 | |
| 775 | if (gatt_is_clcb_allocated(conn_id)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 776 | LOG(ERROR) << StringPrintf("GATT_BUSY conn_id = %d", conn_id); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 777 | return GATT_BUSY; |
| 778 | } |
| 779 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 780 | tGATT_CLCB* p_clcb = gatt_clcb_alloc(conn_id); |
| 781 | if (!p_clcb) return GATT_NO_RESOURCES; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 782 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 783 | p_clcb->operation = GATTC_OPTYPE_WRITE; |
| 784 | p_clcb->op_subtype = type; |
| 785 | p_clcb->auth_req = p_write->auth_req; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 786 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 787 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 789 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 790 | 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 794 | } |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 795 | |
| 796 | gatt_security_check_start(p_clcb); |
| 797 | return GATT_SUCCESS; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 798 | } |
| 799 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 800 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 801 | * |
| 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 Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 808 | * is_execute - to execute or cancel the prepared write |
| 809 | * request(s) |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 810 | * |
| 811 | * Returns GATT_SUCCESS if command started successfully. |
| 812 | * |
| 813 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 814 | tGATT_STATUS GATTC_ExecuteWrite(uint16_t conn_id, bool is_execute) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 815 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 819 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 820 | VLOG(1) << __func__ |
| 821 | << StringPrintf(": conn_id=%d is_execute=%d", conn_id, is_execute); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 822 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 823 | if ((p_tcb == NULL) || (p_reg == NULL)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 824 | LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d", conn_id); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 825 | return GATT_ILLEGAL_PARAMETER; |
| 826 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 827 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 828 | if (gatt_is_clcb_allocated(conn_id)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 829 | LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 830 | return GATT_BUSY; |
| 831 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 832 | |
Jakub Pawlowski | 1ad9038 | 2017-06-08 12:27:30 -0700 | [diff] [blame] | 833 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 841 | } |
| 842 | |
| 843 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 844 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 856 | tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) { |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 857 | VLOG(1) << __func__ |
| 858 | << StringPrintf(" conn_id=%d handle=0x%x", conn_id, handle); |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 859 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 860 | tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id)); |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 861 | if (!p_tcb) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 862 | LOG(ERROR) << StringPrintf(" Unknown conn_id: %u", conn_id); |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 863 | return GATT_ILLEGAL_PARAMETER; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 864 | } |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 865 | |
| 866 | if (p_tcb->ind_count == 0) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 867 | VLOG(1) << " conn_id: " << +conn_id |
| 868 | << " ignored not waiting for indicaiton ack"; |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 869 | return GATT_SUCCESS; |
| 870 | } |
| 871 | |
| 872 | alarm_cancel(p_tcb->ind_ack_timer); |
| 873 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 874 | VLOG(1) << "notif_count= " << p_tcb->ind_count; |
Jakub Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 875 | /* send confirmation now */ |
Myles Watson | 8d74904 | 2017-09-19 10:01:28 -0700 | [diff] [blame] | 876 | 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 Pawlowski | f4c0292 | 2017-05-30 11:21:04 -0700 | [diff] [blame] | 880 | |
| 881 | p_tcb->ind_count = 0; |
| 882 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 883 | return ret; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 884 | } |
| 885 | |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 886 | /******************************************************************************/ |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 887 | /* */ |
| 888 | /* GATT APIs */ |
| 889 | /* */ |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 890 | /******************************************************************************/ |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 891 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 892 | * |
| 893 | * Function GATT_SetIdleTimeout |
| 894 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 895 | * Description This function (common to both client and server) sets the |
| 896 | * idle timeout for a tansport connection |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 897 | * |
| 898 | * Parameter bd_addr: target device bd address. |
| 899 | * idle_tout: timeout value in seconds. |
| 900 | * |
| 901 | * Returns void |
| 902 | * |
| 903 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 904 | void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 905 | tBT_TRANSPORT transport) { |
| 906 | tGATT_TCB* p_tcb; |
| 907 | bool status = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 908 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 909 | 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 Calloji | 444a8da | 2015-03-06 10:38:22 -0800 | [diff] [blame] | 913 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 914 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 920 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 921 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 922 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 923 | VLOG(1) << __func__ |
| 924 | << StringPrintf(" idle_tout=%d status=%d(1-OK 0-not performed)", |
| 925 | idle_tout, status); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 926 | } |
| 927 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 928 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 929 | * |
| 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 Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 938 | * Returns 0 for error, otherwise the index of the client registered |
| 939 | * with GATT |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 940 | * |
| 941 | ******************************************************************************/ |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 942 | tGATT_IF GATT_Register(const Uuid& app_uuid128, tGATT_CBACK* p_cb_info) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 943 | tGATT_REG* p_reg; |
| 944 | uint8_t i_gatt_if = 0; |
| 945 | tGATT_IF gatt_if = 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 946 | |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 947 | LOG(INFO) << __func__ << app_uuid128; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 948 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 949 | for (i_gatt_if = 0, p_reg = gatt_cb.cl_rcb; i_gatt_if < GATT_MAX_APPS; |
| 950 | i_gatt_if++, p_reg++) { |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 951 | if (p_reg->in_use && p_reg->app_uuid128 == app_uuid128) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 952 | LOG(ERROR) << "application already registered."; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 953 | return 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 954 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 955 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 956 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 957 | 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 Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 962 | p_reg->app_uuid128 = app_uuid128; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 963 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 966 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 967 | LOG(INFO) << "allocated gatt_if=" << +gatt_if; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 968 | return gatt_if; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 969 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 970 | } |
Jakub Pawlowski | db4ec76 | 2016-05-13 13:09:08 -0700 | [diff] [blame] | 971 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 972 | LOG(ERROR) << "can't Register GATT client, MAX client reached: " |
| 973 | << GATT_MAX_APPS; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 974 | return 0; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 975 | } |
| 976 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 977 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 978 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 988 | void GATT_Deregister(tGATT_IF gatt_if) { |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 989 | VLOG(1) << __func__ << " gatt_if=" << +gatt_if; |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 990 | |
| 991 | tGATT_REG* p_reg = gatt_get_regcb(gatt_if); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 992 | /* Index 0 is GAP and is never deregistered */ |
| 993 | if ((gatt_if == 0) || (p_reg == NULL)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 994 | LOG(ERROR) << "invalid gatt_if: " << +gatt_if; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 995 | 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 Quan | a5aca8f | 2017-07-24 19:46:53 +0800 | [diff] [blame] | 1003 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1008 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1009 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1010 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1011 | /* free all services db buffers if owned by this application */ |
Jakub Pawlowski | 819e2ec | 2017-07-10 09:56:09 -0700 | [diff] [blame] | 1012 | gatt_free_srvc_db_buffer_app_id(p_reg->app_uuid128); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1013 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1014 | /* When an application deregisters, check remove the link associated with the |
| 1015 | * app */ |
Jakub Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 1016 | tGATT_TCB* p_tcb; |
| 1017 | int i, j; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1018 | 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 Pawlowski | 6395f15 | 2017-05-09 05:02:38 -0700 | [diff] [blame] | 1024 | tGATT_CLCB* p_clcb; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1025 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1032 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1033 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1034 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1035 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1036 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1037 | gatt_deregister_bgdev_list(gatt_if); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1038 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1039 | memset(p_reg, 0, sizeof(tGATT_REG)); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1040 | } |
| 1041 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1042 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1043 | * |
| 1044 | * Function GATT_StartIf |
| 1045 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1046 | * 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 Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1049 | * |
| 1050 | * Parameter gatt_if: applicaiton interface. |
| 1051 | * |
| 1052 | * Returns None. |
| 1053 | * |
| 1054 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1055 | void GATT_StartIf(tGATT_IF gatt_if) { |
| 1056 | tGATT_REG* p_reg; |
| 1057 | tGATT_TCB* p_tcb; |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 1058 | RawAddress bda; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1059 | uint8_t start_idx, found_idx; |
| 1060 | uint16_t conn_id; |
| 1061 | tGATT_TRANSPORT transport; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1062 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 1063 | VLOG(1) << __func__ << " gatt_if=" << gatt_if; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1064 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1075 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1076 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1077 | } |
| 1078 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1079 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1080 | * |
| 1081 | * Function GATT_Connect |
| 1082 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1083 | * Description This function initiate a connecttion to a remote device on |
| 1084 | * GATT channel. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1085 | * |
| 1086 | * Parameters gatt_if: applicaiton interface |
| 1087 | * bd_addr: peer device address. |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1088 | * is_direct: is a direct conenection or a background auto |
| 1089 | * connection |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1090 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1091 | * Returns true if connection started; false if connection start |
| 1092 | * failure. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1093 | * |
| 1094 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 1095 | bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1096 | tBT_TRANSPORT transport, bool opportunistic) { |
Jakub Pawlowski | 96fb273 | 2017-03-24 17:52:02 -0700 | [diff] [blame] | 1097 | 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 Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 1102 | bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct, |
Jakub Pawlowski | 96fb273 | 2017-03-24 17:52:02 -0700 | [diff] [blame] | 1103 | tBT_TRANSPORT transport, bool opportunistic, |
| 1104 | uint8_t initiating_phys) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1105 | tGATT_REG* p_reg; |
| 1106 | bool status = false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1107 | |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 1108 | LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << " " << bd_addr; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1109 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1110 | /* Make sure app is registered */ |
| 1111 | p_reg = gatt_get_regcb(gatt_if); |
| 1112 | if (p_reg == NULL) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1113 | LOG(ERROR) << "gatt_if = " << gatt_if << " is not registered"; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1114 | return (false); |
| 1115 | } |
| 1116 | |
| 1117 | if (is_direct) |
Jakub Pawlowski | 96fb273 | 2017-03-24 17:52:02 -0700 | [diff] [blame] | 1118 | status = gatt_act_connect(p_reg, bd_addr, transport, opportunistic, |
| 1119 | initiating_phys); |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1120 | else { |
| 1121 | if (transport == BT_TRANSPORT_LE) |
| 1122 | status = gatt_update_auto_connect_dev(gatt_if, true, bd_addr); |
| 1123 | else { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1124 | LOG(ERROR) << "Unsupported transport for background connection"; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1125 | } |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1126 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1127 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1128 | return status; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1129 | } |
| 1130 | |
| 1131 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1132 | * |
| 1133 | * Function GATT_CancelConnect |
| 1134 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1135 | * Description This function terminate the connection initaition to a |
| 1136 | * remote device on GATT channel. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1137 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1138 | * Parameters gatt_if: client interface. If 0 used as unconditionally |
| 1139 | * disconnect, typically used for direct connection |
| 1140 | * cancellation. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1141 | * bd_addr: peer device address. |
| 1142 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1143 | * Returns true if the connection started; false otherwise. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1144 | * |
| 1145 | ******************************************************************************/ |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 1146 | bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr, |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 1147 | bool is_direct) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1148 | LOG(INFO) << __func__ << ": gatt_if=" << +gatt_if; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1149 | |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1150 | if (gatt_if && !gatt_get_regcb(gatt_if)) { |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1151 | LOG(ERROR) << "gatt_if =" << +gatt_if << " is not registered"; |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1152 | return false; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1153 | } |
| 1154 | |
| 1155 | if (is_direct) { |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1156 | if (gatt_if) { |
| 1157 | return gatt_cancel_open(gatt_if, bd_addr); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1158 | } |
Jakub Pawlowski | 7cfd839 | 2017-06-06 10:03:07 -0700 | [diff] [blame] | 1159 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1160 | VLOG(1) << " unconditional"; |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1161 | /* 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1164 | LOG(ERROR) << __func__ << " no app found"; |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1165 | return false; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1166 | } |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1167 | |
| 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 Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1184 | LOG(ERROR) |
| 1185 | << __func__ |
| 1186 | << ": no app associated with the bg device for unconditional removal"; |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1187 | return false; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1188 | } |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1189 | |
Jakub Pawlowski | 3dda898 | 2017-06-05 15:23:32 -0700 | [diff] [blame] | 1190 | return true; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1191 | } |
| 1192 | |
| 1193 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1194 | * |
| 1195 | * Function GATT_Disconnect |
| 1196 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1197 | * Description This function disconnects the GATT channel for this |
| 1198 | * registered application. |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1199 | * |
| 1200 | * Parameters conn_id: connection identifier. |
| 1201 | * |
| 1202 | * Returns GATT_SUCCESS if disconnected. |
| 1203 | * |
| 1204 | ******************************************************************************/ |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1205 | tGATT_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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1210 | |
Jakub Pawlowski | d8be0e5 | 2017-06-08 17:04:47 -0700 | [diff] [blame] | 1211 | LOG(INFO) << __func__ << " conn_id=" << +conn_id; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1212 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1213 | p_tcb = gatt_get_tcb_by_idx(tcb_idx); |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1214 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1215 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1220 | } |
| 1221 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1222 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1223 | * |
| 1224 | * Function GATT_GetConnectionInfor |
| 1225 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1226 | * Description This function uses conn_id to find its associated BD address |
| 1227 | * and application interface |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1228 | * |
| 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 Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1236 | bool GATT_GetConnectionInfor(uint16_t conn_id, tGATT_IF* p_gatt_if, |
Jakub Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 1237 | RawAddress& bd_addr, tBT_TRANSPORT* p_transport) { |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1238 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1243 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 1244 | VLOG(1) << __func__ << " conn_id=" << +conn_id; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1245 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1246 | if (p_tcb && p_reg) { |
Jakub Pawlowski | c2276b0 | 2017-06-09 16:00:25 -0700 | [diff] [blame] | 1247 | bd_addr = p_tcb->peer_bda; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1248 | *p_gatt_if = gatt_if; |
| 1249 | *p_transport = p_tcb->transport; |
| 1250 | status = true; |
| 1251 | } |
| 1252 | return status; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1253 | } |
| 1254 | |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1255 | /******************************************************************************* |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1256 | * |
| 1257 | * Function GATT_GetConnIdIfConnected |
| 1258 | * |
Myles Watson | 9ca0709 | 2016-11-28 16:41:53 -0800 | [diff] [blame] | 1259 | * Description This function find the conn_id if the logical link for BD |
| 1260 | * address and applciation interface is connected |
Myles Watson | ee96a3c | 2016-11-23 14:49:54 -0800 | [diff] [blame] | 1261 | * |
| 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 Pawlowski | a484a88 | 2017-06-24 17:30:18 -0700 | [diff] [blame] | 1270 | bool GATT_GetConnIdIfConnected(tGATT_IF gatt_if, const RawAddress& bd_addr, |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1271 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1275 | |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1276 | 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 Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1280 | |
Jakub Pawlowski | ef65d64 | 2017-09-06 08:41:46 -0700 | [diff] [blame] | 1281 | VLOG(1) << __func__ << " status= " << +status; |
Myles Watson | 911d1ae | 2016-11-28 16:44:40 -0800 | [diff] [blame] | 1282 | return status; |
The Android Open Source Project | 5738f83 | 2012-12-12 16:00:35 -0800 | [diff] [blame] | 1283 | } |