1 /******************************************************************************
2  *
3  *  Copyright 2003-2012 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  *  This is the main implementation file for the BTA system manager.
22  *
23  ******************************************************************************/
24 
25 #define LOG_TAG "bt_bta_sys_main"
26 
27 #include <base/functional/bind.h>
28 #include <bluetooth/log.h>
29 
30 #include <cstring>
31 
32 #include "bta/sys/bta_sys.h"
33 #include "bta/sys/bta_sys_int.h"
34 #include "include/hardware/bluetooth.h"
35 #include "internal_include/bt_target.h"
36 #include "osi/include/alarm.h"
37 #include "osi/include/allocator.h"
38 #include "stack/include/bt_hdr.h"
39 #include "stack/include/main_thread.h"
40 
41 using namespace bluetooth;
42 
43 /* system manager control block definition */
44 tBTA_SYS_CB bta_sys_cb;
45 
46 /*******************************************************************************
47  *
48  * Function         bta_sys_init
49  *
50  * Description      BTA initialization; called from task initialization.
51  *
52  *
53  * Returns          void
54  *
55  ******************************************************************************/
bta_sys_init(void)56 void bta_sys_init(void) { memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB)); }
57 
58 /*******************************************************************************
59  *
60  * Function         bta_sys_event
61  *
62  * Description      BTA event handler; called from task event handler.
63  *
64  *
65  * Returns          void
66  *
67  ******************************************************************************/
bta_sys_event(BT_HDR_RIGID * p_msg)68 static void bta_sys_event(BT_HDR_RIGID* p_msg) {
69   bool freebuf = true;
70 
71   log::verbose("Event 0x{:x}", p_msg->event);
72 
73   /* get subsystem id from event */
74   uint8_t id = (uint8_t)(p_msg->event >> 8);
75 
76   /* verify id and call subsystem event handler */
77   if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
78     freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
79   } else {
80     log::info("Ignoring receipt of unregistered event id:{}[{}]",
81               BtaIdSysText(static_cast<tBTA_SYS_ID>(id)), id);
82   }
83 
84   if (freebuf) {
85     osi_free(p_msg);
86   }
87 }
88 
89 /*******************************************************************************
90  *
91  * Function         bta_sys_register
92  *
93  * Description      Called by other BTA subsystems to register their event
94  *                  handler.
95  *
96  *
97  * Returns          void
98  *
99  ******************************************************************************/
bta_sys_register(uint8_t id,const tBTA_SYS_REG * p_reg)100 void bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg) {
101   bta_sys_cb.reg[id] = (tBTA_SYS_REG*)p_reg;
102   bta_sys_cb.is_reg[id] = true;
103 }
104 
105 /*******************************************************************************
106  *
107  * Function         bta_sys_deregister
108  *
109  * Description      Called by other BTA subsystems to de-register
110  *                  handler.
111  *
112  *
113  * Returns          void
114  *
115  ******************************************************************************/
bta_sys_deregister(uint8_t id)116 void bta_sys_deregister(uint8_t id) { bta_sys_cb.is_reg[id] = false; }
117 
118 /*******************************************************************************
119  *
120  * Function         bta_sys_is_register
121  *
122  * Description      Called by other BTA subsystems to get registeration
123  *                  status.
124  *
125  *
126  * Returns          void
127  *
128  ******************************************************************************/
bta_sys_is_register(uint8_t id)129 bool bta_sys_is_register(uint8_t id) { return bta_sys_cb.is_reg[id]; }
130 
131 /*******************************************************************************
132  *
133  * Function         bta_sys_sendmsg
134  *
135  * Description      Send a GKI message to BTA.  This function is designed to
136  *                  optimize sending of messages to BTA.  It is called by BTA
137  *                  API functions and call-in functions.
138  *
139  *                  TODO (apanicke): Add location object as parameter for easier
140  *                  future debugging when doing alarm refactor
141  *
142  *
143  * Returns          void
144  *
145  ******************************************************************************/
bta_sys_sendmsg(void * p_msg)146 void bta_sys_sendmsg(void* p_msg) {
147   if (do_in_main_thread(base::BindOnce(&bta_sys_event, static_cast<BT_HDR_RIGID*>(p_msg))) !=
148       BT_STATUS_SUCCESS) {
149     log::error("do_in_main_thread failed");
150   }
151 }
152 
bta_sys_sendmsg_delayed(void * p_msg,std::chrono::microseconds delay)153 void bta_sys_sendmsg_delayed(void* p_msg, std::chrono::microseconds delay) {
154   if (do_in_main_thread_delayed(base::Bind(&bta_sys_event, static_cast<BT_HDR_RIGID*>(p_msg)),
155                                 delay) != BT_STATUS_SUCCESS) {
156     log::error("do_in_main_thread_delayed failed");
157   }
158 }
159 
160 /*******************************************************************************
161  *
162  * Function         bta_sys_start_timer
163  *
164  * Description      Start a protocol timer for the specified amount
165  *                  of time in milliseconds.
166  *
167  * Returns          void
168  *
169  ******************************************************************************/
bta_sys_start_timer(alarm_t * alarm,uint64_t interval_ms,uint16_t event,uint16_t layer_specific)170 void bta_sys_start_timer(alarm_t* alarm, uint64_t interval_ms, uint16_t event,
171                          uint16_t layer_specific) {
172   BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID));
173 
174   p_buf->event = event;
175   p_buf->layer_specific = layer_specific;
176 
177   alarm_set_on_mloop(alarm, interval_ms, bta_sys_sendmsg, p_buf);
178 }
179 
180 /*******************************************************************************
181  *
182  * Function         bta_sys_disable
183  *
184  * Description      For each registered subsystem execute its disable function.
185  *
186  * Returns          void
187  *
188  ******************************************************************************/
bta_sys_disable()189 void bta_sys_disable() {
190   int bta_id = BTA_ID_DM_SEC;
191   int bta_id_max = BTA_ID_BLUETOOTH_MAX;
192 
193   for (; bta_id <= bta_id_max; bta_id++) {
194     if (bta_sys_cb.reg[bta_id] != NULL) {
195       if (bta_sys_cb.is_reg[bta_id] && bta_sys_cb.reg[bta_id]->disable != NULL) {
196         (*bta_sys_cb.reg[bta_id]->disable)();
197       }
198     }
199   }
200 }
201