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