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