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/bind.h>
27 #include <cstring>
28
29 #include "bta/ag/bta_ag_int.h"
30 #include "osi/include/osi.h"
31 #include "stack/include/btu.h" // do_in_main_thread
32 #include "stack/include/port_api.h"
33
34 /* Event mask for RfCOMM port callback */
35 #define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR
36
37 /* each scb has its own rfcomm callbacks */
38 void bta_ag_port_cback_1(uint32_t code, uint16_t port_handle);
39 void bta_ag_port_cback_2(uint32_t code, uint16_t port_handle);
40 void bta_ag_port_cback_3(uint32_t code, uint16_t port_handle);
41 void bta_ag_port_cback_4(uint32_t code, uint16_t port_handle);
42 void bta_ag_port_cback_5(uint32_t code, uint16_t port_handle);
43 void bta_ag_port_cback_6(uint32_t code, uint16_t port_handle);
44 void bta_ag_mgmt_cback_1(uint32_t code, uint16_t port_handle);
45 void bta_ag_mgmt_cback_2(uint32_t code, uint16_t port_handle);
46 void bta_ag_mgmt_cback_3(uint32_t code, uint16_t port_handle);
47 void bta_ag_mgmt_cback_4(uint32_t code, uint16_t port_handle);
48 void bta_ag_mgmt_cback_5(uint32_t code, uint16_t port_handle);
49 void bta_ag_mgmt_cback_6(uint32_t code, uint16_t port_handle);
50
51 /* rfcomm callback function tables */
52 typedef tPORT_CALLBACK* tBTA_AG_PORT_CBACK;
53 const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] = {
54 bta_ag_port_cback_1, bta_ag_port_cback_2, bta_ag_port_cback_3,
55 bta_ag_port_cback_4, bta_ag_port_cback_5, bta_ag_port_cback_6};
56
57 const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] = {
58 bta_ag_mgmt_cback_1, bta_ag_mgmt_cback_2, bta_ag_mgmt_cback_3,
59 bta_ag_mgmt_cback_4, bta_ag_mgmt_cback_5, bta_ag_mgmt_cback_6};
60
61 /*******************************************************************************
62 *
63 * Function bta_ag_port_cback
64 *
65 * Description RFCOMM Port callback
66 *
67 *
68 * Returns void
69 *
70 ******************************************************************************/
bta_ag_port_cback(UNUSED_ATTR uint32_t code,uint16_t port_handle,uint16_t handle)71 static void bta_ag_port_cback(UNUSED_ATTR uint32_t code, uint16_t port_handle,
72 uint16_t handle) {
73 tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
74 if (p_scb != nullptr) {
75 /* ignore port events for port handles other than connected handle */
76 if (port_handle != p_scb->conn_handle) {
77 APPL_TRACE_ERROR(
78 "ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
79 port_handle, p_scb->conn_handle, handle);
80 return;
81 }
82 if (!bta_ag_scb_open(p_scb)) {
83 LOG(ERROR) << __func__ << ": rfcomm data on an unopened control block "
84 << handle << " peer_addr " << p_scb->peer_addr << " state "
85 << std::to_string(p_scb->state);
86 }
87 do_in_main_thread(FROM_HERE,
88 base::Bind(&bta_ag_sm_execute_by_handle, handle,
89 BTA_AG_RFC_DATA_EVT, tBTA_AG_DATA::kEmpty));
90 }
91 }
92
93 /*******************************************************************************
94 *
95 * Function bta_ag_mgmt_cback
96 *
97 * Description RFCOMM management callback
98 *
99 *
100 * Returns void
101 *
102 ******************************************************************************/
bta_ag_mgmt_cback(uint32_t code,uint16_t port_handle,uint16_t handle)103 static void bta_ag_mgmt_cback(uint32_t code, uint16_t port_handle,
104 uint16_t handle) {
105 tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(handle);
106 APPL_TRACE_DEBUG("%s: code=%d, port_handle=%d, scb_handle=%d, p_scb=0x%08x",
107 __func__, code, port_handle, handle, p_scb);
108 if (p_scb == nullptr) {
109 LOG(WARNING) << __func__ << ": cannot find scb, code=" << code
110 << ", port_handle=" << port_handle << ", handle=" << handle;
111 return;
112 }
113 /* ignore close event for port handles other than connected handle */
114 if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle)) {
115 LOG(WARNING) << __func__ << ": ignore open failure for unmatched "
116 << "port_handle " << port_handle << ", scb_handle=" << handle;
117 return;
118 }
119 uint16_t event;
120 if (code == PORT_SUCCESS) {
121 bool found_handle = false;
122 if (p_scb->conn_handle) {
123 /* Outgoing connection */
124 if (port_handle == p_scb->conn_handle) {
125 found_handle = true;
126 }
127 } else {
128 /* Incoming connection */
129 for (uint16_t service_port_handle : p_scb->serv_handle) {
130 if (port_handle == service_port_handle) {
131 found_handle = true;
132 break;
133 }
134 }
135 }
136 if (!found_handle) {
137 LOG(ERROR) << __func__ << ": port opened successfully, but port_handle "
138 << port_handle << " is unknown"
139 << ", scb_handle=" << handle;
140 return;
141 }
142 event = BTA_AG_RFC_OPEN_EVT;
143 } else if (port_handle == p_scb->conn_handle) {
144 /* distinguish server close events */
145 event = BTA_AG_RFC_CLOSE_EVT;
146 } else {
147 event = BTA_AG_RFC_SRV_CLOSE_EVT;
148 }
149
150 tBTA_AG_DATA data = {};
151 data.rfc.port_handle = port_handle;
152 do_in_main_thread(
153 FROM_HERE, base::Bind(&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(uint32_t code,uint16_t port_handle)168 void bta_ag_mgmt_cback_1(uint32_t code, uint16_t port_handle) {
169 bta_ag_mgmt_cback(code, port_handle, 1);
170 }
bta_ag_mgmt_cback_2(uint32_t code,uint16_t port_handle)171 void bta_ag_mgmt_cback_2(uint32_t code, uint16_t port_handle) {
172 bta_ag_mgmt_cback(code, port_handle, 2);
173 }
bta_ag_mgmt_cback_3(uint32_t code,uint16_t port_handle)174 void bta_ag_mgmt_cback_3(uint32_t code, uint16_t port_handle) {
175 bta_ag_mgmt_cback(code, port_handle, 3);
176 }
bta_ag_mgmt_cback_4(uint32_t code,uint16_t port_handle)177 void bta_ag_mgmt_cback_4(uint32_t code, uint16_t port_handle) {
178 bta_ag_mgmt_cback(code, port_handle, 4);
179 }
bta_ag_mgmt_cback_5(uint32_t code,uint16_t port_handle)180 void bta_ag_mgmt_cback_5(uint32_t code, uint16_t port_handle) {
181 bta_ag_mgmt_cback(code, port_handle, 5);
182 }
bta_ag_mgmt_cback_6(uint32_t code,uint16_t port_handle)183 void bta_ag_mgmt_cback_6(uint32_t 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 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 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 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 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 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 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 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 CHECK_GE(port_callback_index, 0)
218 << "invalid callback index, handle=" << handle << ", bd_addr"
219 << p_scb->peer_addr;
220 CHECK_LT(port_callback_index,
221 static_cast<int>(sizeof(bta_ag_port_cback_tbl) /
222 sizeof(bta_ag_port_cback_tbl[0])))
223 << "callback index out of bound, handle=" << handle << ", bd_addr"
224 << p_scb->peer_addr;
225 PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
226 PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[port_callback_index]);
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 CHECK_GE(management_callback_index, 0)
246 << "invalid callback index, services=" << loghex(services)
247 << ", bd_addr=" << p_scb->peer_addr;
248 CHECK_LT(management_callback_index,
249 static_cast<int>(sizeof(bta_ag_mgmt_cback_tbl) /
250 sizeof(bta_ag_mgmt_cback_tbl[0])))
251 << "callback index out of bound, services=" << loghex(services)
252 << ", bd_addr" << p_scb->peer_addr;
253 int status = RFCOMM_CreateConnectionWithSecurity(
254 bta_ag_uuid[i], bta_ag_cb.profile[i].scn, true, BTA_AG_MTU,
255 RawAddress::kAny, &(p_scb->serv_handle[i]),
256 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) << __func__ << ": RFCOMM_CreateConnectionWithSecurity ERROR "
263 << status << ", p_scb=" << p_scb
264 << ", services=" << loghex(services)
265 << ", mgmt_cback_index=" << management_callback_index;
266 }
267 APPL_TRACE_DEBUG("%s: p_scb=0x%08x, services=0x%04x, mgmt_cback_index=%d",
268 __func__, p_scb, 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 RFCOMM_RemoveServer(p_scb->serv_handle[i]);
289 p_scb->serv_handle[i] = 0;
290 }
291 }
292 }
293
294 /*******************************************************************************
295 *
296 * Function bta_ag_is_server_closed
297 *
298 * Description Returns true if all servers are closed.
299 *
300 *
301 * Returns true if all servers are closed, false otherwise
302 *
303 ******************************************************************************/
bta_ag_is_server_closed(tBTA_AG_SCB * p_scb)304 bool bta_ag_is_server_closed(tBTA_AG_SCB* p_scb) {
305 uint8_t xx;
306 bool is_closed = true;
307
308 for (xx = 0; xx < BTA_AG_NUM_IDX; xx++) {
309 if (p_scb->serv_handle[xx] != 0) is_closed = false;
310 }
311
312 return is_closed;
313 }
314
315 /*******************************************************************************
316 *
317 * Function bta_ag_rfc_do_open
318 *
319 * Description Open an RFCOMM connection to the peer device.
320 *
321 *
322 * Returns void
323 *
324 ******************************************************************************/
bta_ag_rfc_do_open(tBTA_AG_SCB * p_scb,const tBTA_AG_DATA & data)325 void bta_ag_rfc_do_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
326 int management_callback_index = bta_ag_scb_to_idx(p_scb) - 1;
327 int status = RFCOMM_CreateConnectionWithSecurity(
328 bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn, false, BTA_AG_MTU,
329 p_scb->peer_addr, &(p_scb->conn_handle),
330 bta_ag_mgmt_cback_tbl[management_callback_index],
331 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
332 APPL_TRACE_DEBUG(
333 "%s: p_scb=0x%08x, conn_handle=%d, mgmt_cback_index=%d,"
334 " status=%d",
335 __func__, p_scb, p_scb->conn_handle, management_callback_index, status);
336 if (status == PORT_SUCCESS) {
337 bta_ag_setup_port(p_scb, p_scb->conn_handle);
338 } else {
339 /* RFCOMM create connection failed; send ourselves RFCOMM close event */
340 LOG(ERROR) << __func__ << ": RFCOMM_CreateConnection ERROR " << status
341 << " for " << 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,UNUSED_ATTR const tBTA_AG_DATA & data)356 void bta_ag_rfc_do_close(tBTA_AG_SCB* p_scb,
357 UNUSED_ATTR const tBTA_AG_DATA& data) {
358 if (p_scb->conn_handle) {
359 RFCOMM_RemoveConnection(p_scb->conn_handle);
360 } else {
361 /* Close API was called while AG is in Opening state. */
362 /* Need to trigger the state machine to send callback to the app */
363 /* and move back to INIT state. */
364 do_in_main_thread(
365 FROM_HERE,
366 base::Bind(&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