• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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