1 /******************************************************************************
2 *
3 * Copyright 2004-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 file contains the audio gateway functions controlling the RFCOMM
22 * connections.
23 *
24 ******************************************************************************/
25
26 #include <base/functional/bind.h>
27 #include <bluetooth/log.h>
28
29 #include <cstdint>
30
31 #include "bta/ag/bta_ag_int.h"
32 #include "bta/include/bta_sec_api.h"
33 #include "bta_api.h"
34 #include "os/logging/log_adapter.h"
35 #include "stack/include/main_thread.h"
36 #include "stack/include/port_api.h"
37 #include "types/raw_address.h"
38
39 /* Event mask for RfCOMM port callback */
40 #define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR
41
42 using namespace bluetooth;
43
44 /* each scb has its own rfcomm callbacks */
45 static void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle);
46 static void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle);
47 static void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle);
48 static void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle);
49 static void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle);
50 static void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle);
51 static void bta_ag_mgmt_cback_1(const tPORT_RESULT code, uint16_t port_handle);
52 static void bta_ag_mgmt_cback_2(const tPORT_RESULT code, uint16_t port_handle);
53 static void bta_ag_mgmt_cback_3(const tPORT_RESULT code, uint16_t port_handle);
54 static void bta_ag_mgmt_cback_4(const tPORT_RESULT code, uint16_t port_handle);
55 static void bta_ag_mgmt_cback_5(const tPORT_RESULT code, uint16_t port_handle);
56 static void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle);
57
58 /* rfcomm callback function tables */
59 typedef tPORT_CALLBACK* tBTA_AG_PORT_CBACK;
60 static const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {
61 bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3,
62 bta_ag_port_cback_4, bta_ag_port_cback_5, bta_ag_port_cback_6};
63
64 typedef tPORT_MGMT_CALLBACK* tBTA_AG_PORT_MGMT_CBACK;
65 static const tBTA_AG_PORT_MGMT_CBACK bta_ag_mgmt_cback_tbl[] = {
66 bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3,
67 bta_ag_mgmt_cback_4, bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6};
68
69 /*******************************************************************************
70 *
71 * Function bta_ag_port_cback
72 *
73 * Description RFCOMM Port callback
74 *
75 *
76 * Returns void
77 *
78 ******************************************************************************/
bta_ag_port_cback(uint32_t,uint16_t port_handle,uint16_t handle)79 static void bta_ag_port_cback(uint32_t /* code */, uint16_t port_handle, uint16_t handle) {
80 tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
81 if (p_scb != nullptr) {
82 /* ignore port events for port handles other than connected handle */
83 if (port_handle != p_scb->conn_handle) {
84 log::error("ag_port_cback ignoring handle:{} conn_handle = {} other handle = {}", port_handle,
85 p_scb->conn_handle, handle);
86 return;
87 }
88 if (!bta_ag_scb_open(p_scb)) {
89 log::error("rfcomm data on an unopened control block {} peer_addr {} state {}", handle,
90 p_scb->peer_addr, bta_ag_state_str(p_scb->state));
91 }
92 do_in_main_thread(base::BindOnce(&bta_ag_sm_execute_by_handle, handle, BTA_AG_RFC_DATA_EVT,
93 tBTA_AG_DATA::kEmpty));
94 }
95 }
96
97 /*******************************************************************************
98 *
99 * Function bta_ag_mgmt_cback
100 *
101 * Description RFCOMM management callback
102 *
103 *
104 * Returns void
105 *
106 ******************************************************************************/
bta_ag_mgmt_cback(const tPORT_RESULT code,uint16_t port_handle,uint16_t handle)107 static void bta_ag_mgmt_cback(const tPORT_RESULT code, uint16_t port_handle, uint16_t handle) {
108 tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
109 log::verbose("code={}, port_handle={}, scb_handle={}, p_scb=0x{}", code, port_handle, handle,
110 std::format_ptr(p_scb));
111 if (p_scb == nullptr) {
112 log::warn("cannot find scb, code={}, port_handle={}, handle={}", code, port_handle, handle);
113 return;
114 }
115 /* ignore close event for port handles other than connected handle */
116 if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) {
117 log::warn("ignore open failure for unmatched port_handle {}, scb_handle={}", port_handle,
118 handle);
119 return;
120 }
121 uint16_t event;
122 if (code == PORT_SUCCESS) {
123 bool found_handle = false;
124 if (p_scb->conn_handle) {
125 /* Outgoing connection */
126 if (port_handle == p_scb->conn_handle) {
127 found_handle = true;
128 }
129 } else {
130 /* Incoming connection */
131 for (uint16_t service_port_handle : p_scb->serv_handle) {
132 if (port_handle == service_port_handle) {
133 found_handle = true;
134 break;
135 }
136 }
137 }
138 if (!found_handle) {
139 log::error("port opened successfully, but port_handle {} is unknown, scb_handle={}",
140 port_handle, handle);
141 return;
142 }
143 event = BTA_AG_RFC_OPEN_EVT;
144 } else if (port_handle == p_scb->conn_handle) {
145 /* distinguish server close events */
146 event = BTA_AG_RFC_CLOSE_EVT;
147 } else {
148 event = BTA_AG_RFC_SRV_CLOSE_EVT;
149 }
150
151 tBTA_AG_DATA data = {};
152 data.rfc.port_handle = port_handle;
153 do_in_main_thread(base::BindOnce(&bta_ag_sm_execute_by_handle, handle, event, data));
154 }
155
156 /*******************************************************************************
157 *
158 * Function bta_ag_port_cback_1 to 6
159 * bta_ag_mgmt_cback_1 to 6
160 *
161 * Description RFCOMM callback functions. This is an easy way to
162 * distinguish scb from the callback.
163 *
164 *
165 * Returns void
166 *
167 ******************************************************************************/
bta_ag_mgmt_cback_1(const tPORT_RESULT code,uint16_t port_handle)168 static void bta_ag_mgmt_cback_1(const tPORT_RESULT code, uint16_t port_handle) {
169 bta_ag_mgmt_cback(code, port_handle, 1);
170 }
bta_ag_mgmt_cback_2(const tPORT_RESULT code,uint16_t port_handle)171 static void bta_ag_mgmt_cback_2(const tPORT_RESULT code, uint16_t port_handle) {
172 bta_ag_mgmt_cback(code, port_handle, 2);
173 }
bta_ag_mgmt_cback_3(const tPORT_RESULT code,uint16_t port_handle)174 static void bta_ag_mgmt_cback_3(const tPORT_RESULT code, uint16_t port_handle) {
175 bta_ag_mgmt_cback(code, port_handle, 3);
176 }
bta_ag_mgmt_cback_4(const tPORT_RESULT code,uint16_t port_handle)177 static void bta_ag_mgmt_cback_4(const tPORT_RESULT code, uint16_t port_handle) {
178 bta_ag_mgmt_cback(code, port_handle, 4);
179 }
bta_ag_mgmt_cback_5(const tPORT_RESULT code,uint16_t port_handle)180 static void bta_ag_mgmt_cback_5(const tPORT_RESULT code, uint16_t port_handle) {
181 bta_ag_mgmt_cback(code, port_handle, 5);
182 }
bta_ag_mgmt_cback_6(const tPORT_RESULT code,uint16_t port_handle)183 static void bta_ag_mgmt_cback_6(const tPORT_RESULT code, uint16_t port_handle) {
184 bta_ag_mgmt_cback(code, port_handle, 6);
185 }
bta_ag_port_cback_1(uint32_t code,uint16_t port_handle)186 static void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle) {
187 bta_ag_port_cback(code, port_handle, 1);
188 }
bta_ag_port_cback_2(uint32_t code,uint16_t port_handle)189 static void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle) {
190 bta_ag_port_cback(code, port_handle, 2);
191 }
bta_ag_port_cback_3(uint32_t code,uint16_t port_handle)192 static void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle) {
193 bta_ag_port_cback(code, port_handle, 3);
194 }
bta_ag_port_cback_4(uint32_t code,uint16_t port_handle)195 static void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle) {
196 bta_ag_port_cback(code, port_handle, 4);
197 }
bta_ag_port_cback_5(uint32_t code,uint16_t port_handle)198 static void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle) {
199 bta_ag_port_cback(code, port_handle, 5);
200 }
bta_ag_port_cback_6(uint32_t code,uint16_t port_handle)201 static void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle) {
202 bta_ag_port_cback(code, port_handle, 6);
203 }
204
205 /*******************************************************************************
206 *
207 * Function bta_ag_setup_port
208 *
209 * Description Setup RFCOMM port for use by AG.
210 *
211 *
212 * Returns void
213 *
214 ******************************************************************************/
bta_ag_setup_port(tBTA_AG_SCB * p_scb,uint16_t handle)215 static void bta_ag_setup_port(tBTA_AG_SCB* p_scb, uint16_t handle) {
216 int port_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
217 log::assert_that(port_callback_index >= 0, "invalid callback index, handle={}, bd_addr={}",
218 handle, ADDRESS_TO_LOGGABLE_STR(p_scb->peer_addr));
219 log::assert_that(port_callback_index < static_cast<int>(sizeof(bta_ag_port_cback_tbl) /
220 sizeof(bta_ag_port_cback_tbl[0])),
221 "callback index out of bound, handle={}, bd_addr={}", handle,
222 ADDRESS_TO_LOGGABLE_STR(p_scb->peer_addr));
223 if (PORT_SetEventMaskAndCallback(handle, BTA_AG_PORT_EV_MASK,
224 bta_ag_port_cback_tbl[port_callback_index]) != PORT_SUCCESS) {
225 log::warn("Unable to set RFCOMM event and callback mask peer:{} handle:{}", p_scb->peer_addr,
226 handle);
227 }
228 }
229
230 /*******************************************************************************
231 *
232 * Function bta_ag_start_servers
233 *
234 * Description Setup RFCOMM servers for use by AG.
235 *
236 *
237 * Returns void
238 *
239 ******************************************************************************/
bta_ag_start_servers(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK services)240 void bta_ag_start_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
241 services >>= BTA_HSP_SERVICE_ID;
242 for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
243 /* if service is set in mask */
244 if (services & 1) {
245 int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
246 log::assert_that(management_callback_index >= 0,
247 "invalid callback index, services=0x{:x}, bd_addr={}", services,
248 ADDRESS_TO_LOGGABLE_STR(p_scb->peer_addr));
249 log::assert_that(
250 management_callback_index < static_cast<int>(sizeof(bta_ag_mgmt_cback_tbl) /
251 sizeof(bta_ag_mgmt_cback_tbl[0])),
252 "callback index out of bound, services=0x{:x}, bd_addr={}", services,
253 ADDRESS_TO_LOGGABLE_STR(p_scb->peer_addr));
254 int status = RFCOMM_CreateConnectionWithSecurity(
255 bta_ag_uuid[i], bta_ag_cb.profile[i].scn, true, BTA_AG_MTU, RawAddress::kAny,
256 &(p_scb->serv_handle[i]), bta_ag_mgmt_cback_tbl[management_callback_index],
257 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
258 if (status == PORT_SUCCESS) {
259 bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
260 } else {
261 /* TODO: CR#137125 to handle to error properly */
262 log::error(
263 "RFCOMM_CreateConnectionWithSecurity ERROR {}, p_scb={}, "
264 "services=0x{:x}, mgmt_cback_index={}",
265 status, std::format_ptr(p_scb), services, management_callback_index);
266 }
267 log::verbose("p_scb=0x{}, services=0x{:04x}, mgmt_cback_index={}", std::format_ptr(p_scb),
268 services, management_callback_index);
269 }
270 }
271 }
272
273 /*******************************************************************************
274 *
275 * Function bta_ag_close_servers
276 *
277 * Description Close RFCOMM servers port for use by AG.
278 *
279 *
280 * Returns void
281 *
282 ******************************************************************************/
bta_ag_close_servers(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK services)283 void bta_ag_close_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
284 services >>= BTA_HSP_SERVICE_ID;
285 for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
286 /* if service is set in mask */
287 if (services & 1) {
288 if (RFCOMM_RemoveServer(p_scb->serv_handle[i]) != PORT_SUCCESS) {
289 log::warn("Unable to remove RFCOMM server service:0x{:x}", services);
290 }
291 p_scb->serv_handle[i] = 0;
292 }
293 }
294 }
295
296 /*******************************************************************************
297 *
298 * Function bta_ag_is_server_closed
299 *
300 * Description Returns true if all servers are closed.
301 *
302 *
303 * Returns true if all servers are closed, false otherwise
304 *
305 ******************************************************************************/
bta_ag_is_server_closed(tBTA_AG_SCB * p_scb)306 bool bta_ag_is_server_closed(tBTA_AG_SCB* p_scb) {
307 uint8_t xx;
308 bool is_closed = true;
309
310 for (xx = 0; xx < BTA_AG_NUM_IDX; xx++) {
311 if (p_scb->serv_handle[xx] != 0) {
312 is_closed = false;
313 }
314 }
315
316 return is_closed;
317 }
318
319 /*******************************************************************************
320 *
321 * Function bta_ag_rfc_do_open
322 *
323 * Description Open an RFCOMM connection to the peer device.
324 *
325 *
326 * Returns void
327 *
328 ******************************************************************************/
bta_ag_rfc_do_open(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)329 void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
330 int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
331 int status = RFCOMM_CreateConnectionWithSecurity(
332 bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, false, BTA_AG_MTU, p_scb->peer_addr,
333 &(p_scb->conn_handle), bta_ag_mgmt_cback_tbl[management_callback_index],
334 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
335 log::verbose("p_scb=0x{}, conn_handle={}, mgmt_cback_index={}, status={}", std::format_ptr(p_scb),
336 p_scb->conn_handle, management_callback_index, status);
337 if (status == PORT_SUCCESS) {
338 bta_ag_setup_port(p_scb, p_scb->conn_handle);
339 } else {
340 /* RFCOMM create connection failed; send ourselves RFCOMM close event */
341 log::error("RFCOMM_CreateConnection ERROR {} for {}", status, p_scb->peer_addr);
342 bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, data);
343 }
344 }
345
346 /*******************************************************************************
347 *
348 * Function bta_ag_rfc_do_close
349 *
350 * Description Close RFCOMM connection.
351 *
352 *
353 * Returns void
354 *
355 ******************************************************************************/
bta_ag_rfc_do_close(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA &)356 void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) {
357 log::info("p_scb->conn_handle: 0x{:04x}", p_scb->conn_handle);
358 if (p_scb->conn_handle) {
359 if (RFCOMM_RemoveConnection(p_scb->conn_handle) != PORT_SUCCESS) {
360 log::warn("Unable to remove RFCOMM connection handle:0x{:04x}", p_scb->conn_handle);
361 }
362 } else {
363 /* Close API was called while AG is in Opening state. */
364 /* Need to trigger the state machine to send callback to the app */
365 /* and move back to INIT state. */
366 do_in_main_thread(base::BindOnce(&bta_ag_sm_execute_by_handle, bta_ag_scb_to_idx(p_scb),
367 BTA_AG_RFC_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
368
369 /* Cancel SDP if it had been started. */
370 /*
371 if(p_scb->p_disc_db)
372 {
373 (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
374 }
375 */
376 }
377 }
378