1 /******************************************************************************
2 *
3 * Copyright (c) 2014 The Android Open Source Project
4 * Copyright (C) 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 <string.h>
28 #include "bta_api.h"
29 #include "bta_hf_client_int.h"
30 #include "port_api.h"
31 #include "bd.h"
32 #include "bt_utils.h"
33
34 /*******************************************************************************
35 **
36 ** Function bta_hf_client_port_cback
37 **
38 ** Description RFCOMM Port callback
39 **
40 **
41 ** Returns void
42 **
43 *******************************************************************************/
bta_hf_client_port_cback(UINT32 code,UINT16 port_handle)44 static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle)
45 {
46 BT_HDR *p_buf;
47 UNUSED(code);
48
49 /* ignore port events for port handles other than connected handle */
50 if (port_handle != bta_hf_client_cb.scb.conn_handle)
51 {
52 APPL_TRACE_DEBUG("bta_hf_client_port_cback ignoring handle:%d conn_handle = %d",
53 port_handle, bta_hf_client_cb.scb.conn_handle);
54 return;
55 }
56
57 if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
58 {
59 p_buf->event = BTA_HF_CLIENT_RFC_DATA_EVT;
60 bta_sys_sendmsg(p_buf);
61 }
62 }
63
64 /*******************************************************************************
65 **
66 ** Function bta_hf_client_mgmt_cback
67 **
68 ** Description RFCOMM management callback
69 **
70 **
71 ** Returns void
72 **
73 *******************************************************************************/
bta_hf_client_mgmt_cback(UINT32 code,UINT16 port_handle)74 static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle)
75 {
76 tBTA_HF_CLIENT_RFC *p_buf;
77 UINT16 event;
78
79 APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback : code = %d, port_handle = %d, conn_handle = %d, serv_handle = %d",
80 code, port_handle, bta_hf_client_cb.scb.conn_handle, bta_hf_client_cb.scb.serv_handle);
81
82 /* ignore close event for port handles other than connected handle */
83 if ((code != PORT_SUCCESS) && (port_handle != bta_hf_client_cb.scb.conn_handle))
84 {
85 APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d", port_handle);
86 return;
87 }
88
89 if (code == PORT_SUCCESS)
90 {
91 if ((bta_hf_client_cb.scb.conn_handle && (port_handle == bta_hf_client_cb.scb.conn_handle)) || /* outgoing connection */
92 (port_handle == bta_hf_client_cb.scb.serv_handle)) /* incoming connection */
93 {
94 event = BTA_HF_CLIENT_RFC_OPEN_EVT;
95 }
96 else
97 {
98 APPL_TRACE_ERROR ("bta_hf_client_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle);
99 return;
100 }
101 }
102 /* distinguish server close events */
103 else if (port_handle == bta_hf_client_cb.scb.conn_handle)
104 {
105 event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
106 }
107 else
108 {
109 event = BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT;
110 }
111
112 if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL)
113 {
114 p_buf->hdr.event = event;
115 p_buf->port_handle = port_handle;
116 bta_sys_sendmsg(p_buf);
117 }
118 }
119
120 /*******************************************************************************
121 **
122 ** Function bta_hf_client_setup_port
123 **
124 ** Description Setup RFCOMM port for use by HF Client.
125 **
126 **
127 ** Returns void
128 **
129 *******************************************************************************/
bta_hf_client_setup_port(UINT16 handle)130 void bta_hf_client_setup_port(UINT16 handle)
131 {
132 PORT_SetEventMask(handle, PORT_EV_RXCHAR);
133 PORT_SetEventCallback(handle, bta_hf_client_port_cback);
134 }
135
136 /*******************************************************************************
137 **
138 ** Function bta_hf_client_start_server
139 **
140 ** Description Setup RFCOMM server for use by HF Client.
141 **
142 **
143 ** Returns void
144 **
145 *******************************************************************************/
bta_hf_client_start_server(void)146 void bta_hf_client_start_server(void)
147 {
148 int i;
149 int port_status;
150
151 if (bta_hf_client_cb.scb.serv_handle > 0)
152 {
153 APPL_TRACE_DEBUG("%s already started, handle: %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle);
154 return;
155 }
156
157 BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HF_HANDSFREE, bta_hf_client_cb.scb.serv_sec_mask,
158 BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scn);
159
160 port_status = RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scn,
161 TRUE, BTA_HF_CLIENT_MTU, (UINT8 *) bd_addr_any, &(bta_hf_client_cb.scb.serv_handle),
162 bta_hf_client_mgmt_cback);
163
164 if (port_status == PORT_SUCCESS)
165 {
166 bta_hf_client_setup_port(bta_hf_client_cb.scb.serv_handle);
167 }
168 else
169 {
170 /* TODO: can we handle this better? */
171 APPL_TRACE_DEBUG("bta_hf_client_start_server: RFCOMM_CreateConnection returned error:%d", port_status);
172 }
173
174 APPL_TRACE_DEBUG("bta_hf_client_start_server handle: %d", bta_hf_client_cb.scb.serv_handle);
175 }
176
177 /*******************************************************************************
178 **
179 ** Function bta_hf_client_close_server
180 **
181 ** Description Close RFCOMM server port for use by HF Client.
182 **
183 **
184 ** Returns void
185 **
186 *******************************************************************************/
bta_hf_client_close_server(void)187 void bta_hf_client_close_server(void)
188 {
189 APPL_TRACE_DEBUG("%s %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle);
190
191 if (bta_hf_client_cb.scb.serv_handle == 0)
192 {
193 APPL_TRACE_DEBUG("%s already stopped", __FUNCTION__);
194 return;
195 }
196
197 RFCOMM_RemoveServer(bta_hf_client_cb.scb.serv_handle);
198 bta_hf_client_cb.scb.serv_handle = 0;
199 }
200
201 /*******************************************************************************
202 **
203 ** Function bta_hf_client_rfc_do_open
204 **
205 ** Description Open an RFCOMM connection to the peer device.
206 **
207 **
208 ** Returns void
209 **
210 *******************************************************************************/
bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA * p_data)211 void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data)
212 {
213 BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HF_HANDSFREE,
214 bta_hf_client_cb.scb.cli_sec_mask, BT_PSM_RFCOMM,
215 BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scb.peer_scn);
216
217 if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scb.peer_scn,
218 FALSE, BTA_HF_CLIENT_MTU, bta_hf_client_cb.scb.peer_addr, &(bta_hf_client_cb.scb.conn_handle),
219 bta_hf_client_mgmt_cback) == PORT_SUCCESS)
220 {
221 bta_hf_client_setup_port(bta_hf_client_cb.scb.conn_handle);
222 APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d", bta_hf_client_cb.scb.conn_handle);
223 }
224 /* RFCOMM create connection failed; send ourselves RFCOMM close event */
225 else
226 {
227 bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data);
228 }
229 }
230
231 /*******************************************************************************
232 **
233 ** Function bta_hf_client_rfc_do_close
234 **
235 ** Description Close RFCOMM connection.
236 **
237 **
238 ** Returns void
239 **
240 *******************************************************************************/
bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA * p_data)241 void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data)
242 {
243 tBTA_HF_CLIENT_RFC *p_buf;
244 UNUSED(p_data);
245
246 if (bta_hf_client_cb.scb.conn_handle)
247 {
248 RFCOMM_RemoveConnection(bta_hf_client_cb.scb.conn_handle);
249 }
250 else
251 {
252 /* Close API was called while HF Client is in Opening state. */
253 /* Need to trigger the state machine to send callback to the app */
254 /* and move back to INIT state. */
255 if ((p_buf = (tBTA_HF_CLIENT_RFC *) GKI_getbuf(sizeof(tBTA_HF_CLIENT_RFC))) != NULL)
256 {
257 p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT;
258 bta_sys_sendmsg(p_buf);
259 }
260
261 /* Cancel SDP if it had been started. */
262 if(bta_hf_client_cb.scb.p_disc_db)
263 {
264 (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db);
265 bta_hf_client_free_db(NULL);
266 }
267 }
268 }
269