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