• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-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 is the implementation file for the MCAP at L2CAP Interface.
22  *
23  ******************************************************************************/
24 #include <string.h>
25 
26 #include "bt_target.h"
27 #include "btm_api.h"
28 #include "btm_int.h"
29 #include "mca_api.h"
30 #include "mca_defs.h"
31 #include "mca_int.h"
32 
33 
34 /* L2CAP callback function structure */
35 const tL2CAP_APPL_INFO mca_l2c_int_appl =
36 {
37     NULL,
38     mca_l2c_connect_cfm_cback,
39     NULL,
40     mca_l2c_config_ind_cback,
41     mca_l2c_config_cfm_cback,
42     mca_l2c_disconnect_ind_cback,
43     mca_l2c_disconnect_cfm_cback,
44     NULL,
45     mca_l2c_data_ind_cback,
46     mca_l2c_congestion_ind_cback,
47 	NULL
48 };
49 
50 /* Control channel eL2CAP default options */
51 const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def =
52 {
53     L2CAP_FCR_ERTM_MODE,            /* Mandatory for MCAP */
54     MCA_FCR_OPT_TX_WINDOW_SIZE,     /* Tx window size */
55     MCA_FCR_OPT_MAX_TX_B4_DISCNT,   /* Maximum transmissions before disconnecting */
56     MCA_FCR_OPT_RETX_TOUT,          /* Retransmission timeout (2 secs) */
57     MCA_FCR_OPT_MONITOR_TOUT,       /* Monitor timeout (12 secs) */
58     MCA_FCR_OPT_MPS_SIZE            /* MPS segment size */
59 };
60 
61 
62 /*******************************************************************************
63 **
64 ** Function         mca_sec_check_complete_term
65 **
66 ** Description      The function called when Security Manager finishes
67 **                  verification of the service side connection
68 **
69 ** Returns          void
70 **
71 *******************************************************************************/
mca_sec_check_complete_term(BD_ADDR bd_addr,void * p_ref_data,UINT8 res)72 static void mca_sec_check_complete_term (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
73 {
74     tMCA_TC_TBL     *p_tbl = (tMCA_TC_TBL *)p_ref_data;
75     tL2CAP_CFG_INFO cfg;
76     tL2CAP_ERTM_INFO ertm_info;
77 
78     MCA_TRACE_DEBUG1("mca_sec_check_complete_term res: %d", res);
79 
80     if ( res == BTM_SUCCESS )
81     {
82         MCA_TRACE_DEBUG2 ("lcid:x%x id:x%x", p_tbl->lcid, p_tbl->id);
83         /* Set the FCR options: control channel mandates ERTM */
84         ertm_info.preferred_mode    = mca_l2c_fcr_opts_def.mode;
85         ertm_info.allowed_modes     = L2CAP_FCR_CHAN_OPT_ERTM;
86         ertm_info.user_rx_pool_id   = MCA_USER_RX_POOL_ID;
87         ertm_info.user_tx_pool_id   = MCA_USER_TX_POOL_ID;
88         ertm_info.fcr_rx_pool_id    = MCA_FCR_RX_POOL_ID;
89         ertm_info.fcr_tx_pool_id    = MCA_FCR_TX_POOL_ID;
90         /* Send response to the L2CAP layer. */
91         L2CA_ErtmConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK, &ertm_info);
92 
93         /* transition to configuration state */
94         p_tbl->state = MCA_TC_ST_CFG;
95 
96         /* Send L2CAP config req */
97         mca_set_cfg_by_tbl (&cfg, p_tbl);
98         L2CA_ConfigReq(p_tbl->lcid, &cfg);
99     }
100     else
101     {
102         L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK, L2CAP_CONN_OK);
103         mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
104     }
105 }
106 
107 /*******************************************************************************
108 **
109 ** Function         mca_sec_check_complete_orig
110 **
111 ** Description      The function called when Security Manager finishes
112 **                  verification of the service side connection
113 **
114 ** Returns          void
115 **
116 *******************************************************************************/
mca_sec_check_complete_orig(BD_ADDR bd_addr,void * p_ref_data,UINT8 res)117 static void mca_sec_check_complete_orig (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
118 {
119     tMCA_TC_TBL     *p_tbl = (tMCA_TC_TBL *)p_ref_data;
120     tL2CAP_CFG_INFO cfg;
121 
122     MCA_TRACE_DEBUG1("mca_sec_check_complete_orig res: %d", res);
123 
124     if ( res == BTM_SUCCESS )
125     {
126         /* set channel state */
127         p_tbl->state = MCA_TC_ST_CFG;
128 
129         /* Send L2CAP config req */
130         mca_set_cfg_by_tbl (&cfg, p_tbl);
131         L2CA_ConfigReq(p_tbl->lcid, &cfg);
132     }
133     else
134     {
135         L2CA_DisconnectReq (p_tbl->lcid);
136         mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
137     }
138 }
139 /*******************************************************************************
140 **
141 ** Function         mca_l2c_cconn_ind_cback
142 **
143 ** Description      This is the L2CAP connect indication callback function.
144 **
145 ** Returns          void
146 **
147 *******************************************************************************/
mca_l2c_cconn_ind_cback(BD_ADDR bd_addr,UINT16 lcid,UINT16 psm,UINT8 id)148 void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
149 {
150     tMCA_HANDLE handle = mca_handle_by_cpsm(psm);
151     tMCA_CCB    *p_ccb;
152     tMCA_TC_TBL *p_tbl = NULL;
153     UINT16      result = L2CAP_CONN_NO_RESOURCES;
154     tBTM_STATUS rc;
155     tL2CAP_ERTM_INFO ertm_info, *p_ertm_info = NULL;
156     tL2CAP_CFG_INFO  cfg;
157 
158     MCA_TRACE_EVENT3 ("mca_l2c_cconn_ind_cback: lcid:x%x psm:x%x id:x%x", lcid, psm, id);
159 
160     /* do we already have a control channel for this peer? */
161     if ((p_ccb = mca_ccb_by_bd(handle, bd_addr)) == NULL)
162     {
163         /* no, allocate ccb */
164         if ((p_ccb = mca_ccb_alloc(handle, bd_addr)) != NULL)
165         {
166             /* allocate and set up entry */
167             p_ccb->lcid     = lcid;
168             p_tbl           = mca_tc_tbl_calloc(p_ccb);
169             p_tbl->id       = id;
170             p_tbl->cfg_flags= MCA_L2C_CFG_CONN_ACP;
171             /* proceed with connection */
172             /* Check the security */
173             rc = btm_sec_mx_access_request (bd_addr, psm, FALSE, BTM_SEC_PROTO_MCA, 0,
174                                             &mca_sec_check_complete_term, p_tbl);
175             if (rc == BTM_CMD_STARTED)
176             {
177                 /* Set the FCR options: control channel mandates ERTM */
178                 ertm_info.preferred_mode    = mca_l2c_fcr_opts_def.mode;
179                 ertm_info.allowed_modes     = L2CAP_FCR_CHAN_OPT_ERTM;
180                 ertm_info.user_rx_pool_id   = MCA_USER_RX_POOL_ID;
181                 ertm_info.user_tx_pool_id   = MCA_USER_TX_POOL_ID;
182                 ertm_info.fcr_rx_pool_id    = MCA_FCR_RX_POOL_ID;
183                 ertm_info.fcr_tx_pool_id    = MCA_FCR_TX_POOL_ID;
184                 p_ertm_info = &ertm_info;
185                 result = L2CAP_CONN_PENDING;
186             }
187             else
188                 result = L2CAP_CONN_OK;
189         }
190 
191         /*  deal with simultaneous control channel connect case */
192     }
193     /* else reject their connection */
194 
195     if (!p_tbl || (p_tbl->state != MCA_TC_ST_CFG))
196     {
197         /* Send L2CAP connect rsp */
198         L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info);
199 
200         /* if result ok, proceed with connection and send L2CAP
201            config req */
202         if (result == L2CAP_CONN_OK)
203         {
204             /* set channel state */
205             p_tbl->state = MCA_TC_ST_CFG;
206 
207             /* Send L2CAP config req */
208             mca_set_cfg_by_tbl (&cfg, p_tbl);
209             L2CA_ConfigReq(p_tbl->lcid, &cfg);
210         }
211     }
212 }
213 
214 /*******************************************************************************
215 **
216 ** Function         mca_l2c_dconn_ind_cback
217 **
218 ** Description      This is the L2CAP connect indication callback function.
219 **
220 **
221 ** Returns          void
222 **
223 *******************************************************************************/
mca_l2c_dconn_ind_cback(BD_ADDR bd_addr,UINT16 lcid,UINT16 psm,UINT8 id)224 void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id)
225 {
226     tMCA_HANDLE handle = mca_handle_by_dpsm(psm);
227     tMCA_CCB    *p_ccb;
228     tMCA_DCB       *p_dcb;
229     tMCA_TC_TBL    *p_tbl = NULL;
230     UINT16          result;
231     tL2CAP_CFG_INFO cfg;
232     tL2CAP_ERTM_INFO *p_ertm_info = NULL, ertm_info;
233     const tMCA_CHNL_CFG   *p_chnl_cfg;
234 
235     MCA_TRACE_EVENT2 ("mca_l2c_dconn_ind_cback: lcid:x%x psm:x%x ", lcid, psm);
236 
237     if (((p_ccb = mca_ccb_by_bd(handle, bd_addr)) != NULL) && /* find the CCB */
238         (p_ccb->status == MCA_CCB_STAT_PENDING) &&  /* this CCB is expecting a MDL */
239         (p_ccb->p_tx_req && (p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) != NULL))
240     {
241         /* found the associated dcb in listening mode */
242         /* proceed with connection */
243         p_dcb->lcid     = lcid;
244         p_tbl           = mca_tc_tbl_dalloc(p_dcb);
245         p_tbl->id       = id;
246         p_tbl->cfg_flags= MCA_L2C_CFG_CONN_ACP;
247         p_chnl_cfg = p_dcb->p_chnl_cfg;
248         /* assume that control channel has verified the security requirement */
249         /* Set the FCR options: control channel mandates ERTM */
250         ertm_info.preferred_mode    = p_chnl_cfg->fcr_opt.mode;
251         ertm_info.allowed_modes     = (1 << p_chnl_cfg->fcr_opt.mode);
252         ertm_info.user_rx_pool_id   = p_chnl_cfg->user_rx_pool_id;
253         ertm_info.user_tx_pool_id   = p_chnl_cfg->user_tx_pool_id;
254         ertm_info.fcr_rx_pool_id    = p_chnl_cfg->fcr_rx_pool_id;
255         ertm_info.fcr_tx_pool_id    = p_chnl_cfg->fcr_tx_pool_id;
256         p_ertm_info = &ertm_info;
257         result = L2CAP_CONN_OK;
258     }
259     else
260     {
261         /* else we're not listening for traffic channel; reject
262          * (this error code is specified by MCAP spec) */
263         result = L2CAP_CONN_NO_RESOURCES;
264     }
265 
266     /* Send L2CAP connect rsp */
267     L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, result, p_ertm_info);
268 
269     /* if result ok, proceed with connection */
270     if (result == L2CAP_CONN_OK)
271     {
272         /* transition to configuration state */
273         p_tbl->state = MCA_TC_ST_CFG;
274 
275         /* Send L2CAP config req */
276         mca_set_cfg_by_tbl (&cfg, p_tbl);
277         L2CA_ConfigReq(lcid, &cfg);
278     }
279 }
280 
281 /*******************************************************************************
282 **
283 ** Function         mca_l2c_connect_cfm_cback
284 **
285 ** Description      This is the L2CAP connect confirm callback function.
286 **
287 **
288 ** Returns          void
289 **
290 *******************************************************************************/
mca_l2c_connect_cfm_cback(UINT16 lcid,UINT16 result)291 void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result)
292 {
293     tMCA_TC_TBL    *p_tbl;
294     tL2CAP_CFG_INFO cfg;
295     tMCA_CCB *p_ccb;
296 
297     MCA_TRACE_DEBUG2("mca_l2c_connect_cfm_cback lcid: x%x, result: %d",
298                      lcid, result);
299     /* look up info for this channel */
300     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
301     {
302         MCA_TRACE_DEBUG2("p_tbl state: %d, tcid: %d", p_tbl->state, p_tbl->tcid);
303         /* if in correct state */
304         if (p_tbl->state == MCA_TC_ST_CONN)
305         {
306             /* if result successful */
307             if (result == L2CAP_CONN_OK)
308             {
309                 if (p_tbl->tcid != 0)
310                 {
311                     /* set channel state */
312                     p_tbl->state = MCA_TC_ST_CFG;
313 
314                     /* Send L2CAP config req */
315                     mca_set_cfg_by_tbl (&cfg, p_tbl);
316                     L2CA_ConfigReq(lcid, &cfg);
317                 }
318                 else
319                 {
320                     p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
321                     if (p_ccb == NULL)
322                     {
323                         result = L2CAP_CONN_NO_RESOURCES;
324                     }
325                     else
326                     {
327                         /* set channel state */
328                         p_tbl->state    = MCA_TC_ST_SEC_INT;
329                         p_tbl->lcid     = lcid;
330                         p_tbl->cfg_flags= MCA_L2C_CFG_CONN_INT;
331 
332                         /* Check the security */
333                         btm_sec_mx_access_request (p_ccb->peer_addr, p_ccb->ctrl_vpsm,
334                                                    TRUE, BTM_SEC_PROTO_MCA,
335                                                    p_tbl->tcid,
336                                                    &mca_sec_check_complete_orig, p_tbl);
337                     }
338                 }
339             }
340 
341             /* failure; notify adaption that channel closed */
342             if (result != L2CAP_CONN_OK)
343             {
344                 p_tbl->cfg_flags |= MCA_L2C_CFG_DISCN_INT;
345                 mca_tc_close_ind(p_tbl, result);
346             }
347         }
348     }
349 }
350 
351 /*******************************************************************************
352 **
353 ** Function         mca_l2c_config_cfm_cback
354 **
355 ** Description      This is the L2CAP config confirm callback function.
356 **
357 **
358 ** Returns          void
359 **
360 *******************************************************************************/
mca_l2c_config_cfm_cback(UINT16 lcid,tL2CAP_CFG_INFO * p_cfg)361 void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
362 {
363     tMCA_TC_TBL    *p_tbl;
364 
365     /* look up info for this channel */
366     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
367     {
368         /* if in correct state */
369         if (p_tbl->state == MCA_TC_ST_CFG)
370         {
371             /* if result successful */
372             if (p_cfg->result == L2CAP_CONN_OK)
373             {
374                 /* update cfg_flags */
375                 p_tbl->cfg_flags |= MCA_L2C_CFG_CFM_DONE;
376 
377                 /* if configuration complete */
378                 if (p_tbl->cfg_flags & MCA_L2C_CFG_IND_DONE)
379                 {
380                     mca_tc_open_ind(p_tbl);
381                 }
382             }
383             /* else failure */
384             else
385             {
386                 /* Send L2CAP disconnect req */
387                 L2CA_DisconnectReq(lcid);
388             }
389         }
390     }
391 }
392 
393 /*******************************************************************************
394 **
395 ** Function         mca_l2c_config_ind_cback
396 **
397 ** Description      This is the L2CAP config indication callback function.
398 **
399 **
400 ** Returns          void
401 **
402 *******************************************************************************/
mca_l2c_config_ind_cback(UINT16 lcid,tL2CAP_CFG_INFO * p_cfg)403 void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg)
404 {
405     tMCA_TC_TBL    *p_tbl;
406     UINT16          result = L2CAP_CFG_OK;
407 
408     /* look up info for this channel */
409     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
410     {
411         /* store the mtu in tbl */
412         if (p_cfg->mtu_present)
413         {
414             p_tbl->peer_mtu = p_cfg->mtu;
415             if (p_tbl->peer_mtu < MCA_MIN_MTU)
416             {
417                 result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
418             }
419         }
420         else
421         {
422             p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
423         }
424         MCA_TRACE_DEBUG3("peer_mtu: %d, lcid: x%x mtu_present:%d",p_tbl->peer_mtu, lcid, p_cfg->mtu_present);
425 
426         /* send L2CAP configure response */
427         memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
428         p_cfg->result = result;
429         L2CA_ConfigRsp(lcid, p_cfg);
430 
431         /* if first config ind */
432         if ((p_tbl->cfg_flags & MCA_L2C_CFG_IND_DONE) == 0)
433         {
434             /* update cfg_flags */
435             p_tbl->cfg_flags |= MCA_L2C_CFG_IND_DONE;
436 
437             /* if configuration complete */
438             if (p_tbl->cfg_flags & MCA_L2C_CFG_CFM_DONE)
439             {
440                 mca_tc_open_ind(p_tbl);
441             }
442         }
443     }
444 }
445 
446 /*******************************************************************************
447 **
448 ** Function         mca_l2c_disconnect_ind_cback
449 **
450 ** Description      This is the L2CAP disconnect indication callback function.
451 **
452 **
453 ** Returns          void
454 **
455 *******************************************************************************/
mca_l2c_disconnect_ind_cback(UINT16 lcid,BOOLEAN ack_needed)456 void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed)
457 {
458     tMCA_TC_TBL    *p_tbl;
459     UINT16         reason = L2CAP_DISC_TIMEOUT;
460 
461     MCA_TRACE_DEBUG2("mca_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d",
462                      lcid, ack_needed);
463     /* look up info for this channel */
464     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
465     {
466         if (ack_needed)
467         {
468             /* send L2CAP disconnect response */
469             L2CA_DisconnectRsp(lcid);
470         }
471 
472         p_tbl->cfg_flags = MCA_L2C_CFG_DISCN_ACP;
473         if (ack_needed)
474             reason = L2CAP_DISC_OK;
475         mca_tc_close_ind(p_tbl, reason);
476     }
477 }
478 
479 /*******************************************************************************
480 **
481 ** Function         mca_l2c_disconnect_cfm_cback
482 **
483 ** Description      This is the L2CAP disconnect confirm callback function.
484 **
485 **
486 ** Returns          void
487 **
488 *******************************************************************************/
mca_l2c_disconnect_cfm_cback(UINT16 lcid,UINT16 result)489 void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result)
490 {
491     tMCA_TC_TBL    *p_tbl;
492 
493     MCA_TRACE_DEBUG2("mca_l2c_disconnect_cfm_cback lcid: x%x, result: %d",
494                      lcid, result);
495     /* look up info for this channel */
496     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
497     {
498         p_tbl->cfg_flags = MCA_L2C_CFG_DISCN_INT;
499         mca_tc_close_ind(p_tbl, result);
500     }
501 }
502 
503 
504 /*******************************************************************************
505 **
506 ** Function         mca_l2c_congestion_ind_cback
507 **
508 ** Description      This is the L2CAP congestion indication callback function.
509 **
510 **
511 ** Returns          void
512 **
513 *******************************************************************************/
mca_l2c_congestion_ind_cback(UINT16 lcid,BOOLEAN is_congested)514 void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested)
515 {
516     tMCA_TC_TBL    *p_tbl;
517 
518     /* look up info for this channel */
519     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
520     {
521         mca_tc_cong_ind(p_tbl, is_congested);
522     }
523 }
524 
525 /*******************************************************************************
526 **
527 ** Function         mca_l2c_data_ind_cback
528 **
529 ** Description      This is the L2CAP data indication callback function.
530 **
531 **
532 ** Returns          void
533 **
534 *******************************************************************************/
mca_l2c_data_ind_cback(UINT16 lcid,BT_HDR * p_buf)535 void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf)
536 {
537     tMCA_TC_TBL    *p_tbl;
538 
539     /* look up info for this channel */
540     if ((p_tbl = mca_tc_tbl_by_lcid(lcid)) != NULL)
541     {
542         mca_tc_data_ind(p_tbl, p_buf);
543     }
544     else /* prevent buffer leak */
545         GKI_freebuf(p_buf);
546 }
547 
548 
549 /*******************************************************************************
550 **
551 ** Function         mca_l2c_open_req
552 **
553 ** Description      This function calls L2CA_ConnectReq() to initiate a L2CAP channel.
554 **
555 ** Returns          void.
556 **
557 *******************************************************************************/
mca_l2c_open_req(BD_ADDR bd_addr,UINT16 psm,const tMCA_CHNL_CFG * p_chnl_cfg)558 UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 psm, const tMCA_CHNL_CFG *p_chnl_cfg)
559 {
560     tL2CAP_ERTM_INFO ertm_info;
561 
562     if (p_chnl_cfg)
563     {
564         ertm_info.preferred_mode    = p_chnl_cfg->fcr_opt.mode;
565         ertm_info.allowed_modes     = (1 << p_chnl_cfg->fcr_opt.mode);
566         ertm_info.user_rx_pool_id   = p_chnl_cfg->user_rx_pool_id;
567         ertm_info.user_tx_pool_id   = p_chnl_cfg->user_tx_pool_id;
568         ertm_info.fcr_rx_pool_id    = p_chnl_cfg->fcr_rx_pool_id;
569         ertm_info.fcr_tx_pool_id    = p_chnl_cfg->fcr_tx_pool_id;
570     }
571     else
572     {
573         ertm_info.preferred_mode    = mca_l2c_fcr_opts_def.mode;
574         ertm_info.allowed_modes     = L2CAP_FCR_CHAN_OPT_ERTM;
575         ertm_info.user_rx_pool_id   = MCA_USER_RX_POOL_ID;
576         ertm_info.user_tx_pool_id   = MCA_USER_TX_POOL_ID;
577         ertm_info.fcr_rx_pool_id    = MCA_FCR_RX_POOL_ID;
578         ertm_info.fcr_tx_pool_id    = MCA_FCR_TX_POOL_ID;
579     }
580     return L2CA_ErtmConnectReq (psm, bd_addr, &ertm_info);
581 }
582 
583