1 /******************************************************************************
2 *
3 * Copyright (c) 2014 The Android Open Source Project
4 * Copyright 2004-2012 Broadcom Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 /******************************************************************************
21 *
22 * This file contains the audio gateway functions controlling the RFCOMM
23 * connections.
24 *
25 ******************************************************************************/
26
27 #include <bluetooth/log.h>
28
29 #include <cstdint>
30
31 #include "bta/hf_client/bta_hf_client_int.h"
32 #include "bta/include/bta_sec_api.h"
33 #include "osi/include/allocator.h"
34 #include "stack/include/bt_uuid16.h"
35 #include "stack/include/port_api.h"
36 #include "stack/include/sdp_api.h"
37 #include "types/raw_address.h"
38
39 using namespace bluetooth::legacy::stack::sdp;
40 using namespace bluetooth;
41
42 /*******************************************************************************
43 *
44 * Function bta_hf_client_port_cback
45 *
46 * Description RFCOMM Port callback. The handle in this function is
47 * specified by BTA layer via the PORT_SetEventCallback
48 * method
49 *
50 * Returns void
51 *
52 ******************************************************************************/
bta_hf_client_port_cback(uint32_t,uint16_t port_handle)53 static void bta_hf_client_port_cback(uint32_t /* code */,
54 uint16_t port_handle) {
55 /* ignore port events for port handles other than connected handle */
56 tBTA_HF_CLIENT_CB* client_cb =
57 bta_hf_client_find_cb_by_rfc_handle(port_handle);
58 if (client_cb == NULL) {
59 log::error("cb not found for handle {}", port_handle);
60 return;
61 }
62
63 tBTA_HF_CLIENT_RFC* p_buf =
64 (tBTA_HF_CLIENT_RFC*)osi_malloc(sizeof(tBTA_HF_CLIENT_RFC));
65 p_buf->hdr.event = BTA_HF_CLIENT_RFC_DATA_EVT;
66 p_buf->hdr.layer_specific = client_cb->handle;
67 bta_sys_sendmsg(p_buf);
68 }
69
70 /*******************************************************************************
71 *
72 * Function bta_hf_client_mgmt_cback
73 *
74 * Description RFCOMM management callback
75 *
76 *
77 * Returns void
78 *
79 ******************************************************************************/
bta_hf_client_mgmt_cback(const tPORT_RESULT code,uint16_t port_handle)80 static void bta_hf_client_mgmt_cback(const tPORT_RESULT code,
81 uint16_t port_handle) {
82 tBTA_HF_CLIENT_CB* client_cb =
83 bta_hf_client_find_cb_by_rfc_handle(port_handle);
84
85 log::verbose("code = {}, port_handle = {} serv = {}", code, port_handle,
86 bta_hf_client_cb_arr.serv_handle);
87
88 /* ignore close event for port handles other than connected handle */
89 if (code != PORT_SUCCESS && client_cb != NULL &&
90 port_handle != client_cb->conn_handle) {
91 log::verbose("bta_hf_client_mgmt_cback ignoring handle:{}", port_handle);
92 return;
93 }
94
95 tBTA_HF_CLIENT_RFC* p_buf =
96 (tBTA_HF_CLIENT_RFC*)osi_malloc(sizeof(tBTA_HF_CLIENT_RFC));
97
98 if (code == PORT_SUCCESS) {
99 if (client_cb && port_handle == client_cb->conn_handle) { /* out conn */
100 p_buf->hdr.event = BTA_HF_CLIENT_RFC_OPEN_EVT;
101 } else if (port_handle == bta_hf_client_cb_arr.serv_handle) {
102 p_buf->hdr.event = BTA_HF_CLIENT_RFC_OPEN_EVT;
103
104 log::verbose("allocating a new CB for incoming connection");
105 // Find the BDADDR of the peer device
106 RawAddress peer_addr = RawAddress::kEmpty;
107 uint16_t lcid = 0;
108 int status = PORT_CheckConnection(port_handle, &peer_addr, &lcid);
109 if (status != PORT_SUCCESS) {
110 log::error("PORT_CheckConnection returned {}", status);
111 }
112
113 // Since we accepted a remote request we should allocate a handle first.
114 uint16_t tmp_handle = -1;
115 bta_hf_client_allocate_handle(peer_addr, &tmp_handle);
116 client_cb = bta_hf_client_find_cb_by_handle(tmp_handle);
117
118 // If allocation fails then we abort.
119 if (client_cb == NULL) {
120 log::error("error allocating a new handle");
121 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
122 if (RFCOMM_RemoveConnection(port_handle) != PORT_SUCCESS) {
123 log::warn("Unable to remote RFCOMM server connection handle:{}",
124 port_handle);
125 }
126
127 } else {
128 // Set the connection fields for this new CB
129 client_cb->conn_handle = port_handle;
130
131 // Since we have accepted an incoming RFCOMM connection:
132 // a) Release the current server from it duties
133 // b) Start a new server for more new incoming connection
134 bta_hf_client_cb_arr.serv_handle = 0;
135 bta_hf_client_start_server();
136 }
137 } else {
138 log::error("PORT_SUCCESS, ignoring handle = {}", port_handle);
139 osi_free(p_buf);
140 return;
141 }
142 } else if (client_cb != NULL &&
143 port_handle == client_cb->conn_handle) { /* code != PORT_SUC */
144 log::error("closing port handle {} dev {}", port_handle,
145 client_cb->peer_addr);
146
147 if (RFCOMM_RemoveServer(port_handle) != PORT_SUCCESS) {
148 log::warn("Unable to remote RFCOMM server connection handle:{}",
149 port_handle);
150 }
151 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
152 } else if (client_cb == NULL) {
153 // client_cb is already cleaned due to hfp client disabled.
154 // Assigned a valid event value to header and send this message anyway.
155 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
156 }
157
158 p_buf->hdr.layer_specific = client_cb != NULL ? client_cb->handle : 0;
159 bta_sys_sendmsg(p_buf);
160 }
161
162 /*******************************************************************************
163 *
164 * Function bta_hf_client_setup_port
165 *
166 * Description Setup RFCOMM port for use by HF Client.
167 *
168 *
169 * Returns void
170 *
171 ******************************************************************************/
bta_hf_client_setup_port(uint16_t handle)172 void bta_hf_client_setup_port(uint16_t handle) {
173 if (PORT_SetEventMaskAndCallback(handle, PORT_EV_RXCHAR,
174 bta_hf_client_port_cback) != PORT_SUCCESS) {
175 log::warn("Unable to set RFCOMM event mask and callbackhandle:{}", handle);
176 }
177 }
178
179 /*******************************************************************************
180 *
181 * Function bta_hf_client_start_server
182 *
183 * Description Setup RFCOMM server for use by HF Client.
184 *
185 *
186 * Returns void
187 *
188 ******************************************************************************/
bta_hf_client_start_server()189 void bta_hf_client_start_server() {
190 int port_status;
191
192 if (bta_hf_client_cb_arr.serv_handle > 0) {
193 log::verbose("already started, handle: {}",
194 bta_hf_client_cb_arr.serv_handle);
195 return;
196 }
197
198 port_status = RFCOMM_CreateConnectionWithSecurity(
199 UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb_arr.scn, true,
200 BTA_HF_CLIENT_MTU, RawAddress::kAny, &(bta_hf_client_cb_arr.serv_handle),
201 bta_hf_client_mgmt_cback, BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
202
203 log::verbose("started rfcomm server with handle {}",
204 bta_hf_client_cb_arr.serv_handle);
205
206 if (port_status == PORT_SUCCESS) {
207 bta_hf_client_setup_port(bta_hf_client_cb_arr.serv_handle);
208 } else {
209 log::verbose("RFCOMM_CreateConnection returned error:{}", port_status);
210 }
211 }
212
213 /*******************************************************************************
214 *
215 * Function bta_hf_client_close_server
216 *
217 * Description Close RFCOMM server port for use by HF Client.
218 *
219 *
220 * Returns void
221 *
222 ******************************************************************************/
bta_hf_client_close_server()223 void bta_hf_client_close_server() {
224 log::verbose("{}", bta_hf_client_cb_arr.serv_handle);
225
226 if (bta_hf_client_cb_arr.serv_handle == 0) {
227 log::verbose("already stopped");
228 return;
229 }
230
231 if (RFCOMM_RemoveServer(bta_hf_client_cb_arr.serv_handle) != PORT_SUCCESS) {
232 log::warn("Unable to remove RFCOMM servier handle:{}",
233 bta_hf_client_cb_arr.serv_handle);
234 }
235 bta_hf_client_cb_arr.serv_handle = 0;
236 }
237
238 /*******************************************************************************
239 *
240 * Function bta_hf_client_rfc_do_open
241 *
242 * Description Open an RFCOMM connection to the peer device.
243 *
244 *
245 * Returns void
246 *
247 ******************************************************************************/
bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA * p_data)248 void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA* p_data) {
249 tBTA_HF_CLIENT_CB* client_cb =
250 bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
251 if (client_cb == NULL) {
252 log::error("cb not found for handle {}", p_data->hdr.layer_specific);
253 return;
254 }
255
256 if (RFCOMM_CreateConnectionWithSecurity(
257 UUID_SERVCLASS_HF_HANDSFREE, client_cb->peer_scn, false,
258 BTA_HF_CLIENT_MTU, client_cb->peer_addr, &(client_cb->conn_handle),
259 bta_hf_client_mgmt_cback,
260 BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) == PORT_SUCCESS) {
261 bta_hf_client_setup_port(client_cb->conn_handle);
262 log::verbose("bta_hf_client_rfc_do_open : conn_handle = {}",
263 client_cb->conn_handle);
264 }
265 /* RFCOMM create connection failed; send ourselves RFCOMM close event */
266 else {
267 bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data);
268 }
269 }
270
271 /*******************************************************************************
272 *
273 * Function bta_hf_client_rfc_do_close
274 *
275 * Description Close RFCOMM connection.
276 *
277 *
278 * Returns void
279 *
280 ******************************************************************************/
bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA * p_data)281 void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA* p_data) {
282 tBTA_HF_CLIENT_CB* client_cb =
283 bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
284 if (client_cb == NULL) {
285 log::error("cb not found for handle {}", p_data->hdr.layer_specific);
286 return;
287 }
288
289 if (client_cb->conn_handle) {
290 if (RFCOMM_RemoveConnection(client_cb->conn_handle) != PORT_SUCCESS) {
291 log::warn("Unable to remove RFCOMM connection peer:{} handle:{}",
292 client_cb->peer_addr, client_cb->conn_handle);
293 }
294 } else {
295 /* Close API was called while HF Client is in Opening state. */
296 /* Need to trigger the state machine to send callback to the app */
297 /* and move back to INIT state. */
298 tBTA_HF_CLIENT_RFC* p_buf =
299 (tBTA_HF_CLIENT_RFC*)osi_malloc(sizeof(tBTA_HF_CLIENT_RFC));
300 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
301 bta_sys_sendmsg(p_buf);
302
303 /* Cancel SDP if it had been started. */
304 if (client_cb->p_disc_db) {
305 (void)get_legacy_stack_sdp_api()->service.SDP_CancelServiceSearch(
306 client_cb->p_disc_db);
307 osi_free_and_reset((void**)&client_cb->p_disc_db);
308 }
309 }
310 }
311