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