1/* 2 * Copyright (C) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "btm.h" 17 18#include <stdint.h> 19 20#include "btstack.h" 21#include "hci/hci.h" 22#include "log.h" 23#include "module.h" 24#include "platform/include/alarm.h" 25#include "platform/include/allocator.h" 26#include "platform/include/list.h" 27#include "platform/include/mutex.h" 28#include "platform/include/thread.h" 29 30#include "btm_acl.h" 31#include "btm_controller.h" 32#include "btm_inq_db.h" 33#include "btm_le_sec.h" 34#include "btm_pm.h" 35#include "btm_sco.h" 36#include "btm_snoop.h" 37#include "btm_thread.h" 38#include "btm_wl.h" 39 40#define STATUS_NONE 0 41#define STATUS_INITIALIZED 1 42 43#define IS_INITIALIZED() (g_status == STATUS_INITIALIZED) 44 45#define MODE_NONE 0 46#define MODE_BREDR 1 47#define MODE_LE 2 48#define MODE_DUAL (MODE_BREDR | MODE_LE) 49 50typedef struct { 51 const BtmCallbacks *callbacks; 52 void *context; 53} BtmCallbacksBlock; 54 55static uint8_t g_currentMode = MODE_NONE; 56static Mutex *g_modeLock = NULL; 57 58static HciFailureCallbacks g_hciFailureCallbacks; 59 60static const int G_COUNT_OF_ALL_MODULES = 8; 61static const char *g_allModules[] = { 62 MODULE_NAME_L2CAP, 63 MODULE_NAME_GAP, 64 MODULE_NAME_SDP, 65 MODULE_NAME_AVCTP, 66 MODULE_NAME_AVDTP, 67 MODULE_NAME_RFCOMM, 68 MODULE_NAME_ATT, 69 MODULE_NAME_SMP, 70}; 71 72static const int G_COUNTOF_BREDR_AND_SHARED_MODULES = 8; 73static const char *g_bredrAndSharedModules[] = { 74 MODULE_NAME_L2CAP, 75 MODULE_NAME_SMP, 76 MODULE_NAME_GAP, 77 MODULE_NAME_SDP, 78 MODULE_NAME_AVCTP, 79 MODULE_NAME_AVDTP, 80 MODULE_NAME_RFCOMM, 81 MODULE_NAME_ATT, 82}; 83 84static const int G_COUNT_OF_BREDR_MODULES = 4; 85static const char *g_bredrModules[] = { 86 MODULE_NAME_SDP, 87 MODULE_NAME_AVCTP, 88 MODULE_NAME_AVDTP, 89 MODULE_NAME_RFCOMM, 90}; 91 92static const int G_COUNT_OF_LE_AND_SHARED_MODULES = 4; 93static const char *g_leAndSharedModules[] = { 94 MODULE_NAME_L2CAP, 95 MODULE_NAME_SMP, 96 MODULE_NAME_GAP, 97 MODULE_NAME_ATT, 98}; 99 100static const int G_COUNT_OF_LE_MODULES = 0; 101static const char *g_leModules[] = {}; 102 103static List *g_btmCallbackList = NULL; 104static Mutex *g_btmCallbackListLock = NULL; 105static uint8_t g_status = STATUS_NONE; 106 107static BtmCallbacksBlock *BtmAllocCallbacksBlock(const BtmCallbacks *callbacks, void *context) 108{ 109 BtmCallbacksBlock *block = MEM_MALLOC.alloc(sizeof(BtmCallbacksBlock)); 110 if (block != NULL) { 111 block->callbacks = (BtmCallbacks *)callbacks; 112 block->context = context; 113 } 114 return block; 115} 116 117static void BtmFreeCallbacksBlock(void *block) 118{ 119 MEM_MALLOC.free(block); 120} 121 122#ifdef DEBUG 123static void BtmOutputCurrentStatus() 124{ 125 LOG_DEBUG("BR/EDR: %{public}s LE: %{public}s", 126 (g_currentMode & MODE_BREDR) ? "Enabled" : "Disabled", 127 (g_currentMode & MODE_LE) ? "Enabled" : "Disabled"); 128} 129#endif 130 131static void BtmInitFeatures() 132{ 133 BtmInitThread(); 134 BtmInitSnoop(); 135 BtmInitAcl(); 136 BtmInitSco(); 137 BtmInitPm(); 138 BtmInitInquiryDb(); 139 BtmInitLeSecurity(); 140 BtmInitWhiteList(); 141} 142 143static void BtmCloseFeatures() 144{ 145 BtmCloseWhiteList(); 146 BtmCloseLeSecurity(); 147 BtmCloseInquiryDb(); 148 BtmClosePm(); 149 BtmCloseSco(); 150 BtmCloseAcl(); 151 BtmCloseSnoop(); 152 BtmCloseThread(); 153} 154 155int BTM_Initialize() 156{ 157 LOG_DEBUG("%{public}s start", __FUNCTION__); 158 159 int result = BT_SUCCESS; 160 do { 161 int32_t ret = AlarmModuleInit(); 162 if (ret != 0) { 163 result = BT_OPERATION_FAILED; 164 break; 165 } 166 167 g_modeLock = MutexCreate(); 168 if (g_modeLock == NULL) { 169 result = BT_OPERATION_FAILED; 170 break; 171 } 172 173 g_btmCallbackList = ListCreate(BtmFreeCallbacksBlock); 174 if (g_btmCallbackList == NULL) { 175 result = BT_OPERATION_FAILED; 176 break; 177 } 178 179 g_btmCallbackListLock = MutexCreate(); 180 if (g_btmCallbackListLock == NULL) { 181 result = BT_OPERATION_FAILED; 182 break; 183 } 184 185 BtmInitFeatures(); 186 187 LOG_DEBUG("ModuleInit start"); 188 for (int i = 0; i < G_COUNT_OF_ALL_MODULES; i++) { 189 LOG_DEBUG("ModuleInit: %{public}s", g_allModules[i]); 190 ModuleInit(g_allModules[i], 0); 191 } 192 LOG_DEBUG("ModuleInit end"); 193 194 g_status = STATUS_INITIALIZED; 195 } while (0); 196 197 LOG_DEBUG("%{public}s end", __FUNCTION__); 198 199 return result; 200} 201 202NO_SANITIZE("cfi") int BTM_Close() 203{ 204 LOG_DEBUG("%{public}s start", __FUNCTION__); 205 206 if (BTM_Disable(LE_CONTROLLER) != BT_SUCCESS) { 207 LOG_WARN("Disable LE Failed"); 208 } 209 if (BTM_Disable(BREDR_CONTROLLER) != BT_SUCCESS) { 210 LOG_WARN("Disable BREDR Failed"); 211 } 212 213 g_status = STATUS_NONE; 214 215 LOG_DEBUG("ModuleCleanup start"); 216 for (int i = G_COUNT_OF_ALL_MODULES - 1; i >= 0; i--) { 217 LOG_DEBUG("ModuleCleanup: %{public}s", g_allModules[i]); 218 ModuleCleanup(g_allModules[i]); 219 } 220 LOG_DEBUG("ModuleCleanup end"); 221 222 BtmCloseFeatures(); 223 224 if (g_btmCallbackListLock != NULL) { 225 MutexDelete(g_btmCallbackListLock); 226 g_btmCallbackListLock = NULL; 227 } 228 229 if (g_btmCallbackList != NULL) { 230 ListDelete(g_btmCallbackList); 231 g_btmCallbackList = NULL; 232 } 233 234 if (g_modeLock != NULL) { 235 MutexDelete(g_modeLock); 236 g_modeLock = NULL; 237 } 238 239 AlarmModuleCleanup(); 240 241 LOG_DEBUG("%{public}s end", __FUNCTION__); 242 243 return BT_SUCCESS; 244} 245 246static int BtmEnableBrEdrAndSharedModules() 247{ 248 BtmStartSnoopOutput(); 249 250 int result = HCI_Initialize(); 251 if (result == BT_SUCCESS) { 252 HCI_RegisterFailureCallback(&g_hciFailureCallbacks); 253 254 result = BtmInitController(); 255 if (result == BT_SUCCESS) { 256 BtmStartAcl(); 257 BtmStartPm(); 258 BtmStartSco(); 259 260 LOG_DEBUG("ModuleStartup start"); 261 for (int i = 0; i < G_COUNTOF_BREDR_AND_SHARED_MODULES; i++) { 262 LOG_DEBUG("ModuleStartup: %{public}s", g_bredrAndSharedModules[i]); 263 ModuleStartup(g_bredrAndSharedModules[i]); 264 } 265 LOG_DEBUG("ModuleStartup end"); 266 } 267 } 268 269 if (result != BT_SUCCESS) { 270 HCI_Close(); 271 272 BtmStopSnoopOutput(); 273 } 274 275 return result; 276} 277 278static int BtmEnableBrEdrModules() 279{ 280 BtmStartPm(); 281 BtmStartSco(); 282 283 LOG_DEBUG("ModuleStartup start"); 284 for (int i = 0; i < G_COUNT_OF_BREDR_MODULES; i++) { 285 LOG_DEBUG("ModuleStartup: %{public}s", g_bredrModules[i]); 286 ModuleStartup(g_bredrModules[i]); 287 } 288 LOG_DEBUG("ModuleStartup end"); 289 290 return BT_SUCCESS; 291} 292 293static int BtmEnableLeAndSharedModules() 294{ 295 BtmStartSnoopOutput(); 296 297 int result = HCI_Initialize(); 298 if (result == BT_SUCCESS) { 299 HCI_RegisterFailureCallback(&g_hciFailureCallbacks); 300 301 result = BtmInitController(); 302 if (result == BT_SUCCESS) { 303 BtmStartAcl(); 304 BtmStartLeSecurity(); 305 BtmStartWhiteList(); 306 307 LOG_DEBUG("ModuleStartup start"); 308 for (int i = 0; i < G_COUNT_OF_LE_AND_SHARED_MODULES; i++) { 309 LOG_DEBUG("ModuleStartup: %{public}s", g_leAndSharedModules[i]); 310 ModuleStartup(g_leAndSharedModules[i]); 311 } 312 LOG_DEBUG("ModuleStartup end"); 313 } 314 } 315 316 if (result != BT_SUCCESS) { 317 HCI_Close(); 318 319 BtmStopSnoopOutput(); 320 } 321 322 return result; 323} 324 325static int BtmEnableLeModules() 326{ 327 BtmStartLeSecurity(); 328 BtmStartWhiteList(); 329 330 LOG_DEBUG("ModuleStartup start"); 331 for (int i = 0; i < G_COUNT_OF_LE_MODULES; i++) { 332 LOG_DEBUG("ModuleStartup: %{public}s", g_leModules[i]); 333 ModuleStartup(g_leModules[i]); 334 } 335 LOG_DEBUG("ModuleStartup end"); 336 337 return BT_SUCCESS; 338} 339 340static void BtmDisableBrEdrAndSharedModules() 341{ 342 BtmCloseAclConnectionByTransport(TRANSPORT_BREDR); 343 344 LOG_DEBUG("ModuleShutdown start"); 345 for (int i = G_COUNTOF_BREDR_AND_SHARED_MODULES - 1; i >= 0; i--) { 346 LOG_DEBUG("ModuleShutdown: %{public}s", g_bredrAndSharedModules[i]); 347 ModuleShutdown(g_bredrAndSharedModules[i]); 348 } 349 LOG_DEBUG("ModuleShutdown end"); 350 351 BtmClearInquiryDb(); 352 BtmStopSco(); 353 BtmStopPm(); 354 BtmStopAcl(); 355 BtmCloseController(); 356 357 HCI_DeregisterFailureCallback(&g_hciFailureCallbacks); 358 HCI_Close(); 359 360 BtmStopSnoopOutput(); 361} 362 363static void BtmDisableBrEdrModules() 364{ 365 BtmCloseAclConnectionByTransport(TRANSPORT_BREDR); 366 367 LOG_DEBUG("ModuleShutdown start"); 368 for (int i = G_COUNT_OF_BREDR_MODULES - 1; i >= 0; i--) { 369 LOG_DEBUG("ModuleShutdown: %{public}s", g_bredrModules[i]); 370 ModuleShutdown(g_bredrModules[i]); 371 } 372 LOG_DEBUG("ModuleShutdown end"); 373 374 BtmClearInquiryDb(); 375 BtmStopSco(); 376 BtmStopPm(); 377} 378 379static void BtmDisableLeAndSharedModules() 380{ 381 BtmCloseAclConnectionByTransport(TRANSPORT_LE); 382 383 LOG_DEBUG("ModuleShutdown start"); 384 for (int i = G_COUNT_OF_LE_AND_SHARED_MODULES - 1; i >= 0; i--) { 385 LOG_DEBUG("ModuleShutdown: %{public}s", g_leAndSharedModules[i]); 386 ModuleShutdown(g_leAndSharedModules[i]); 387 } 388 LOG_DEBUG("ModuleShutdown end"); 389 390 BtmStopWhiteList(); 391 BtmStopLeSecurity(); 392 BtmStopAcl(); 393 BtmCloseController(); 394 395 HCI_DeregisterFailureCallback(&g_hciFailureCallbacks); 396 HCI_Close(); 397 398 BtmStopSnoopOutput(); 399} 400 401static void BtmDisableLeModules() 402{ 403 BtmCloseAclConnectionByTransport(TRANSPORT_LE); 404 405 LOG_DEBUG("ModuleShutdown start"); 406 for (int i = G_COUNT_OF_LE_MODULES - 1; i >= 0; i--) { 407 LOG_DEBUG("ModuleShutdown: %{public}s", g_leModules[i]); 408 ModuleShutdown(g_leModules[i]); 409 } 410 LOG_DEBUG("ModuleShutdown end"); 411 412 BtmStopWhiteList(); 413 BtmStopLeSecurity(); 414} 415 416int BTM_Enable(int controller) 417{ 418 LOG_DEBUG("%{public}s start", __FUNCTION__); 419 420 if (controller != BREDR_CONTROLLER && controller != LE_CONTROLLER) { 421 return BT_BAD_PARAM; 422 } 423 424 if (!IS_INITIALIZED()) { 425 return BT_BAD_STATUS; 426 } 427 428 int result = BT_SUCCESS; 429 430 MutexLock(g_modeLock); 431 432 if (controller == BREDR_CONTROLLER) { 433 if (g_currentMode == MODE_NONE) { 434 result = BtmEnableBrEdrAndSharedModules(); 435 } else if (g_currentMode == MODE_LE) { 436 result = BtmEnableBrEdrModules(); 437 } 438 439 if (result == BT_SUCCESS) { 440 g_currentMode |= MODE_BREDR; 441 } 442 } else if (controller == LE_CONTROLLER) { 443 if (g_currentMode == MODE_NONE) { 444 result = BtmEnableLeAndSharedModules(); 445 } else if (g_currentMode == MODE_BREDR) { 446 result = BtmEnableLeModules(); 447 } 448 449 if (result == BT_SUCCESS) { 450 g_currentMode |= MODE_LE; 451 } 452 } 453 454#ifdef DEBUG 455 BtmOutputCurrentStatus(); 456#endif 457 458 MutexUnlock(g_modeLock); 459 LOG_DEBUG("%{public}s end", __FUNCTION__); 460 return result; 461} 462 463int BTM_Disable(int controller) 464{ 465 LOG_DEBUG("%{public}s start", __FUNCTION__); 466 if (controller != BREDR_CONTROLLER && controller != LE_CONTROLLER) { 467 return BT_BAD_PARAM; 468 } 469 470 if (!IS_INITIALIZED()) { 471 return BT_BAD_STATUS; 472 } 473 474 MutexLock(g_modeLock); 475 476 if (controller == BREDR_CONTROLLER) { 477 if (g_currentMode == MODE_DUAL) { 478 BtmDisableBrEdrModules(); 479 } else if (g_currentMode == MODE_BREDR) { 480 BtmDisableBrEdrAndSharedModules(); 481 } 482 483 g_currentMode &= (~MODE_BREDR); 484 } else if (controller == LE_CONTROLLER) { 485 if (g_currentMode == MODE_DUAL) { 486 BtmDisableLeModules(); 487 } else if (g_currentMode == MODE_LE) { 488 BtmDisableLeAndSharedModules(); 489 } 490 491 g_currentMode &= (~MODE_LE); 492 } 493 494#ifdef DEBUG 495 BtmOutputCurrentStatus(); 496#endif 497 498 MutexUnlock(g_modeLock); 499 LOG_DEBUG("%{public}s end", __FUNCTION__); 500 return BT_SUCCESS; 501} 502 503bool BTM_IsEnabled(int controller) 504{ 505 if (!IS_INITIALIZED()) { 506 return false; 507 } 508 509 bool isEnabled = false; 510 511 if (controller == BREDR_CONTROLLER) { 512 MutexLock(g_modeLock); 513 isEnabled = !!(g_currentMode & MODE_BREDR); 514 MutexUnlock(g_modeLock); 515 } else if (controller == LE_CONTROLLER) { 516 MutexLock(g_modeLock); 517 isEnabled = !!(g_currentMode & MODE_LE); 518 MutexUnlock(g_modeLock); 519 } 520 521 return isEnabled; 522} 523 524int BTM_RegisterCallbacks(const BtmCallbacks *callbacks, void *context) 525{ 526 if (callbacks == NULL) { 527 return BT_BAD_PARAM; 528 } 529 530 if (!IS_INITIALIZED()) { 531 return BT_BAD_STATUS; 532 } 533 534 BtmCallbacksBlock *block = BtmAllocCallbacksBlock(callbacks, context); 535 if (block == NULL) { 536 return BT_NO_MEMORY; 537 } 538 539 MutexLock(g_btmCallbackListLock); 540 ListAddLast(g_btmCallbackList, block); 541 MutexUnlock(g_btmCallbackListLock); 542 543 return BT_SUCCESS; 544} 545 546int BTM_DeregisterCallbacks(const BtmCallbacks *callbacks) 547{ 548 if (callbacks == NULL) { 549 return BT_BAD_PARAM; 550 } 551 552 if (!IS_INITIALIZED()) { 553 return BT_BAD_STATUS; 554 } 555 556 MutexLock(g_btmCallbackListLock); 557 558 BtmCallbacksBlock *block = NULL; 559 ListNode *node = ListGetFirstNode(g_btmCallbackList); 560 while (node != NULL) { 561 block = ListGetNodeData(node); 562 if (block != NULL) { 563 if (block->callbacks == callbacks) { 564 ListRemoveNode(g_btmCallbackList, block); 565 break; 566 } 567 } 568 node = ListGetNextNode(node); 569 } 570 571 MutexUnlock(g_btmCallbackListLock); 572 573 return BT_SUCCESS; 574} 575 576static void BtmOnHCIFailure() 577{ 578 BtmCallbacksBlock *block = NULL; 579 MutexLock(g_btmCallbackListLock); 580 ListNode *node = ListGetFirstNode(g_btmCallbackList); 581 while (node != NULL) { 582 block = ListGetNodeData(node); 583 if (block->callbacks != NULL && block->callbacks->hciFailure != NULL) { 584 block->callbacks->hciFailure(block->context); 585 } 586 node = ListGetNextNode(node); 587 } 588 MutexUnlock(g_btmCallbackListLock); 589} 590 591static HciFailureCallbacks g_hciFailureCallbacks = { 592 .onCmdTimeout = BtmOnHCIFailure, 593}; 594