• 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 "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 
47 const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX] =
48 {
49     UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
50     UUID_SERVCLASS_AG_HANDSFREE
51 };
52 
53 const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX] =
54 {
55     BTM_SEC_SERVICE_HEADSET_AG,
56     BTM_SEC_SERVICE_AG_HANDSFREE
57 };
58 
59 const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] =
60 {
61     BTA_HSP_SERVICE_ID,
62     BTA_HFP_SERVICE_ID
63 };
64 
65 const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] =
66 {
67     BTA_HSP_SERVICE_MASK,
68     BTA_HFP_SERVICE_MASK
69 };
70 
71 typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
72                                     char *p_arg, INT16 int_arg);
73 
74 const 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 *******************************************************************************/
bta_ag_cback_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data,tBTA_AG_STATUS status)90 static 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 *******************************************************************************/
bta_ag_register(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)123 void 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 *******************************************************************************/
bta_ag_deregister(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)157 void 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 *******************************************************************************/
bta_ag_start_dereg(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)182 void 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 *******************************************************************************/
bta_ag_start_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)201 void 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 *******************************************************************************/
bta_ag_disc_int_res(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)243 void 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 *******************************************************************************/
bta_ag_disc_acp_res(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)311 void 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 *******************************************************************************/
bta_ag_disc_fail(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)335 void 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 *******************************************************************************/
bta_ag_open_fail(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)356 void 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 *******************************************************************************/
bta_ag_rfc_fail(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)372 void 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 *******************************************************************************/
bta_ag_rfc_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)403 void 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 *******************************************************************************/
bta_ag_rfc_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)496 void 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 *******************************************************************************/
bta_ag_rfc_acp_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)542 void 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 *******************************************************************************/
bta_ag_rfc_data(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)636 void 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 *******************************************************************************/
bta_ag_start_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)679 void 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 *******************************************************************************/
bta_ag_post_sco_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)710 void 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 *******************************************************************************/
bta_ag_post_sco_close(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)739 void 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 *******************************************************************************/
bta_ag_svc_conn_open(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)796 void 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 *******************************************************************************/
bta_ag_ci_rx_data(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)838 void 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 *******************************************************************************/
bta_ag_rcvd_slc_ready(tBTA_AG_SCB * p_scb,tBTA_AG_DATA * p_data)857 void 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