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