1/****************************************************************************** 2 * 3 * Copyright (C) 2014 Broadcom Corporation 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 * Filename: btif_gatt_multi_adv_util.c 22 * 23 * Description: Multi ADV helper implementation 24 * 25 *******************************************************************************/ 26 27#define LOG_TAG "bt_btif_gatt" 28 29 30#include <stdio.h> 31#include <stdlib.h> 32#include <string.h> 33 34#include "btu.h" 35#include "bt_target.h" 36 37#if (BLE_INCLUDED == TRUE) 38 39#include <hardware/bluetooth.h> 40#include <hardware/bt_gatt.h> 41 42#include "bta_gatt_api.h" 43#include "btif_common.h" 44#include "btif_gatt_multi_adv_util.h" 45#include "btif_gatt_util.h" 46 47extern fixed_queue_t *btu_general_alarm_queue; 48 49/******************************************************************************* 50** Static variables 51********************************************************************************/ 52static int user_app_count = 0; 53static btgatt_multi_adv_common_data *p_multi_adv_com_data_cb = NULL; 54 55btgatt_multi_adv_common_data *btif_obtain_multi_adv_data_cb() 56{ 57 int max_adv_inst = BTM_BleMaxMultiAdvInstanceCount(); 58 if (0 == max_adv_inst) 59 max_adv_inst = 1; 60 61 BTIF_TRACE_DEBUG("%s, Count:%d", __FUNCTION__, max_adv_inst); 62 63 if (NULL == p_multi_adv_com_data_cb) 64 { 65 p_multi_adv_com_data_cb = osi_calloc(sizeof(btgatt_multi_adv_common_data)); 66 /* Storing both client_if and inst_id details */ 67 p_multi_adv_com_data_cb->clntif_map = 68 osi_calloc((max_adv_inst * INST_ID_IDX_MAX) * sizeof(INT8)); 69 70 p_multi_adv_com_data_cb->inst_cb = 71 osi_calloc((max_adv_inst + 1) * sizeof(btgatt_multi_adv_inst_cb)); 72 73 for (int i = 0; i < max_adv_inst * 2; i += 2) { 74 p_multi_adv_com_data_cb->clntif_map[i] = INVALID_ADV_INST; 75 p_multi_adv_com_data_cb->clntif_map[i+1] = INVALID_ADV_INST; 76 } 77 } 78 79 return p_multi_adv_com_data_cb; 80} 81 82void btif_gattc_incr_app_count(void) 83{ 84 // TODO: Instead of using a fragile reference counter here, one could 85 // simply track the client_if instances that are in the map. 86 ++user_app_count; 87} 88 89void btif_gattc_decr_app_count(void) 90{ 91 if (user_app_count > 0) 92 user_app_count--; 93 94 if ((user_app_count == 0) && (p_multi_adv_com_data_cb != NULL)) { 95 osi_free(p_multi_adv_com_data_cb->clntif_map); 96 osi_free(p_multi_adv_com_data_cb->inst_cb); 97 osi_free_and_reset((void **)&p_multi_adv_com_data_cb); 98 } 99} 100 101int btif_multi_adv_add_instid_map(int client_if, int inst_id, BOOLEAN gen_temp_instid) 102{ 103 int i=1; 104 105 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 106 if (NULL == p_multi_adv_data_cb) 107 return INVALID_ADV_INST; 108 109 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++) 110 { 111 if (client_if == p_multi_adv_data_cb->clntif_map[i + i]) 112 { 113 if (!gen_temp_instid) 114 { 115 // Write the final inst_id value obtained from stack layer 116 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = inst_id; 117 BTIF_TRACE_DEBUG("%s -Index: %d, Found client_if: %d", __FUNCTION__, 118 i, p_multi_adv_data_cb->clntif_map[i + i]); 119 break; 120 } 121 else 122 { 123 //Store the passed in inst_id value 124 if (inst_id != INVALID_ADV_INST) 125 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = inst_id; 126 else 127 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = (i + 1); 128 129 BTIF_TRACE_DEBUG("%s - Index:%d,Found client_if: %d", __FUNCTION__, 130 i, p_multi_adv_data_cb->clntif_map[i + i]); 131 break; 132 } 133 } 134 } 135 136 if (i < BTM_BleMaxMultiAdvInstanceCount()) 137 return i; 138 139 // If client ID if is not found, then write both values 140 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++) 141 { 142 if (INVALID_ADV_INST == p_multi_adv_data_cb->clntif_map[i + i]) 143 { 144 p_multi_adv_data_cb->clntif_map[i + i] = client_if; 145 if (inst_id != INVALID_ADV_INST) 146 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = inst_id; 147 else 148 p_multi_adv_data_cb->clntif_map[i + (i + 1)] = (i + 1); 149 BTIF_TRACE_DEBUG("%s -Not found - Index:%d, client_if: %d, Inst ID: %d", 150 __FUNCTION__,i, 151 p_multi_adv_data_cb->clntif_map[i + i], 152 p_multi_adv_data_cb->clntif_map[i + (i + 1)]); 153 break; 154 } 155 } 156 157 if (i < BTM_BleMaxMultiAdvInstanceCount()) 158 return i; 159 return INVALID_ADV_INST; 160} 161 162int btif_multi_adv_instid_for_clientif(int client_if) 163{ 164 int i=1, ret = INVALID_ADV_INST; 165 166 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 167 168 if (NULL == p_multi_adv_data_cb) 169 return INVALID_ADV_INST; 170 171 // Retrieve the existing inst_id for the client_if value 172 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++) 173 { 174 if (client_if == p_multi_adv_data_cb->clntif_map[i + i]) 175 { 176 BTIF_TRACE_DEBUG("%s - Client if found", __FUNCTION__, client_if); 177 ret = p_multi_adv_data_cb->clntif_map[i + (i + 1)]; 178 } 179 } 180 181 return ret; 182} 183 184int btif_gattc_obtain_idx_for_datacb(int value, int clnt_inst_index) 185{ 186 int i=1; 187 188 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 189 190 if (NULL == p_multi_adv_data_cb) 191 return INVALID_ADV_INST; 192 193 // Retrieve the array index for the inst_id value 194 for (i=1; i < BTM_BleMaxMultiAdvInstanceCount(); i++) 195 { 196 if (value == p_multi_adv_data_cb->clntif_map[i + (i + clnt_inst_index)]) 197 break; 198 } 199 200 if (i < BTM_BleMaxMultiAdvInstanceCount()) 201 { 202 BTIF_TRACE_DEBUG("%s, %d",__FUNCTION__,i); 203 return i; 204 } 205 206 BTIF_TRACE_DEBUG("%s Invalid instance",__FUNCTION__); 207 return INVALID_ADV_INST; 208} 209 210void btif_gattc_adv_data_packager(int client_if, bool set_scan_rsp, 211 bool include_name, bool include_txpower, int min_interval, int max_interval, 212 int appearance, int manufacturer_len, char* manufacturer_data, 213 int service_data_len, char* service_data, int service_uuid_len, 214 char* service_uuid, btif_adv_data_t *p_multi_adv_inst) 215{ 216 memset(p_multi_adv_inst, 0 , sizeof(btif_adv_data_t)); 217 218 p_multi_adv_inst->client_if = (uint8_t) client_if; 219 p_multi_adv_inst->set_scan_rsp = set_scan_rsp; 220 p_multi_adv_inst->include_name = include_name; 221 p_multi_adv_inst->include_txpower = include_txpower; 222 p_multi_adv_inst->min_interval = min_interval; 223 p_multi_adv_inst->max_interval = max_interval; 224 p_multi_adv_inst->appearance = appearance; 225 p_multi_adv_inst->manufacturer_len = manufacturer_len; 226 227 if (manufacturer_len > 0) 228 { 229 p_multi_adv_inst->p_manufacturer_data = osi_malloc(manufacturer_len); 230 memcpy(p_multi_adv_inst->p_manufacturer_data, manufacturer_data, manufacturer_len); 231 } 232 233 p_multi_adv_inst->service_data_len = service_data_len; 234 if (service_data_len > 0) 235 { 236 p_multi_adv_inst->p_service_data = osi_malloc(service_data_len); 237 memcpy(p_multi_adv_inst->p_service_data, service_data, service_data_len); 238 } 239 240 p_multi_adv_inst->service_uuid_len = service_uuid_len; 241 if (service_uuid_len > 0) 242 { 243 p_multi_adv_inst->p_service_uuid = osi_malloc(service_uuid_len); 244 memcpy(p_multi_adv_inst->p_service_uuid, service_uuid, service_uuid_len); 245 } 246} 247 248void btif_gattc_adv_data_cleanup(btif_adv_data_t* adv) 249{ 250 osi_free_and_reset((void **)&adv->p_service_data); 251 osi_free_and_reset((void **)&adv->p_service_uuid); 252 osi_free_and_reset((void **)&adv->p_manufacturer_data); 253} 254 255BOOLEAN btif_gattc_copy_datacb(int cbindex, const btif_adv_data_t *p_adv_data, 256 BOOLEAN bInstData) { 257 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 258 if (NULL == p_multi_adv_data_cb || cbindex < 0) 259 return false; 260 261 BTIF_TRACE_DEBUG("%s", __func__); 262 263 memset(&p_multi_adv_data_cb->inst_cb[cbindex].data, 0, 264 sizeof(p_multi_adv_data_cb->inst_cb[cbindex].data)); 265 p_multi_adv_data_cb->inst_cb[cbindex].mask = 0; 266 267 if (!p_adv_data->set_scan_rsp) 268 { 269 p_multi_adv_data_cb->inst_cb[cbindex].mask = BTM_BLE_AD_BIT_FLAGS; 270 p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS_GENERAL; 271 if (p_multi_adv_data_cb->inst_cb[cbindex].timeout_s) 272 p_multi_adv_data_cb->inst_cb[cbindex].data.flag = ADV_FLAGS_LIMITED; 273 if (p_multi_adv_data_cb->inst_cb[cbindex].param.adv_type == BTA_BLE_NON_CONNECT_EVT) 274 p_multi_adv_data_cb->inst_cb[cbindex].data.flag &= 275 ~(BTA_DM_LIMITED_DISC | BTA_DM_GENERAL_DISC); 276 if (p_multi_adv_data_cb->inst_cb[cbindex].data.flag == 0) 277 p_multi_adv_data_cb->inst_cb[cbindex].mask = 0; 278 } 279 280 if (p_adv_data->include_name) 281 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_DEV_NAME; 282 283 if (p_adv_data->include_txpower) 284 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_TX_PWR; 285 286 if (false == bInstData && p_adv_data->min_interval > 0 && p_adv_data->max_interval > 0 && 287 p_adv_data->max_interval > p_adv_data->min_interval) 288 { 289 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_INT_RANGE; 290 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low = 291 p_adv_data->min_interval; 292 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi = 293 p_adv_data->max_interval; 294 } 295 else 296 if (true == bInstData) 297 { 298 if (p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min > 0 && 299 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max > 0 && 300 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max > 301 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min) 302 { 303 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.low = 304 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_min; 305 p_multi_adv_data_cb->inst_cb[cbindex].data.int_range.hi = 306 p_multi_adv_data_cb->inst_cb[cbindex].param.adv_int_max; 307 } 308 309 if (p_adv_data->include_txpower) 310 { 311 p_multi_adv_data_cb->inst_cb[cbindex].data.tx_power = 312 p_multi_adv_data_cb->inst_cb[cbindex].param.tx_power; 313 } 314 } 315 316 if (p_adv_data->appearance != 0) 317 { 318 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_APPEARANCE; 319 p_multi_adv_data_cb->inst_cb[cbindex].data.appearance = p_adv_data->appearance; 320 } 321 322 if (p_adv_data->manufacturer_len > 0 && 323 p_adv_data->p_manufacturer_data != NULL && 324 p_adv_data->manufacturer_len < MAX_SIZE_MANUFACTURER_DATA) 325 { 326 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_MANU; 327 p_multi_adv_data_cb->inst_cb[cbindex].data.manu.len = 328 p_adv_data->manufacturer_len; 329 memcpy(&p_multi_adv_data_cb->inst_cb[cbindex].data.manu.val, 330 p_adv_data->p_manufacturer_data, p_adv_data->manufacturer_len); 331 } 332 333 if (p_adv_data->service_data_len > 0 && 334 p_adv_data->p_service_data != NULL && 335 p_adv_data->service_data_len < MAX_SIZE_PROPRIETARY_ELEMENT) 336 { 337 BTIF_TRACE_DEBUG("%s - In service_data", __func__); 338 tBTA_BLE_PROPRIETARY *p_prop = &p_multi_adv_data_cb->inst_cb[cbindex].data.proprietary; 339 p_prop->num_elem = 1; 340 341 tBTA_BLE_PROP_ELEM *p_elem = &p_prop->elem[0]; 342 p_elem->adv_type = BTM_BLE_AD_TYPE_SERVICE_DATA; 343 p_elem->len = p_adv_data->service_data_len; 344 memcpy(p_elem->val, p_adv_data->p_service_data, 345 p_adv_data->service_data_len); 346 347 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_PROPRIETARY; 348 } 349 350 if (p_adv_data->service_uuid_len && p_adv_data->p_service_uuid) 351 { 352 UINT16 *p_uuid_out16 = NULL; 353 UINT32 *p_uuid_out32 = NULL; 354 for (int position = 0; position < p_adv_data->service_uuid_len; position += LEN_UUID_128) 355 { 356 bt_uuid_t uuid; 357 memset(&uuid, 0, sizeof(uuid)); 358 memcpy(&uuid.uu, p_adv_data->p_service_uuid + position, LEN_UUID_128); 359 360 tBT_UUID bt_uuid; 361 memset(&bt_uuid, 0, sizeof(bt_uuid)); 362 btif_to_bta_uuid(&bt_uuid, &uuid); 363 364 switch(bt_uuid.len) 365 { 366 case (LEN_UUID_16): 367 { 368 if (p_multi_adv_data_cb->inst_cb[cbindex].data.services.num_service == 0) 369 { 370 p_multi_adv_data_cb->inst_cb[cbindex].data.services.list_cmpl = FALSE; 371 p_uuid_out16 = p_multi_adv_data_cb->inst_cb[cbindex].data.services.uuid; 372 } 373 374 if (p_multi_adv_data_cb->inst_cb[cbindex].data.services.num_service < MAX_16BIT_SERVICES) 375 { 376 BTIF_TRACE_DEBUG("%s - In 16-UUID_data", __func__); 377 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_SERVICE; 378 ++p_multi_adv_data_cb->inst_cb[cbindex].data.services.num_service; 379 *p_uuid_out16++ = bt_uuid.uu.uuid16; 380 } 381 break; 382 } 383 384 case (LEN_UUID_32): 385 { 386 if (p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.num_service == 0) 387 { 388 p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.list_cmpl = FALSE; 389 p_uuid_out32 = p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.uuid; 390 } 391 392 if (p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.num_service < MAX_32BIT_SERVICES) 393 { 394 BTIF_TRACE_DEBUG("%s - In 32-UUID_data", __func__); 395 p_multi_adv_data_cb->inst_cb[cbindex].mask |= BTM_BLE_AD_BIT_SERVICE_32; 396 ++p_multi_adv_data_cb->inst_cb[cbindex].data.service_32b.num_service; 397 *p_uuid_out32++ = bt_uuid.uu.uuid32; 398 } 399 break; 400 } 401 402 case (LEN_UUID_128): 403 { 404 /* Currently, only one 128-bit UUID is supported */ 405 if (p_multi_adv_data_cb->inst_cb[cbindex].data.services_128b.num_service == 0) 406 { 407 BTIF_TRACE_DEBUG("%s - In 128-UUID_data", __FUNCTION__); 408 p_multi_adv_data_cb->inst_cb[cbindex].mask |= 409 BTM_BLE_AD_BIT_SERVICE_128; 410 memcpy(p_multi_adv_data_cb->inst_cb[cbindex] 411 .data.services_128b.uuid128, 412 bt_uuid.uu.uuid128, LEN_UUID_128); 413 BTIF_TRACE_DEBUG( 414 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", 415 bt_uuid.uu.uuid128[0], bt_uuid.uu.uuid128[1], 416 bt_uuid.uu.uuid128[2], bt_uuid.uu.uuid128[3], 417 bt_uuid.uu.uuid128[4], bt_uuid.uu.uuid128[5], 418 bt_uuid.uu.uuid128[6], bt_uuid.uu.uuid128[7], 419 bt_uuid.uu.uuid128[8], bt_uuid.uu.uuid128[9], 420 bt_uuid.uu.uuid128[10], bt_uuid.uu.uuid128[11], 421 bt_uuid.uu.uuid128[12], bt_uuid.uu.uuid128[13], 422 bt_uuid.uu.uuid128[14], bt_uuid.uu.uuid128[15]); 423 ++p_multi_adv_data_cb->inst_cb[cbindex] 424 .data.services_128b.num_service; 425 p_multi_adv_data_cb->inst_cb[cbindex] 426 .data.services_128b.list_cmpl = TRUE; 427 } 428 break; 429 } 430 431 default: 432 break; 433 } 434 } 435 } 436 437 return true; 438} 439 440void btif_gattc_clear_clientif(int client_if, BOOLEAN stop_timer) 441{ 442 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 443 if (NULL == p_multi_adv_data_cb) 444 return; 445 446 // Clear both the inst_id and client_if values 447 for (int i=0; i < BTM_BleMaxMultiAdvInstanceCount()*2; i+=2) 448 { 449 if (client_if == p_multi_adv_data_cb->clntif_map[i]) 450 { 451 btif_gattc_cleanup_inst_cb(p_multi_adv_data_cb->clntif_map[i+1], stop_timer); 452 if (stop_timer) 453 { 454 p_multi_adv_data_cb->clntif_map[i] = INVALID_ADV_INST; 455 p_multi_adv_data_cb->clntif_map[i+1] = INVALID_ADV_INST; 456 BTIF_TRACE_DEBUG("Cleaning up index %d for clnt_if :%d,", i/2, client_if); 457 } 458 break; 459 } 460 } 461} 462 463void btif_gattc_cleanup_inst_cb(int inst_id, BOOLEAN stop_timer) 464{ 465 // Check for invalid instance id 466 if (inst_id < 0 || inst_id >= BTM_BleMaxMultiAdvInstanceCount()) 467 return; 468 469 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 470 if (NULL == p_multi_adv_data_cb) 471 return; 472 473 int cbindex = (STD_ADV_INSTID == inst_id) ? 474 STD_ADV_INSTID : btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX); 475 if (cbindex < 0) return; 476 477 BTIF_TRACE_DEBUG("%s: inst_id %d, cbindex %d", __func__, inst_id, cbindex); 478 btif_gattc_cleanup_multi_inst_cb(&p_multi_adv_data_cb->inst_cb[cbindex], stop_timer); 479} 480 481void btif_gattc_cleanup_multi_inst_cb(btgatt_multi_adv_inst_cb *p_multi_inst_cb, 482 BOOLEAN stop_timer) 483{ 484 if (p_multi_inst_cb == NULL) 485 return; 486 487 // Discoverability timer cleanup 488 if (stop_timer) 489 { 490 alarm_free(p_multi_inst_cb->multi_adv_timer); 491 p_multi_inst_cb->multi_adv_timer = NULL; 492 } 493 494 memset(&p_multi_inst_cb->data, 0, sizeof(p_multi_inst_cb->data)); 495} 496 497void btif_multi_adv_timer_ctrl(int client_if, alarm_callback_t cb) 498{ 499 int inst_id = btif_multi_adv_instid_for_clientif(client_if); 500 if (inst_id == INVALID_ADV_INST) 501 return; 502 503 int cbindex = btif_gattc_obtain_idx_for_datacb(inst_id, INST_ID_IDX); 504 if (cbindex == INVALID_ADV_INST) 505 return; 506 507 btgatt_multi_adv_common_data *p_multi_adv_data_cb = btif_obtain_multi_adv_data_cb(); 508 if (p_multi_adv_data_cb == NULL) 509 return; 510 511 btgatt_multi_adv_inst_cb *inst_cb = &p_multi_adv_data_cb->inst_cb[cbindex]; 512 if (cb == NULL) 513 { 514 alarm_free(inst_cb->multi_adv_timer); 515 inst_cb->multi_adv_timer = NULL; 516 } else { 517 if (inst_cb->timeout_s != 0) 518 { 519 alarm_free(inst_cb->multi_adv_timer); 520 inst_cb->multi_adv_timer = alarm_new("btif_gatt.multi_adv_timer"); 521 alarm_set_on_queue(inst_cb->multi_adv_timer, 522 inst_cb->timeout_s * 1000, 523 cb, INT_TO_PTR(client_if), 524 btu_general_alarm_queue); 525 } 526 } 527} 528 529#endif 530