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