• 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 "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