• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (c) 2014 The Android Open Source Project
4  *  Copyright (C) 2003-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 action functions for the handsfree client.
23  *
24  ******************************************************************************/
25 
26 #include <string.h>
27 #include "bt_utils.h"
28 #include "bta_api.h"
29 #include "bta_dm_api.h"
30 #include "bta_hf_client_api.h"
31 #include "bta_hf_client_int.h"
32 #include "bta_sys.h"
33 #include "l2c_api.h"
34 #include "osi/include/compat.h"
35 #include "osi/include/osi.h"
36 #include "port_api.h"
37 #include "utl.h"
38 
39 /*****************************************************************************
40  *  Constants
41  ****************************************************************************/
42 
43 /* maximum length of data to read from RFCOMM */
44 #define BTA_HF_CLIENT_RFC_READ_MAX 512
45 
46 /*******************************************************************************
47  *
48  * Function         bta_hf_client_start_close
49  *
50  * Description      Start the process of closing SCO and RFCOMM connection.
51  *
52  *
53  * Returns          void
54  *
55  ******************************************************************************/
bta_hf_client_start_close(tBTA_HF_CLIENT_DATA * p_data)56 void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA* p_data) {
57   tBTA_HF_CLIENT_CB* client_cb =
58       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
59   if (client_cb == NULL) {
60     APPL_TRACE_ERROR("%s: wrong handle to control block %d", __func__,
61                      p_data->hdr.layer_specific);
62     return;
63   }
64 
65   /* Take the link out of sniff and set L2C idle time to 0 */
66   bta_dm_pm_active(client_cb->peer_addr);
67   L2CA_SetIdleTimeoutByBdAddr(client_cb->peer_addr, 0, BT_TRANSPORT_BR_EDR);
68 
69   /* if SCO is open close SCO and wait on RFCOMM close */
70   if (client_cb->sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) {
71     client_cb->sco_close_rfc = true;
72   } else {
73     bta_hf_client_rfc_do_close(p_data);
74   }
75 
76   /* always do SCO shutdown to handle all SCO corner cases */
77   bta_hf_client_sco_shutdown(client_cb);
78 }
79 
80 /*******************************************************************************
81  *
82  * Function         bta_hf_client_start_open
83  *
84  * Description      This starts an HF Client open.
85  *
86  *
87  * Returns          void
88  *
89  ******************************************************************************/
bta_hf_client_start_open(tBTA_HF_CLIENT_DATA * p_data)90 void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA* p_data) {
91   tBTA_HF_CLIENT_CB* client_cb =
92       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
93   if (client_cb == NULL) {
94     APPL_TRACE_ERROR("%s: wrong handle to control block %d", __func__,
95                      p_data->hdr.layer_specific);
96     return;
97   }
98 
99   /* store parameters */
100   if (p_data) {
101     client_cb->peer_addr = p_data->api_open.bd_addr;
102     client_cb->cli_sec_mask = p_data->api_open.sec_mask;
103   }
104 
105   /* Check if RFCOMM has any incoming connection to avoid collision. */
106   RawAddress pending_bd_addr;
107   if (PORT_IsOpening(pending_bd_addr)) {
108     /* Let the incoming connection goes through.                        */
109     /* Issue collision for now.                                         */
110     /* We will decide what to do when we find incoming connection later.*/
111     bta_hf_client_collision_cback(0, BTA_ID_HS, 0, &client_cb->peer_addr);
112     return;
113   }
114 
115   /* set role */
116   client_cb->role = BTA_HF_CLIENT_INT;
117 
118   /* do service search */
119   bta_hf_client_do_disc(client_cb);
120 }
121 
122 /*******************************************************************************
123  *
124  * Function         bta_hf_client_rfc_open
125  *
126  * Description      Handle RFCOMM channel open.
127  *
128  *
129  * Returns          void
130  *
131  ******************************************************************************/
bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA * p_data)132 void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA* p_data) {
133   APPL_TRACE_DEBUG("%s", __func__);
134   tBTA_HF_CLIENT_CB* client_cb =
135       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
136   if (client_cb == NULL) {
137     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
138                      p_data->hdr.layer_specific);
139     return;
140   }
141 
142   bta_sys_conn_open(BTA_ID_HS, 1, client_cb->peer_addr);
143 
144   /* start SLC procedure */
145   bta_hf_client_slc_seq(client_cb, false);
146 }
147 
148 /*******************************************************************************
149  *
150  * Function         bta_hf_client_rfc_acp_open
151  *
152  * Description      Handle RFCOMM channel open when accepting connection.
153  *
154  *
155  * Returns          void
156  *
157  ******************************************************************************/
bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA * p_data)158 void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA* p_data) {
159   APPL_TRACE_DEBUG("%s", __func__);
160   tBTA_HF_CLIENT_CB* client_cb =
161       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
162   if (client_cb == NULL) {
163     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
164                      p_data->hdr.layer_specific);
165     return;
166   }
167 
168   uint16_t lcid;
169   RawAddress dev_addr;
170   int status;
171 
172   /* set role */
173   client_cb->role = BTA_HF_CLIENT_ACP;
174 
175   APPL_TRACE_DEBUG("%s: conn_handle %d", __func__, client_cb->conn_handle);
176 
177   /* get bd addr of peer */
178   if (PORT_SUCCESS != (status = PORT_CheckConnection(client_cb->conn_handle,
179                                                      dev_addr, &lcid))) {
180     APPL_TRACE_DEBUG("%s: error PORT_CheckConnection returned status %d",
181                      __func__, status);
182   }
183 
184   /* Collision Handling */
185   if (alarm_is_scheduled(client_cb->collision_timer)) {
186     alarm_cancel(client_cb->collision_timer);
187 
188     if (dev_addr == client_cb->peer_addr) {
189       /* If incoming and outgoing device are same, nothing more to do. */
190       /* Outgoing conn will be aborted because we have successful incoming conn.
191        */
192     } else {
193       /* Resume outgoing connection. */
194       bta_hf_client_resume_open(client_cb);
195     }
196   }
197 
198   client_cb->peer_addr = dev_addr;
199 
200   /* do service discovery to get features */
201   bta_hf_client_do_disc(client_cb);
202 
203   /* continue with open processing */
204   bta_hf_client_rfc_open(p_data);
205 }
206 
207 /*******************************************************************************
208  *
209  * Function         bta_hf_client_rfc_fail
210  *
211  * Description      RFCOMM connection failed.
212  *
213  *
214  * Returns          void
215  *
216  ******************************************************************************/
bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA * p_data)217 void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA* p_data) {
218   tBTA_HF_CLIENT_CB* client_cb =
219       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
220   if (client_cb == NULL) {
221     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
222                      p_data->hdr.layer_specific);
223     return;
224   }
225 
226   /* reinitialize stuff */
227   client_cb->peer_features = 0;
228   client_cb->chld_features = 0;
229   client_cb->role = BTA_HF_CLIENT_ACP;
230   client_cb->svc_conn = false;
231   client_cb->send_at_reply = false;
232   client_cb->negotiated_codec = BTM_SCO_CODEC_CVSD;
233 
234   bta_hf_client_at_reset(client_cb);
235 }
236 
237 /*******************************************************************************
238  *
239  * Function         bta_hf_client_disc_fail
240  *
241  * Description      This function handles a discovery failure.
242  *
243  *
244  * Returns          void
245  *
246  ******************************************************************************/
bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA * p_data)247 void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA* p_data) {
248   tBTA_HF_CLIENT_CB* client_cb =
249       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
250   if (client_cb == NULL) {
251     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
252                      p_data->hdr.layer_specific);
253     return;
254   }
255 }
256 
257 /*******************************************************************************
258  *
259  * Function         bta_hf_client_open_fail
260  *
261  * Description      open connection failed.
262  *
263  *
264  * Returns          void
265  *
266  ******************************************************************************/
bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA * p_data)267 void bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA* p_data) {
268   tBTA_HF_CLIENT_CB* client_cb =
269       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
270   if (client_cb == NULL) {
271     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
272                      p_data->hdr.layer_specific);
273     return;
274   }
275 }
276 
277 /*******************************************************************************
278  *
279  * Function         bta_hf_client_rfc_close
280  *
281  * Description      RFCOMM connection closed.
282  *
283  *
284  * Returns          void
285  *
286  ******************************************************************************/
bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA * p_data)287 void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA* p_data) {
288   tBTA_HF_CLIENT_CB* client_cb =
289       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
290   if (client_cb == NULL) {
291     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
292                      p_data->hdr.layer_specific);
293     return;
294   }
295 
296   bta_hf_client_at_reset(client_cb);
297 
298   bta_sys_conn_close(BTA_ID_HS, 1, client_cb->peer_addr);
299 
300   /* call close cback */
301   tBTA_HF_CLIENT evt;
302   memset(&evt, 0, sizeof(evt));
303   evt.conn.bd_addr = client_cb->peer_addr;
304 
305   /* if not deregistering reopen server */
306   if (bta_hf_client_cb_arr.deregister == false) {
307     /* Make sure SCO is shutdown */
308     bta_hf_client_sco_shutdown(client_cb);
309 
310     bta_sys_sco_unuse(BTA_ID_HS, 1, client_cb->peer_addr);
311   }
312   /* else close port and deallocate scb */
313   else {
314     tBTA_HF_CLIENT evt;
315     memset(&evt, 0, sizeof(evt));
316     evt.reg.bd_addr = client_cb->peer_addr;
317     bta_hf_client_app_callback(BTA_HF_CLIENT_DISABLE_EVT, &evt);
318   }
319 }
320 
321 /*******************************************************************************
322  *
323  * Function         bta_hf_client_disc_int_res
324  *
325  * Description      This function handles a discovery result when initiator.
326  *
327  *
328  * Returns          void
329  *
330  ******************************************************************************/
bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA * p_data)331 void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA* p_data) {
332   uint16_t event = BTA_HF_CLIENT_DISC_FAIL_EVT;
333 
334   APPL_TRACE_DEBUG("%s: Status: %d", __func__, p_data->disc_result.status);
335   tBTA_HF_CLIENT_CB* client_cb =
336       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
337   if (client_cb == NULL) {
338     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
339                      p_data->hdr.layer_specific);
340     return;
341   }
342 
343   /* if found service */
344   if (p_data->disc_result.status == SDP_SUCCESS ||
345       p_data->disc_result.status == SDP_DB_FULL) {
346     /* get attributes */
347     if (bta_hf_client_sdp_find_attr(client_cb)) {
348       event = BTA_HF_CLIENT_DISC_OK_EVT;
349     }
350   }
351 
352   /* free discovery db */
353   bta_hf_client_free_db(p_data);
354 
355   /* send ourselves sdp ok/fail event */
356   bta_hf_client_sm_execute(event, p_data);
357 }
358 
359 /*******************************************************************************
360  *
361  * Function         bta_hf_client_disc_acp_res
362  *
363  * Description      This function handles a discovery result when acceptor.
364  *
365  *
366  * Returns          void
367  *
368  ******************************************************************************/
bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA * p_data)369 void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA* p_data) {
370   tBTA_HF_CLIENT_CB* client_cb =
371       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
372   if (client_cb == NULL) {
373     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
374                      p_data->hdr.layer_specific);
375     return;
376   }
377 
378   /* if found service */
379   if (p_data->disc_result.status == SDP_SUCCESS ||
380       p_data->disc_result.status == SDP_DB_FULL) {
381     /* get attributes */
382     bta_hf_client_sdp_find_attr(client_cb);
383   }
384 
385   /* free discovery db */
386   bta_hf_client_free_db(p_data);
387 }
388 
389 /*******************************************************************************
390  *
391  * Function         bta_hf_client_rfc_data
392  *
393  * Description      Read and process data from RFCOMM.
394  *
395  *
396  * Returns          void
397  *
398  ******************************************************************************/
bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA * p_data)399 void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA* p_data) {
400   tBTA_HF_CLIENT_CB* client_cb =
401       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
402   if (client_cb == NULL) {
403     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
404                      p_data->hdr.layer_specific);
405     return;
406   }
407 
408   uint16_t len;
409   char buf[BTA_HF_CLIENT_RFC_READ_MAX];
410   memset(buf, 0, sizeof(buf));
411   /* read data from rfcomm; if bad status, we're done */
412   while (PORT_ReadData(client_cb->conn_handle, buf, BTA_HF_CLIENT_RFC_READ_MAX,
413                        &len) == PORT_SUCCESS) {
414     /* if no data, we're done */
415     if (len == 0) {
416       break;
417     }
418 
419     bta_hf_client_at_parse(client_cb, buf, len);
420 
421     /* no more data to read, we're done */
422     if (len < BTA_HF_CLIENT_RFC_READ_MAX) {
423       break;
424     }
425   }
426 }
427 
428 /*******************************************************************************
429  *
430  * Function         bta_hf_client_svc_conn_open
431  *
432  * Description      Service level connection opened
433  *
434  *
435  * Returns          void
436  *
437  ******************************************************************************/
bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA * p_data)438 void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA* p_data) {
439   APPL_TRACE_DEBUG("%s", __func__);
440   tBTA_HF_CLIENT_CB* client_cb =
441       bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
442   if (client_cb == NULL) {
443     APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
444                      p_data->hdr.layer_specific);
445     return;
446   }
447 
448   tBTA_HF_CLIENT evt;
449 
450   memset(&evt, 0, sizeof(evt));
451 
452   if (!client_cb->svc_conn) {
453     /* set state variable */
454     client_cb->svc_conn = true;
455 
456     /* call callback */
457     evt.conn.bd_addr = client_cb->peer_addr;
458     evt.conn.peer_feat = client_cb->peer_features;
459     evt.conn.chld_feat = client_cb->chld_features;
460 
461     bta_hf_client_app_callback(BTA_HF_CLIENT_CONN_EVT, &evt);
462   }
463 }
464