• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2003-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  This file contains action functions for the audio gateway.
22  *
23  ******************************************************************************/
24 
25 #include <string.h>
26 
27 #include "bta_ag_api.h"
28 #include "bta_ag_co.h"
29 #include "bta_ag_int.h"
30 #include "bta_api.h"
31 #include "bta_dm_api.h"
32 #include "bta_sys.h"
33 #include "l2c_api.h"
34 #include "osi/include/osi.h"
35 #include "port_api.h"
36 #include "utl.h"
37 
38 /*****************************************************************************
39  *  Constants
40  ****************************************************************************/
41 
42 /* maximum length of data to read from RFCOMM */
43 #define BTA_AG_RFC_READ_MAX 512
44 
45 /* maximum AT command length */
46 #define BTA_AG_CMD_MAX 512
47 
48 const uint16_t bta_ag_uuid[BTA_AG_NUM_IDX] = {
49     UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, UUID_SERVCLASS_AG_HANDSFREE};
50 
51 const uint8_t bta_ag_sec_id[BTA_AG_NUM_IDX] = {BTM_SEC_SERVICE_HEADSET_AG,
52                                                BTM_SEC_SERVICE_AG_HANDSFREE};
53 
54 const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] = {BTA_HSP_SERVICE_ID,
55                                                        BTA_HFP_SERVICE_ID};
56 
57 const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] = {
58     BTA_HSP_SERVICE_MASK, BTA_HFP_SERVICE_MASK};
59 
60 typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB* p_scb, uint16_t cmd,
61                                     uint8_t arg_type, char* p_arg, char* p_end,
62                                     int16_t int_arg);
63 
64 const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] = {
65     bta_ag_at_hsp_cback, bta_ag_at_hfp_cback};
66 
67 /*******************************************************************************
68  *
69  * Function         bta_ag_cback_open
70  *
71  * Description      Send open callback event to application.
72  *
73  *
74  * Returns          void
75  *
76  ******************************************************************************/
bta_ag_cback_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data,tBTA_AG_STATUS status)77 static void bta_ag_cback_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data,
78                               tBTA_AG_STATUS status) {
79   tBTA_AG_OPEN open;
80 
81   /* call app callback with open event */
82   open.hdr.handle = bta_ag_scb_to_idx(p_scb);
83   open.hdr.app_id = p_scb->app_id;
84   open.status = status;
85   open.service_id = bta_ag_svc_id[p_scb->conn_service];
86   if (p_data) {
87     /* if p_data is provided then we need to pick the bd address from the open
88      * api structure */
89     open.bd_addr = p_data->api_open.bd_addr;
90   } else {
91     open.bd_addr = p_scb->peer_addr;
92   }
93 
94   (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG*)&open);
95 }
96 
97 /*******************************************************************************
98  *
99  * Function         bta_ag_register
100  *
101  * Description      This function initializes values of the AG cb and sets up
102  *                  the SDP record for the services.
103  *
104  *
105  * Returns          void
106  *
107  ******************************************************************************/
bta_ag_register(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)108 void bta_ag_register(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
109   tBTA_AG_REGISTER reg;
110 
111   /* initialize control block */
112   p_scb->reg_services = p_data->api_register.services;
113   p_scb->serv_sec_mask = p_data->api_register.sec_mask;
114   p_scb->features = p_data->api_register.features;
115   p_scb->app_id = p_data->api_register.app_id;
116 
117   /* create SDP records */
118   bta_ag_create_records(p_scb, p_data);
119 
120   /* start RFCOMM servers */
121   bta_ag_start_servers(p_scb, p_scb->reg_services);
122 
123   /* call app callback with register event */
124   reg.hdr.handle = bta_ag_scb_to_idx(p_scb);
125   reg.hdr.app_id = p_scb->app_id;
126   reg.status = BTA_AG_SUCCESS;
127   (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG*)&reg);
128 }
129 
130 /*******************************************************************************
131  *
132  * Function         bta_ag_deregister
133  *
134  * Description      This function removes the sdp records, closes the RFCOMM
135  *                  servers, and deallocates the service control block.
136  *
137  *
138  * Returns          void
139  *
140  ******************************************************************************/
bta_ag_deregister(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)141 void bta_ag_deregister(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
142   /* set dealloc */
143   p_scb->dealloc = true;
144 
145   /* remove sdp records */
146   bta_ag_del_records(p_scb, p_data);
147 
148   /* remove rfcomm servers */
149   bta_ag_close_servers(p_scb, p_scb->reg_services);
150 
151   /* dealloc */
152   bta_ag_scb_dealloc(p_scb);
153 }
154 
155 /*******************************************************************************
156  *
157  * Function         bta_ag_start_dereg
158  *
159  * Description      Start a deregister event.
160  *
161  *
162  * Returns          void
163  *
164  ******************************************************************************/
bta_ag_start_dereg(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)165 void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
166   /* set dealloc */
167   p_scb->dealloc = true;
168 
169   /* remove sdp records */
170   bta_ag_del_records(p_scb, p_data);
171 }
172 
173 /*******************************************************************************
174  *
175  * Function         bta_ag_start_open
176  *
177  * Description      This starts an AG open.
178  *
179  *
180  * Returns          void
181  *
182  ******************************************************************************/
bta_ag_start_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)183 void bta_ag_start_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
184   RawAddress pending_bd_addr;
185 
186   /* store parameters */
187   if (p_data) {
188     p_scb->peer_addr = p_data->api_open.bd_addr;
189     p_scb->open_services = p_data->api_open.services;
190     p_scb->cli_sec_mask = p_data->api_open.sec_mask;
191   }
192 
193   /* Check if RFCOMM has any incoming connection to avoid collision. */
194   if (PORT_IsOpening(pending_bd_addr)) {
195     /* Let the incoming connection goes through.                        */
196     /* Issue collision for this scb for now.                            */
197     /* We will decide what to do when we find incoming connetion later. */
198     bta_ag_collision_cback(0, BTA_ID_AG, 0, &p_scb->peer_addr);
199     return;
200   }
201 
202   /* close servers */
203   bta_ag_close_servers(p_scb, p_scb->reg_services);
204 
205   /* set role */
206   p_scb->role = BTA_AG_INT;
207 
208   /* do service search */
209   bta_ag_do_disc(p_scb, p_scb->open_services);
210 }
211 
212 /*******************************************************************************
213  *
214  * Function         bta_ag_disc_int_res
215  *
216  * Description      This function handles a discovery result when initiator.
217  *
218  *
219  * Returns          void
220  *
221  ******************************************************************************/
bta_ag_disc_int_res(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)222 void bta_ag_disc_int_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
223   uint16_t event = BTA_AG_DISC_FAIL_EVT;
224 
225   APPL_TRACE_DEBUG("bta_ag_disc_int_res: Status: %d",
226                    p_data->disc_result.status);
227 
228   /* if found service */
229   if (p_data->disc_result.status == SDP_SUCCESS ||
230       p_data->disc_result.status == SDP_DB_FULL) {
231     /* get attributes */
232     if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services)) {
233       /* set connected service */
234       p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services);
235 
236       /* send ourselves sdp ok event */
237       event = BTA_AG_DISC_OK_EVT;
238     }
239   }
240 
241   /* free discovery db */
242   bta_ag_free_db(p_scb, p_data);
243 
244   /* if service not found check if we should search for other service */
245   if ((event == BTA_AG_DISC_FAIL_EVT) &&
246       (p_data->disc_result.status == SDP_SUCCESS ||
247        p_data->disc_result.status == SDP_DB_FULL ||
248        p_data->disc_result.status == SDP_NO_RECS_MATCH)) {
249     if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) &&
250         (p_scb->open_services & BTA_HSP_SERVICE_MASK)) {
251       /* search for HSP */
252       p_scb->open_services &= ~BTA_HFP_SERVICE_MASK;
253       bta_ag_do_disc(p_scb, p_scb->open_services);
254     } else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) &&
255                (p_scb->hsp_version == HSP_VERSION_1_2)) {
256       /* search for UUID_SERVCLASS_HEADSET instead */
257       p_scb->hsp_version = HSP_VERSION_1_0;
258       bta_ag_do_disc(p_scb, p_scb->open_services);
259     } else {
260       /* send ourselves sdp ok/fail event */
261       bta_ag_sm_execute(p_scb, event, p_data);
262     }
263   } else {
264     /* send ourselves sdp ok/fail event */
265     bta_ag_sm_execute(p_scb, event, p_data);
266   }
267 }
268 
269 /*******************************************************************************
270  *
271  * Function         bta_ag_disc_acp_res
272  *
273  * Description      This function handles a discovery result when acceptor.
274  *
275  *
276  * Returns          void
277  *
278  ******************************************************************************/
bta_ag_disc_acp_res(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)279 void bta_ag_disc_acp_res(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
280   /* if found service */
281   if (p_data->disc_result.status == SDP_SUCCESS ||
282       p_data->disc_result.status == SDP_DB_FULL) {
283     /* get attributes */
284     bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
285   }
286 
287   /* free discovery db */
288   bta_ag_free_db(p_scb, p_data);
289 }
290 
291 /*******************************************************************************
292  *
293  * Function         bta_ag_disc_fail
294  *
295  * Description      This function handles a discovery failure.
296  *
297  *
298  * Returns          void
299  *
300  ******************************************************************************/
bta_ag_disc_fail(tBTA_AG_SCB * p_scb,UNUSED_ATTR tBTA_AG_DATA * p_data)301 void bta_ag_disc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
302   /* reopen registered servers */
303   bta_ag_start_servers(p_scb, p_scb->reg_services);
304 
305   /* reinitialize stuff */
306 
307   /* clear the remote BD address */
308   p_scb->peer_addr = RawAddress::kEmpty;
309 
310   /* call open cback w. failure */
311   bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
312 }
313 
314 /*******************************************************************************
315  *
316  * Function         bta_ag_open_fail
317  *
318  * Description      open connection failed.
319  *
320  *
321  * Returns          void
322  *
323  ******************************************************************************/
bta_ag_open_fail(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)324 void bta_ag_open_fail(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
325   /* call open cback w. failure */
326   bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES);
327 }
328 
329 /*******************************************************************************
330  *
331  * Function         bta_ag_rfc_fail
332  *
333  * Description      RFCOMM connection failed.
334  *
335  *
336  * Returns          void
337  *
338  ******************************************************************************/
bta_ag_rfc_fail(tBTA_AG_SCB * p_scb,UNUSED_ATTR tBTA_AG_DATA * p_data)339 void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
340   /* reinitialize stuff */
341   p_scb->conn_handle = 0;
342   p_scb->conn_service = 0;
343   p_scb->peer_features = 0;
344   p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
345   p_scb->sco_codec = BTA_AG_CODEC_CVSD;
346   p_scb->role = 0;
347   p_scb->svc_conn = false;
348   p_scb->hsp_version = HSP_VERSION_1_2;
349   /*Clear the BD address*/
350   p_scb->peer_addr = RawAddress::kEmpty;
351 
352   /* reopen registered servers */
353   bta_ag_start_servers(p_scb, p_scb->reg_services);
354 
355   /* call open cback w. failure */
356   bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM);
357 }
358 
359 /*******************************************************************************
360  *
361  * Function         bta_ag_rfc_close
362  *
363  * Description      RFCOMM connection closed.
364  *
365  *
366  * Returns          void
367  *
368  ******************************************************************************/
bta_ag_rfc_close(tBTA_AG_SCB * p_scb,UNUSED_ATTR tBTA_AG_DATA * p_data)369 void bta_ag_rfc_close(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
370   tBTA_AG_CLOSE close;
371   tBTA_SERVICE_MASK services;
372   int i, num_active_conn = 0;
373 
374   /* reinitialize stuff */
375   p_scb->conn_service = 0;
376   p_scb->peer_features = 0;
377   p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
378   p_scb->sco_codec = BTA_AG_CODEC_CVSD;
379   /* Clear these flags upon SLC teardown */
380   p_scb->codec_updated = false;
381   p_scb->codec_fallback = false;
382   p_scb->codec_msbc_settings = BTA_AG_SCO_MSBC_SETTINGS_T2;
383   p_scb->role = 0;
384   p_scb->post_sco = BTA_AG_POST_SCO_NONE;
385   p_scb->svc_conn = false;
386   p_scb->hsp_version = HSP_VERSION_1_2;
387   bta_ag_at_reinit(&p_scb->at_cb);
388 
389   memset(&(p_scb->peer_hf_indicators), 0, sizeof(p_scb->peer_hf_indicators));
390   memset(&(p_scb->local_hf_indicators), 0, sizeof(p_scb->local_hf_indicators));
391 
392   /* stop timers */
393   alarm_cancel(p_scb->ring_timer);
394   alarm_cancel(p_scb->codec_negotiation_timer);
395 
396   close.hdr.handle = bta_ag_scb_to_idx(p_scb);
397   close.hdr.app_id = p_scb->app_id;
398   close.bd_addr = p_scb->peer_addr;
399 
400   bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
401 
402   /* call close call-out */
403   bta_ag_co_data_close(close.hdr.handle);
404 
405   /* call close cback */
406   (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG*)&close);
407 
408   /* if not deregistering (deallocating) reopen registered servers */
409   if (p_scb->dealloc == false) {
410     /* Clear peer bd_addr so instance can be reused */
411     p_scb->peer_addr = RawAddress::kEmpty;
412 
413     /* start only unopened server */
414     services = p_scb->reg_services;
415     for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++) {
416       if (p_scb->serv_handle[i])
417         services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i));
418     }
419     bta_ag_start_servers(p_scb, services);
420 
421     p_scb->conn_handle = 0;
422 
423     /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */
424     bta_ag_sco_shutdown(p_scb, NULL);
425 
426     /* Check if all the SLCs are down */
427     for (i = 0; i < BTA_AG_NUM_SCB; i++) {
428       if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn)
429         num_active_conn++;
430     }
431 
432     if (!num_active_conn) {
433       bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
434     }
435 
436   }
437   /* else close port and deallocate scb */
438   else {
439     RFCOMM_RemoveServer(p_scb->conn_handle);
440     bta_ag_scb_dealloc(p_scb);
441   }
442 }
443 
444 /*******************************************************************************
445  *
446  * Function         bta_ag_rfc_open
447  *
448  * Description      Handle RFCOMM channel open.
449  *
450  *
451  * Returns          void
452  *
453  ******************************************************************************/
bta_ag_rfc_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)454 void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
455   /* initialize AT feature variables */
456   p_scb->clip_enabled = false;
457   p_scb->ccwa_enabled = false;
458   p_scb->cmer_enabled = false;
459   p_scb->cmee_enabled = false;
460   p_scb->inband_enabled =
461       ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND);
462 
463   /* set up AT command interpreter */
464   p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD*)bta_ag_at_tbl[p_scb->conn_service];
465   p_scb->at_cb.p_cmd_cback =
466       (tBTA_AG_AT_CMD_CBACK*)bta_ag_at_cback_tbl[p_scb->conn_service];
467   p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK*)bta_ag_at_err_cback;
468   p_scb->at_cb.p_user = p_scb;
469   p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX;
470   bta_ag_at_init(&p_scb->at_cb);
471 
472   /* call app open call-out */
473   bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb),
474                       bta_ag_svc_id[p_scb->conn_service]);
475 
476   bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
477 
478   bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
479 
480   if (p_scb->conn_service == BTA_AG_HFP) {
481     /* if hfp start timer for service level conn */
482     bta_sys_start_timer(p_scb->ring_timer, p_bta_ag_cfg->conn_tout,
483                         BTA_AG_SVC_TIMEOUT_EVT, bta_ag_scb_to_idx(p_scb));
484   } else {
485     /* else service level conn is open */
486     bta_ag_svc_conn_open(p_scb, p_data);
487   }
488 }
489 
490 /*******************************************************************************
491  *
492  * Function         bta_ag_rfc_acp_open
493  *
494  * Description      Handle RFCOMM channel open when accepting connection.
495  *
496  *
497  * Returns          void
498  *
499  ******************************************************************************/
bta_ag_rfc_acp_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)500 void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
501   uint16_t lcid;
502   int i;
503   tBTA_AG_SCB *ag_scb, *other_scb;
504   RawAddress dev_addr;
505   int status;
506 
507   /* set role */
508   p_scb->role = BTA_AG_ACP;
509 
510   APPL_TRACE_DEBUG("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
511                    p_scb->serv_handle[0], p_scb->serv_handle[1]);
512 
513   /* get bd addr of peer */
514   if (PORT_SUCCESS != (status = PORT_CheckConnection(p_data->rfc.port_handle,
515                                                      dev_addr, &lcid))) {
516     APPL_TRACE_DEBUG(
517         "bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d",
518         status);
519   }
520 
521   /* Collision Handling */
522   for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) {
523     if (ag_scb->in_use && alarm_is_scheduled(ag_scb->collision_timer)) {
524       alarm_cancel(ag_scb->collision_timer);
525 
526       if (dev_addr == ag_scb->peer_addr) {
527         /* If incoming and outgoing device are same, nothing more to do. */
528         /* Outgoing conn will be aborted because we have successful incoming
529          * conn.  */
530       } else {
531         /* Resume outgoing connection. */
532         other_scb = bta_ag_get_other_idle_scb(p_scb);
533         if (other_scb) {
534           other_scb->peer_addr = ag_scb->peer_addr;
535           other_scb->open_services = ag_scb->open_services;
536           other_scb->cli_sec_mask = ag_scb->cli_sec_mask;
537 
538           bta_ag_resume_open(other_scb);
539         }
540       }
541 
542       break;
543     }
544   }
545 
546   p_scb->peer_addr = dev_addr;
547 
548   /* determine connected service from port handle */
549   for (i = 0; i < BTA_AG_NUM_IDX; i++) {
550     APPL_TRACE_DEBUG(
551         "bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", i,
552         p_scb->serv_handle[i], p_data->rfc.port_handle);
553 
554     if (p_scb->serv_handle[i] == p_data->rfc.port_handle) {
555       p_scb->conn_service = i;
556       p_scb->conn_handle = p_data->rfc.port_handle;
557       break;
558     }
559   }
560 
561   APPL_TRACE_DEBUG("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
562                    p_scb->conn_service, p_scb->conn_handle);
563 
564   /* close any unopened server */
565   bta_ag_close_servers(
566       p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service]));
567 
568   /* do service discovery to get features */
569   bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
570 
571   /* continue with common open processing */
572   bta_ag_rfc_open(p_scb, p_data);
573 }
574 
575 /*******************************************************************************
576  *
577  * Function         bta_ag_rfc_data
578  *
579  * Description      Read and process data from RFCOMM.
580  *
581  *
582  * Returns          void
583  *
584  ******************************************************************************/
bta_ag_rfc_data(tBTA_AG_SCB * p_scb,UNUSED_ATTR tBTA_AG_DATA * p_data)585 void bta_ag_rfc_data(tBTA_AG_SCB* p_scb, UNUSED_ATTR tBTA_AG_DATA* p_data) {
586   uint16_t len;
587   char buf[BTA_AG_RFC_READ_MAX];
588 
589   memset(buf, 0, BTA_AG_RFC_READ_MAX);
590 
591   APPL_TRACE_DEBUG("%s", __func__);
592 
593   /* do the following */
594   for (;;) {
595     /* read data from rfcomm; if bad status, we're done */
596     if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) !=
597         PORT_SUCCESS) {
598       break;
599     }
600 
601     /* if no data, we're done */
602     if (len == 0) {
603       break;
604     }
605 
606     /* run AT command interpreter on data */
607     bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
608     bta_ag_at_parse(&p_scb->at_cb, buf, len);
609     if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) &&
610         bta_ag_sco_is_open(p_scb)) {
611       APPL_TRACE_DEBUG("%s change link policy for SCO", __func__);
612       bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
613     } else {
614       bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
615     }
616 
617     /* no more data to read, we're done */
618     if (len < BTA_AG_RFC_READ_MAX) {
619       break;
620     }
621   }
622 }
623 
624 /*******************************************************************************
625  *
626  * Function         bta_ag_start_close
627  *
628  * Description      Start the process of closing SCO and RFCOMM connection.
629  *
630  *
631  * Returns          void
632  *
633  ******************************************************************************/
bta_ag_start_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)634 void bta_ag_start_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
635   /* Take the link out of sniff and set L2C idle time to 0 */
636   bta_dm_pm_active(p_scb->peer_addr);
637   L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0, BT_TRANSPORT_BR_EDR);
638 
639   /* if SCO is open close SCO and wait on RFCOMM close */
640   if (bta_ag_sco_is_open(p_scb)) {
641     p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC;
642   } else {
643     p_scb->post_sco = BTA_AG_POST_SCO_NONE;
644     bta_ag_rfc_do_close(p_scb, p_data);
645   }
646 
647   /* always do SCO shutdown to handle all SCO corner cases */
648   bta_ag_sco_shutdown(p_scb, p_data);
649 }
650 
651 /*******************************************************************************
652  *
653  * Function         bta_ag_post_sco_open
654  *
655  * Description      Perform post-SCO open action, if any
656  *
657  *
658  * Returns          void
659  *
660  ******************************************************************************/
bta_ag_post_sco_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)661 void bta_ag_post_sco_open(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
662   switch (p_scb->post_sco) {
663     case BTA_AG_POST_SCO_RING:
664       bta_ag_send_ring(p_scb, p_data);
665       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
666       break;
667 
668     case BTA_AG_POST_SCO_CALL_CONN:
669       bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
670       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
671       break;
672 
673     default:
674       break;
675   }
676 }
677 
678 /*******************************************************************************
679  *
680  * Function         bta_ag_post_sco_close
681  *
682  * Description      Perform post-SCO close action, if any
683  *
684  *
685  * Returns          void
686  *
687  ******************************************************************************/
bta_ag_post_sco_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)688 void bta_ag_post_sco_close(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
689   switch (p_scb->post_sco) {
690     case BTA_AG_POST_SCO_CLOSE_RFC:
691       bta_ag_rfc_do_close(p_scb, p_data);
692       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
693       break;
694 
695     case BTA_AG_POST_SCO_CALL_CONN:
696       bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
697       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
698       break;
699 
700     case BTA_AG_POST_SCO_CALL_ORIG:
701       bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES);
702       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
703       break;
704 
705     case BTA_AG_POST_SCO_CALL_END:
706       bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
707       p_scb->post_sco = BTA_AG_POST_SCO_NONE;
708       break;
709 
710     case BTA_AG_POST_SCO_CALL_END_INCALL:
711       bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
712 
713       /* Sending callsetup IND and Ring were defered to after SCO close. */
714       bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES);
715 
716       if (bta_ag_inband_enabled(p_scb) &&
717           !(p_scb->features & BTA_AG_FEAT_NOSCO)) {
718         p_scb->post_sco = BTA_AG_POST_SCO_RING;
719         bta_ag_sco_open(p_scb, p_data);
720       } else {
721         p_scb->post_sco = BTA_AG_POST_SCO_NONE;
722         bta_ag_send_ring(p_scb, p_data);
723       }
724       break;
725 
726     default:
727       break;
728   }
729 }
730 
731 /*******************************************************************************
732  *
733  * Function         bta_ag_svc_conn_open
734  *
735  * Description      Service level connection opened
736  *
737  *
738  * Returns          void
739  *
740  ******************************************************************************/
bta_ag_svc_conn_open(tBTA_AG_SCB * p_scb,UNUSED_ATTR tBTA_AG_DATA * p_data)741 void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb,
742                           UNUSED_ATTR tBTA_AG_DATA* p_data) {
743   tBTA_AG_CONN evt;
744 
745   if (!p_scb->svc_conn) {
746     /* set state variable */
747     p_scb->svc_conn = true;
748 
749     /* Clear AT+BIA mask from previous SLC if any. */
750     p_scb->bia_masked_out = 0;
751 
752     alarm_cancel(p_scb->ring_timer);
753 
754     /* call callback */
755     evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
756     evt.hdr.app_id = p_scb->app_id;
757     evt.peer_feat = p_scb->peer_features;
758     evt.bd_addr = p_scb->peer_addr;
759     evt.peer_codec = p_scb->peer_codecs;
760 
761     if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) ||
762         (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE)) {
763       bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
764     }
765 
766     (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG*)&evt);
767   }
768 }
769 
770 /*******************************************************************************
771  *
772  * Function         bta_ag_ci_rx_data
773  *
774  * Description      Send result code
775  *
776  * Returns          void
777  *
778  ******************************************************************************/
bta_ag_ci_rx_data(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)779 void bta_ag_ci_rx_data(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
780   uint16_t len;
781   tBTA_AG_CI_RX_WRITE* p_rx_write_msg = (tBTA_AG_CI_RX_WRITE*)p_data;
782   char* p_data_area =
783       (char*)(p_rx_write_msg + 1); /* Point to data area after header */
784 
785   APPL_TRACE_DEBUG("bta_ag_ci_rx_data:");
786   /* send to RFCOMM */
787   bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
788   PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
789   if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) && bta_ag_sco_is_open(p_scb)) {
790     APPL_TRACE_DEBUG("bta_ag_rfc_data, change link policy for SCO");
791     bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
792   } else {
793     bta_sys_idle(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
794   }
795 }
796 
797 /*******************************************************************************
798  *
799  * Function         bta_ag_rcvd_slc_ready
800  *
801  * Description      Handles SLC ready call-in in case of pass-through mode.
802  *
803  * Returns          void
804  *
805  ******************************************************************************/
bta_ag_rcvd_slc_ready(tBTA_AG_SCB * p_scb,UNUSED_ATTR tBTA_AG_DATA * p_data)806 void bta_ag_rcvd_slc_ready(tBTA_AG_SCB* p_scb,
807                            UNUSED_ATTR tBTA_AG_DATA* p_data) {
808   APPL_TRACE_DEBUG("bta_ag_rcvd_slc_ready: handle = %d",
809                    bta_ag_scb_to_idx(p_scb));
810 
811   if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH) {
812     /* In pass-through mode, BTA knows that SLC is ready only through call-in.
813      */
814     bta_ag_svc_conn_open(p_scb, NULL);
815   }
816 }
817 
818 /*******************************************************************************
819  *
820  * Function         bta_ag_setcodec
821  *
822  * Description      Handle API SetCodec
823  *
824  *
825  * Returns          void
826  *
827  ******************************************************************************/
bta_ag_setcodec(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)828 void bta_ag_setcodec(tBTA_AG_SCB* p_scb, tBTA_AG_DATA* p_data) {
829   tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
830   tBTA_AG_VAL val;
831 
832   /* Check if the requested codec type is valid */
833   if ((codec_type != BTA_AG_CODEC_NONE) && (codec_type != BTA_AG_CODEC_CVSD) &&
834       (codec_type != BTA_AG_CODEC_MSBC)) {
835     val.num = codec_type;
836     val.hdr.status = BTA_AG_FAIL_RESOURCES;
837     APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d",
838                      codec_type);
839     (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
840     return;
841   }
842 
843   if ((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) ||
844       (codec_type == BTA_AG_CODEC_CVSD)) {
845     p_scb->sco_codec = codec_type;
846     p_scb->codec_updated = true;
847     val.num = codec_type;
848     val.hdr.status = BTA_AG_SUCCESS;
849     APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type);
850   } else {
851     val.num = codec_type;
852     val.hdr.status = BTA_AG_FAIL_RESOURCES;
853     APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d",
854                      codec_type);
855   }
856 
857   (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
858 }
859