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_rfcomm_metrics.h"
33 #include "bta/include/bta_sec_api.h"
34 #include "bta_api.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, 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, p_scb->peer_addr);
222 if (PORT_SetEventMaskAndCallback(handle, BTA_AG_PORT_EV_MASK,
223 bta_ag_port_cback_tbl[port_callback_index]) != PORT_SUCCESS) {
224 log::warn("Unable to set RFCOMM event and callback mask peer:{} handle:{}", p_scb->peer_addr,
225 handle);
226 }
227 }
228
229 /*******************************************************************************
230 *
231 * Function bta_ag_start_servers
232 *
233 * Description Setup RFCOMM servers for use by AG.
234 *
235 *
236 * Returns void
237 *
238 ******************************************************************************/
bta_ag_start_servers(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK services)239 void bta_ag_start_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
240 services >>= BTA_HSP_SERVICE_ID;
241 for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
242 /* if service is set in mask */
243 if (services & 1) {
244 int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
245 log::assert_that(management_callback_index >= 0,
246 "invalid callback index, services=0x{:x}, bd_addr={}", services,
247 p_scb->peer_addr);
248 log::assert_that(
249 management_callback_index < static_cast<int>(sizeof(bta_ag_mgmt_cback_tbl) /
250 sizeof(bta_ag_mgmt_cback_tbl[0])),
251 "callback index out of bound, services=0x{:x}, bd_addr={}", services,
252 p_scb->peer_addr);
253 int status = RFCOMM_CreateConnectionWithSecurity(
254 bta_ag_uuid[i], bta_ag_cb.profile[i].scn, true, BTA_AG_MTU, RawAddress::kAny,
255 &(p_scb->serv_handle[i]), bta_ag_mgmt_cback_tbl[management_callback_index],
256 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, RfcommCfgInfo{});
257 if (status == PORT_SUCCESS) {
258 bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
259 } else {
260 /* TODO: CR#137125 to handle to error properly */
261 bta_collect_rfc_metrics_after_port_fail(static_cast<tPORT_RESULT>(status), false,
262 tBTA_JV_STATUS::SUCCESS, p_scb->peer_addr, 0,
263 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, true, 0);
264 log::error(
265 "RFCOMM_CreateConnectionWithSecurity ERROR {}, p_scb={}, "
266 "services=0x{:x}, mgmt_cback_index={}",
267 status, std::format_ptr(p_scb), services, management_callback_index);
268 }
269 log::verbose("p_scb=0x{}, services=0x{:04x}, mgmt_cback_index={}", std::format_ptr(p_scb),
270 services, management_callback_index);
271 }
272 }
273 }
274
275 /*******************************************************************************
276 *
277 * Function bta_ag_close_servers
278 *
279 * Description Close RFCOMM servers port for use by AG.
280 *
281 *
282 * Returns void
283 *
284 ******************************************************************************/
bta_ag_close_servers(tBTA_AG_SCB * p_scb,tBTA_SERVICE_MASK services)285 void bta_ag_close_servers(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK services) {
286 services >>= BTA_HSP_SERVICE_ID;
287 for (int i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1) {
288 /* if service is set in mask */
289 if (services & 1) {
290 if (RFCOMM_RemoveServer(p_scb->serv_handle[i]) != PORT_SUCCESS) {
291 log::warn("Unable to remove RFCOMM server service:0x{:x}", services);
292 }
293 p_scb->serv_handle[i] = 0;
294 }
295 }
296 }
297
298 /*******************************************************************************
299 *
300 * Function bta_ag_is_server_closed
301 *
302 * Description Returns true if all servers are closed.
303 *
304 *
305 * Returns true if all servers are closed, false otherwise
306 *
307 ******************************************************************************/
bta_ag_is_server_closed(tBTA_AG_SCB * p_scb)308 bool bta_ag_is_server_closed(tBTA_AG_SCB* p_scb) {
309 uint8_t xx;
310 bool is_closed = true;
311
312 for (xx = 0; xx < BTA_AG_NUM_IDX; xx++) {
313 if (p_scb->serv_handle[xx] != 0) {
314 is_closed = false;
315 }
316 }
317
318 return is_closed;
319 }
320
321 /*******************************************************************************
322 *
323 * Function bta_ag_rfc_do_open
324 *
325 * Description Open an RFCOMM connection to the peer device.
326 *
327 *
328 * Returns void
329 *
330 ******************************************************************************/
bta_ag_rfc_do_open(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)331 void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
332 int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
333 int status = RFCOMM_CreateConnectionWithSecurity(
334 bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, false, BTA_AG_MTU, p_scb->peer_addr,
335 &(p_scb->conn_handle), bta_ag_mgmt_cback_tbl[management_callback_index],
336 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT, RfcommCfgInfo{});
337 log::verbose("p_scb=0x{}, conn_handle={}, mgmt_cback_index={}, status={}", std::format_ptr(p_scb),
338 p_scb->conn_handle, management_callback_index, status);
339 if (status == PORT_SUCCESS) {
340 bta_ag_setup_port(p_scb, p_scb->conn_handle);
341 } else {
342 /* RFCOMM create connection failed; send ourselves RFCOMM close event */
343 bta_collect_rfc_metrics_after_port_fail(
344 static_cast<tPORT_RESULT>(status), p_scb->sdp_metrics.sdp_initiated,
345 p_scb->sdp_metrics.status, p_scb->peer_addr, 0, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT,
346 true, p_scb->sdp_metrics.sdp_start_ms - p_scb->sdp_metrics.sdp_end_ms);
347 log::error("RFCOMM_CreateConnection ERROR {} for {}", status, p_scb->peer_addr);
348 bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, data);
349 }
350 }
351
352 /*******************************************************************************
353 *
354 * Function bta_ag_rfc_do_close
355 *
356 * Description Close RFCOMM connection.
357 *
358 *
359 * Returns void
360 *
361 ******************************************************************************/
bta_ag_rfc_do_close(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA &)362 void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& /* data */) {
363 log::info("p_scb->conn_handle: 0x{:04x}", p_scb->conn_handle);
364 if (p_scb->conn_handle) {
365 if (RFCOMM_RemoveConnection(p_scb->conn_handle) != PORT_SUCCESS) {
366 log::warn("Unable to remove RFCOMM connection handle:0x{:04x}", p_scb->conn_handle);
367 }
368 } else {
369 /* Close API was called while AG is in Opening state. */
370 /* Need to trigger the state machine to send callback to the app */
371 /* and move back to INIT state. */
372 do_in_main_thread(base::BindOnce(&bta_ag_sm_execute_by_handle, bta_ag_scb_to_idx(p_scb),
373 BTA_AG_RFC_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
374
375 /* Cancel SDP if it had been started. */
376 /*
377 if(p_scb->p_disc_db)
378 {
379 (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
380 }
381 */
382 }
383 }
384