OSDN Git Service

Merge "Add checks whether the AVDTP element data length is valid" into oc-dev am...
[android-x86/system-bt.git] / stack / avct / avct_bcb_act.cc
1 /******************************************************************************
2  *
3  *  Copyright 2003-2016 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  *  Name:           avct_bcb_act.cc
22  *
23  *  Description:    This module contains action functions of the browsing
24  *                  control state machine.
25  *
26  *****************************************************************************/
27
28 #include <string.h>
29 #include "avct_api.h"
30 #include "avct_int.h"
31 #include "bt_target.h"
32 #include "bt_utils.h"
33 #include "btm_api.h"
34 #include "osi/include/osi.h"
35
36 /* action function list */
37 const tAVCT_BCB_ACTION avct_bcb_action[] = {
38     avct_bcb_chnl_open,   /* AVCT_LCB_CHNL_OPEN */
39     avct_bcb_chnl_disc,   /* AVCT_LCB_CHNL_DISC */
40     avct_bcb_send_msg,    /* AVCT_LCB_SEND_MSG */
41     avct_bcb_open_ind,    /* AVCT_LCB_OPEN_IND */
42     avct_bcb_open_fail,   /* AVCT_LCB_OPEN_FAIL */
43     avct_bcb_close_ind,   /* AVCT_LCB_CLOSE_IND */
44     avct_bcb_close_cfm,   /* AVCT_LCB_CLOSE_CFM */
45     avct_bcb_msg_ind,     /* AVCT_LCB_MSG_IND */
46     avct_bcb_cong_ind,    /* AVCT_LCB_CONG_IND */
47     avct_bcb_bind_conn,   /* AVCT_LCB_BIND_CONN */
48     avct_bcb_bind_fail,   /* AVCT_LCB_BIND_FAIL */
49     avct_bcb_unbind_disc, /* AVCT_LCB_UNBIND_DISC */
50     avct_bcb_chk_disc,    /* AVCT_LCB_CHK_DISC */
51     avct_bcb_discard_msg, /* AVCT_LCB_DISCARD_MSG */
52     avct_bcb_dealloc,     /* AVCT_LCB_DEALLOC */
53     avct_bcb_free_msg_ind /* AVCT_LCB_FREE_MSG_IND */
54 };
55
56 /*******************************************************************************
57  *
58  * Function         avct_bcb_msg_asmbl
59  *
60  * Description      Reassemble incoming message.
61  *
62  *
63  * Returns          Pointer to reassembled message;  NULL if no message
64  *                  available.
65  *
66  ******************************************************************************/
67 static BT_HDR* avct_bcb_msg_asmbl(UNUSED_ATTR tAVCT_BCB* p_bcb, BT_HDR* p_buf) {
68   uint8_t* p;
69   uint8_t pkt_type;
70
71   /* parse the message header */
72   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
73   pkt_type = AVCT_PKT_TYPE(p);
74
75   /* must be single packet - can not fragment */
76   if (pkt_type != AVCT_PKT_TYPE_SINGLE) {
77     osi_free_and_reset((void**)&p_buf);
78     AVCT_TRACE_WARNING("Pkt type=%d - fragmentation not allowed. drop it",
79                        pkt_type);
80   }
81   return p_buf;
82 }
83
84 /*******************************************************************************
85  *
86  * Function         avct_bcb_chnl_open
87  *
88  * Description      Open L2CAP channel to peer
89  *
90  *
91  * Returns          Nothing.
92  *
93  ******************************************************************************/
94 void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
95   uint16_t result = AVCT_RESULT_FAIL;
96   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
97   tL2CAP_ERTM_INFO ertm_info;
98
99   BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP_BROWSE, 0);
100
101   /* Set the FCR options: Browsing channel mandates ERTM */
102   ertm_info.preferred_mode = avct_l2c_br_fcr_opts_def.mode;
103   ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
104   ertm_info.user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
105   ertm_info.user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
106   ertm_info.fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE;
107   ertm_info.fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE;
108
109   /* call l2cap connect req */
110   p_bcb->ch_state = AVCT_CH_CONN;
111   p_bcb->ch_lcid =
112       L2CA_ErtmConnectReq(AVCT_BR_PSM, p_lcb->peer_addr, &ertm_info);
113   if (p_bcb->ch_lcid == 0) {
114     /* if connect req failed, send ourselves close event */
115     tAVCT_LCB_EVT avct_lcb_evt;
116     avct_lcb_evt.result = result;
117     avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);
118   }
119 }
120
121 /*******************************************************************************
122  *
123  * Function         avct_bcb_unbind_disc
124  *
125  * Description      call callback with disconnect event.
126  *
127  *
128  * Returns          Nothing.
129  *
130  ******************************************************************************/
131 void avct_bcb_unbind_disc(UNUSED_ATTR tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
132   p_data->p_ccb->p_bcb = NULL;
133   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
134                                     AVCT_BROWSE_DISCONN_CFM_EVT, 0, NULL);
135 }
136
137 /*******************************************************************************
138  *
139  * Function         avct_bcb_open_ind
140  *
141  * Description      Handle an LL_OPEN event.
142  *                  For the allocated ccb already bound to the bcb, send a
143  *                  connect event. For the unbound ccb with a new PID, bind that
144  *                  ccb to the bcb with the same bd_addr and send a connect
145  *                  event.
146  *
147  *
148  * Returns          Nothing.
149  *
150  ******************************************************************************/
151 void avct_bcb_open_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
152   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
153   tAVCT_CCB* p_ccb_bind = NULL;
154   bool bind = false;
155   tAVCT_UL_MSG ul_msg;
156
157   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
158     /* if ccb allocated and */
159     if (p_ccb->allocated) {
160       /* if bound to this bcb send connect confirm event */
161       if (p_ccb->p_bcb == p_bcb) {
162         bind = true;
163         p_ccb_bind = p_ccb;
164         p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_CFM_EVT,
165                                0, &p_ccb->p_lcb->peer_addr);
166       }
167       /* if unbound acceptor and lcb allocated and bd_addr are the same for bcb
168          and lcb */
169       else if ((p_ccb->p_bcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
170                (p_ccb->p_lcb != NULL) &&
171                p_bcb->peer_addr == p_ccb->p_lcb->peer_addr) {
172         /* bind bcb to ccb and send connect ind event */
173         bind = true;
174         p_ccb_bind = p_ccb;
175         p_ccb->p_bcb = p_bcb;
176         p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_BROWSE_CONN_IND_EVT,
177                                0, &p_ccb->p_lcb->peer_addr);
178       }
179     }
180   }
181
182   /* if no ccbs bound to this lcb, disconnect */
183   if (!bind) {
184     avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
185     return;
186   }
187
188   if (!p_bcb->p_tx_msg || !p_ccb_bind) {
189     return;
190   }
191
192   ul_msg.p_buf = p_bcb->p_tx_msg;
193   ul_msg.p_ccb = p_ccb_bind;
194   ul_msg.label = (uint8_t)(p_bcb->p_tx_msg->layer_specific & 0xFF);
195   ul_msg.cr = (uint8_t)((p_bcb->p_tx_msg->layer_specific & 0xFF00) >> 8);
196   p_bcb->p_tx_msg->layer_specific = AVCT_DATA_BROWSE;
197   p_bcb->p_tx_msg = NULL;
198
199   /* send msg event to bcb */
200   tAVCT_LCB_EVT avct_lcb_evt;
201   avct_lcb_evt.ul_msg = ul_msg;
202   avct_bcb_event(p_bcb, AVCT_LCB_UL_MSG_EVT, &avct_lcb_evt);
203 }
204
205 /*******************************************************************************
206  *
207  * Function         avct_bcb_open_fail
208  *
209  * Description      L2CAP channel open attempt failed.  Mark the ccbs
210  *                  as NULL bcb.
211  *
212  *
213  * Returns          Nothing.
214  *
215  ******************************************************************************/
216 void avct_bcb_open_fail(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
217   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
218
219   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
220     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
221       p_ccb->p_bcb = NULL;
222     }
223   }
224 }
225
226 /*******************************************************************************
227  *
228  * Function         avct_bcb_close_ind
229  *
230  * Description      L2CAP channel closed by peer.  Deallocate any initiator
231  *                  ccbs on this lcb and send disconnect ind event.
232  *
233  *
234  * Returns          Nothing.
235  *
236  ******************************************************************************/
237 void avct_bcb_close_ind(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
238   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
239   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
240
241   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
242     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
243       if (p_ccb->cc.role == AVCT_INT) {
244         (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb),
245                                   AVCT_BROWSE_DISCONN_CFM_EVT, 0,
246                                   &p_lcb->peer_addr);
247       } else {
248         (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb),
249                                   AVCT_BROWSE_DISCONN_IND_EVT, 0, NULL);
250       }
251       p_ccb->p_bcb = NULL;
252     }
253   }
254 }
255
256 /*******************************************************************************
257  *
258  * Function         avct_bcb_close_cfm
259  *
260  * Description      L2CAP channel closed by us.  Deallocate any initiator
261  *                  ccbs on this lcb and send disconnect ind or cfm event.
262  *
263  *
264  * Returns          Nothing.
265  *
266  ******************************************************************************/
267 void avct_bcb_close_cfm(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
268   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
269   uint8_t event = 0;
270   /* Whether BCB initiated channel close */
271   bool ch_close = p_bcb->ch_close;
272   tAVCT_CTRL_CBACK* p_cback;
273
274   p_bcb->ch_close = false;
275   p_bcb->allocated = 0;
276   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
277     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
278       /* if this ccb initiated close send disconnect cfm otherwise ind */
279       if (ch_close) {
280         event = AVCT_BROWSE_DISCONN_CFM_EVT;
281       } else {
282         event = AVCT_BROWSE_DISCONN_IND_EVT;
283       }
284
285       p_cback = p_ccb->cc.p_ctrl_cback;
286       p_ccb->p_bcb = NULL;
287       if (p_ccb->p_lcb == NULL) avct_ccb_dealloc(p_ccb, AVCT_NO_EVT, 0, NULL);
288       (*p_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result,
289                  &p_bcb->peer_addr);
290     }
291   }
292 }
293
294 /*******************************************************************************
295  *
296  * Function         avct_bcb_bind_conn
297  *
298  * Description      Bind ccb to lcb and send connect cfm event.
299  *
300  *
301  * Returns          Nothing.
302  *
303  ******************************************************************************/
304 void avct_bcb_bind_conn(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
305   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
306   p_data->p_ccb->p_bcb = p_bcb;
307   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
308                                     AVCT_BROWSE_CONN_CFM_EVT, 0,
309                                     &p_lcb->peer_addr);
310 }
311
312 /*******************************************************************************
313  *
314  * Function         avct_bcb_chk_disc
315  *
316  * Description      A ccb wants to close; if it is the last ccb on this lcb,
317  *                  close channel.  Otherwise just deallocate and call
318  *                  callback.
319  *
320  *
321  * Returns          Nothing.
322  *
323  ******************************************************************************/
324 void avct_bcb_chk_disc(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
325   p_bcb->ch_close = avct_bcb_get_last_ccb_index(p_bcb, p_data->p_ccb);
326   if (p_bcb->ch_close) {
327     avct_bcb_event(p_bcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
328     return;
329   }
330
331   avct_bcb_unbind_disc(p_bcb, p_data);
332 }
333
334 /*******************************************************************************
335  *
336  * Function         avct_bcb_chnl_disc
337  *
338  * Description      Disconnect L2CAP channel.
339  *
340  *
341  * Returns          Nothing.
342  *
343  ******************************************************************************/
344 void avct_bcb_chnl_disc(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
345   L2CA_DisconnectReq(p_bcb->ch_lcid);
346 }
347
348 /*******************************************************************************
349  *
350  * Function         avct_bcb_bind_fail
351  *
352  * Description      Deallocate ccb and call callback with connect event
353  *                  with failure result.
354  *
355  *
356  * Returns          Nothing.
357  *
358  ******************************************************************************/
359 void avct_bcb_bind_fail(UNUSED_ATTR tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
360   p_data->p_ccb->p_bcb = NULL;
361   (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
362                                     AVCT_BROWSE_CONN_CFM_EVT, AVCT_RESULT_FAIL,
363                                     NULL);
364 }
365
366 /*******************************************************************************
367  *
368  * Function         avct_bcb_cong_ind
369  *
370  * Description      Handle congestion indication from L2CAP.
371  *
372  *
373  * Returns          Nothing.
374  *
375  ******************************************************************************/
376 void avct_bcb_cong_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
377   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
378   uint8_t event;
379   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
380
381   /* set event */
382   event =
383       (p_data->cong) ? AVCT_BROWSE_CONG_IND_EVT : AVCT_BROWSE_UNCONG_IND_EVT;
384
385   /* send event to all ccbs on this lcb */
386   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
387     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
388       (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0,
389                                 &p_lcb->peer_addr);
390     }
391   }
392 }
393
394 /*******************************************************************************
395  *
396  * Function         avct_bcb_discard_msg
397  *
398  * Description      Discard a message sent in from the API.
399  *
400  *
401  * Returns          Nothing.
402  *
403  ******************************************************************************/
404 void avct_bcb_discard_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
405   osi_free_and_reset((void**)&p_bcb->p_tx_msg);
406
407   /* if control channel is up, save the message and open the browsing channel */
408   if (p_data->ul_msg.p_ccb->p_lcb == NULL) {
409     osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
410     return;
411   }
412   p_bcb->p_tx_msg = p_data->ul_msg.p_buf;
413
414   if (p_bcb->p_tx_msg) {
415     p_bcb->p_tx_msg->layer_specific =
416         (p_data->ul_msg.cr << 8) + p_data->ul_msg.label;
417
418     /* the channel is closed, opening or closing - open it again */
419     AVCT_TRACE_DEBUG("ch_state: %d, allocated:%d->%d", p_bcb->ch_state,
420                      p_bcb->allocated, p_data->ul_msg.p_ccb->p_lcb->allocated);
421     p_bcb->allocated = p_data->ul_msg.p_ccb->p_lcb->allocated;
422     avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT,
423                    (tAVCT_LCB_EVT*)p_data->ul_msg.p_ccb);
424   }
425 }
426
427 /*******************************************************************************
428  *
429  * Function         avct_bcb_send_msg
430  *
431  * Description      Build and send an AVCTP message.
432  *
433  *
434  * Returns          Nothing.
435  *
436  ******************************************************************************/
437 void avct_bcb_send_msg(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
438   uint16_t curr_msg_len;
439   uint8_t pkt_type = AVCT_PKT_TYPE_SINGLE;
440   uint8_t hdr_len;
441   BT_HDR* p_buf;
442   uint8_t* p;
443
444   /* store msg len */
445   curr_msg_len = p_data->ul_msg.p_buf->len;
446
447   /* initialize packet type and other stuff */
448   if (curr_msg_len > (p_bcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) {
449     AVCT_TRACE_ERROR("%s msg len (%d) exceeds peer mtu(%d-%d)!!", __func__,
450                      curr_msg_len, p_bcb->peer_mtu, AVCT_HDR_LEN_SINGLE);
451     osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
452     return;
453   }
454
455   /* set header len */
456   hdr_len = avct_lcb_pkt_type_len[pkt_type];
457   p_buf = p_data->ul_msg.p_buf;
458
459   /* set up to build header */
460   p_buf->len += hdr_len;
461   p_buf->offset -= hdr_len;
462   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
463
464   /* build header */
465   AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
466   UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
467
468   p_buf->layer_specific = AVCT_DATA_BROWSE;
469
470   /* send message to L2CAP */
471   L2CA_DataWrite(p_bcb->ch_lcid, p_buf);
472 }
473
474 /*******************************************************************************
475  *
476  * Function         avct_bcb_free_msg_ind
477  *
478  * Description      Discard an incoming AVCTP message.
479  *
480  *
481  * Returns          Nothing.
482  *
483  ******************************************************************************/
484 void avct_bcb_free_msg_ind(UNUSED_ATTR tAVCT_BCB* p_bcb,
485                            tAVCT_LCB_EVT* p_data) {
486   if (p_data) osi_free_and_reset((void**)&p_data->p_buf);
487 }
488
489 /*******************************************************************************
490  *
491  * Function         avct_bcb_msg_ind
492  *
493  * Description      Handle an incoming AVCTP message.
494  *
495  *
496  * Returns          Nothing.
497  *
498  ******************************************************************************/
499 void avct_bcb_msg_ind(tAVCT_BCB* p_bcb, tAVCT_LCB_EVT* p_data) {
500   uint8_t* p;
501   uint8_t label, type, cr_ipid;
502   uint16_t pid;
503   tAVCT_CCB* p_ccb;
504   tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);
505
506   if ((p_data == NULL) || (p_data->p_buf == NULL)) {
507     AVCT_TRACE_WARNING("%s p_data is NULL, returning!", __func__);
508     return;
509   }
510
511   /* this p_buf is to be reported through p_msg_cback. The layer_specific
512    * needs to be set properly to indicate that it is received through
513    * browsing channel */
514   p_data->p_buf->layer_specific = AVCT_DATA_BROWSE;
515
516   /* reassemble message; if no message available (we received a fragment) return
517    */
518   p_data->p_buf = avct_bcb_msg_asmbl(p_bcb, p_data->p_buf);
519   if (p_data->p_buf == NULL) {
520     return;
521   }
522
523   p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset;
524
525   /* parse header byte */
526   AVCT_PARSE_HDR(p, label, type, cr_ipid);
527
528   /* check for invalid cr_ipid */
529   if (cr_ipid == AVCT_CR_IPID_INVALID) {
530     AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
531     osi_free_and_reset((void**)&p_data->p_buf);
532     return;
533   }
534
535   /* parse and lookup PID */
536   BE_STREAM_TO_UINT16(pid, p);
537   p_ccb = avct_lcb_has_pid(p_lcb, pid);
538   if (p_ccb) {
539     /* PID found; send msg up, adjust bt hdr and call msg callback */
540     p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
541     p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
542     (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
543                              p_data->p_buf);
544     return;
545   }
546
547   /* PID not found; drop message */
548   AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
549   osi_free_and_reset((void**)&p_data->p_buf);
550
551   /* if command send reject */
552   if (cr_ipid == AVCT_CMD) {
553     BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVRC_CMD_BUF_SIZE);
554     p_buf->len = AVCT_HDR_LEN_SINGLE;
555     p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
556     p = (uint8_t*)(p_buf + 1) + p_buf->offset;
557     AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
558     UINT16_TO_BE_STREAM(p, pid);
559     p_buf->layer_specific = AVCT_DATA_BROWSE;
560     L2CA_DataWrite(p_bcb->ch_lcid, p_buf);
561   }
562 }
563
564 /*******************************************************************************
565  *
566  * Function         avct_bcb_dealloc
567  *
568  * Description      Deallocate a browse control block.
569  *
570  *
571  * Returns          void.
572  *
573  ******************************************************************************/
574 void avct_bcb_dealloc(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
575   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
576
577   AVCT_TRACE_DEBUG("%s %d", __func__, p_bcb->allocated);
578
579   for (int idx = 0; idx < AVCT_NUM_CONN; idx++, p_ccb++) {
580     /* if ccb allocated and */
581     if ((p_ccb->allocated) && (p_ccb->p_bcb == p_bcb)) {
582       p_ccb->p_bcb = NULL;
583       AVCT_TRACE_DEBUG("%s used by ccb: %d", __func__, idx);
584       break;
585     }
586   }
587
588   /* the browsing channel is down. Check if we have pending messages */
589   osi_free_and_reset((void**)&p_bcb->p_tx_msg);
590   memset(p_bcb, 0, sizeof(tAVCT_BCB));
591 }
592
593 /*******************************************************************************
594  *
595  * Function         avct_close_bcb
596  *
597  * Description      this function is called right before LCB disconnects.
598  *
599  *
600  * Returns          Nothing.
601  *
602  ******************************************************************************/
603 void avct_close_bcb(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
604   tAVCT_BCB* p_bcb = avct_bcb_by_lcb(p_lcb);
605   if (p_bcb->allocated) {
606     avct_bcb_event(p_bcb, AVCT_LCB_UL_UNBIND_EVT, p_data);
607   }
608 }
609
610 /*******************************************************************************
611  *
612  * Function         avct_lcb_by_bcb
613  *
614  * Description      This lookup function finds the lcb for a bcb.
615  *
616  * Returns          pointer to the lcb.
617  *
618  ******************************************************************************/
619 tAVCT_LCB* avct_lcb_by_bcb(tAVCT_BCB* p_bcb) {
620   return &avct_cb.lcb[p_bcb->allocated - 1];
621 }
622
623 /*******************************************************************************
624  *
625  * Function         avct_bcb_by_lcb
626  *
627  * Description      This lookup function finds the bcb for a lcb.
628  *
629  * Returns          pointer to the lcb.
630  *
631  ******************************************************************************/
632 tAVCT_BCB* avct_bcb_by_lcb(tAVCT_LCB* p_lcb) {
633   return &avct_cb.bcb[p_lcb->allocated - 1];
634 }
635
636 /*******************************************************************************
637  *
638  * Function         avct_bcb_get_last_ccb_index
639  *
640  * Description      See if given ccb is only one on the bcb.
641  *
642  *
643  * Returns          0, if ccb is last,  (ccb index + 1) otherwise.
644  *
645  ******************************************************************************/
646 uint8_t avct_bcb_get_last_ccb_index(tAVCT_BCB* p_bcb, tAVCT_CCB* p_ccb_last) {
647   tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
648   uint8_t idx = 0;
649
650   for (int i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
651     if (p_ccb->allocated && (p_ccb->p_bcb == p_bcb)) {
652       if (p_ccb != p_ccb_last) return 0;
653       idx = (uint8_t)(i + 1);
654     }
655   }
656   return idx;
657 }
658
659 /*******************************************************************************
660  *
661  * Function         avct_bcb_by_lcid
662  *
663  * Description      Find the BCB associated with the L2CAP LCID
664  *
665  *
666  * Returns          pointer to the lcb, or NULL if none found.
667  *
668  ******************************************************************************/
669 tAVCT_BCB* avct_bcb_by_lcid(uint16_t lcid) {
670   tAVCT_BCB* p_bcb = &avct_cb.bcb[0];
671   int idx;
672
673   for (idx = 0; idx < AVCT_NUM_LINKS; idx++, p_bcb++) {
674     if (p_bcb->allocated && (p_bcb->ch_lcid == lcid)) {
675       return p_bcb;
676     }
677   }
678
679   /* out of lcbs */
680   AVCT_TRACE_WARNING("No bcb for lcid %x", lcid);
681   return NULL;
682 }