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 module contains action functions of the link control state machine.
22 *
23 ******************************************************************************/
24
25#include <string.h>
26#include "data_types.h"
27#include "bt_target.h"
28#include "avct_api.h"
29#include "avct_int.h"
30#include "gki.h"
31#include "btm_api.h"
32
33/* packet header length lookup table */
34const UINT8 avct_lcb_pkt_type_len[] = {
35    AVCT_HDR_LEN_SINGLE,
36    AVCT_HDR_LEN_START,
37    AVCT_HDR_LEN_CONT,
38    AVCT_HDR_LEN_END
39};
40
41/*******************************************************************************
42**
43** Function         avct_lcb_msg_asmbl
44**
45** Description      Reassemble incoming message.
46**
47**
48** Returns          Pointer to reassembled message;  NULL if no message
49**                  available.
50**
51*******************************************************************************/
52static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf)
53{
54    UINT8   *p;
55    UINT8   pkt_type;
56    BT_HDR  *p_ret;
57    UINT16  buf_len;
58
59    /* parse the message header */
60    p = (UINT8 *)(p_buf + 1) + p_buf->offset;
61    AVCT_PRS_PKT_TYPE(p, pkt_type);
62
63    /* quick sanity check on length */
64    if (p_buf->len < avct_lcb_pkt_type_len[pkt_type])
65    {
66        GKI_freebuf(p_buf);
67        AVCT_TRACE_WARNING0("Bad length during reassembly");
68        p_ret = NULL;
69    }
70    /* single packet */
71    else if (pkt_type == AVCT_PKT_TYPE_SINGLE)
72    {
73        /* if reassembly in progress drop message and process new single */
74        if (p_lcb->p_rx_msg != NULL)
75        {
76            GKI_freebuf(p_lcb->p_rx_msg);
77            p_lcb->p_rx_msg = NULL;
78            AVCT_TRACE_WARNING0("Got single during reassembly");
79        }
80        p_ret = p_buf;
81    }
82    /* start packet */
83    else if (pkt_type == AVCT_PKT_TYPE_START)
84    {
85        /* if reassembly in progress drop message and process new start */
86        if (p_lcb->p_rx_msg != NULL)
87        {
88            GKI_freebuf(p_lcb->p_rx_msg);
89            AVCT_TRACE_WARNING0("Got start during reassembly");
90        }
91        p_lcb->p_rx_msg = p_buf;
92
93        /* copy first header byte over nosp */
94        *(p + 1) = *p;
95
96        /* set offset to point to where to copy next */
97        p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
98
99        /* adjust length for packet header */
100        p_lcb->p_rx_msg->len -= 1;
101
102        p_ret = NULL;
103    }
104    /* continue or end */
105    else
106    {
107        /* if no reassembly in progress drop message */
108        if (p_lcb->p_rx_msg == NULL)
109        {
110            GKI_freebuf(p_buf);
111            AVCT_TRACE_WARNING1("Pkt type=%d out of order", pkt_type);
112            p_ret = NULL;
113        }
114        else
115        {
116            /* get size of buffer holding assembled message */
117            buf_len = GKI_get_buf_size(p_lcb->p_rx_msg) - sizeof(BT_HDR);
118
119            /* adjust offset and len of fragment for header byte */
120            p_buf->offset += AVCT_HDR_LEN_CONT;
121            p_buf->len -= AVCT_HDR_LEN_CONT;
122
123            /* verify length */
124            if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len)
125            {
126                /* won't fit; free everything */
127                GKI_freebuf(p_lcb->p_rx_msg);
128                p_lcb->p_rx_msg = NULL;
129                GKI_freebuf(p_buf);
130                p_ret = NULL;
131                AVCT_TRACE_WARNING0("Fragmented message to big!");
132            }
133            else
134            {
135                /* copy contents of p_buf to p_rx_msg */
136                memcpy((UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset,
137                       (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len);
138
139                if (pkt_type == AVCT_PKT_TYPE_END)
140                {
141                    p_lcb->p_rx_msg->offset -= p_lcb->p_rx_msg->len;
142                    p_lcb->p_rx_msg->len += p_buf->len;
143                    p_ret = p_lcb->p_rx_msg;
144                    p_lcb->p_rx_msg = NULL;
145                }
146                else
147                {
148                    p_lcb->p_rx_msg->offset += p_buf->len;
149                    p_lcb->p_rx_msg->len += p_buf->len;
150                    p_ret = NULL;
151                }
152                GKI_freebuf(p_buf);
153            }
154        }
155    }
156    return p_ret;
157}
158
159
160/*******************************************************************************
161**
162** Function         avct_lcb_chnl_open
163**
164** Description      Open L2CAP channel to peer
165**
166**
167** Returns          Nothing.
168**
169*******************************************************************************/
170void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
171{
172    UINT16 result = AVCT_RESULT_FAIL;
173
174    BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0);
175    /* call l2cap connect req */
176    p_lcb->ch_state = AVCT_CH_CONN;
177    if ((p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr)) == 0)
178    {
179        /* if connect req failed, send ourselves close event */
180        avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT *) &result);
181    }
182}
183
184/*******************************************************************************
185**
186** Function         avct_lcb_unbind_disc
187**
188** Description      Deallocate ccb and call callback with disconnect event.
189**
190**
191** Returns          Nothing.
192**
193*******************************************************************************/
194void avct_lcb_unbind_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
195{
196    avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
197}
198
199/*******************************************************************************
200**
201** Function         avct_lcb_open_ind
202**
203** Description      Handle an LL_OPEN event.  For each allocated ccb already
204**                  bound to this lcb, send a connect event.  For each
205**                  unbound ccb with a new PID, bind that ccb to this lcb and
206**                  send a connect event.
207**
208**
209** Returns          Nothing.
210**
211*******************************************************************************/
212void avct_lcb_open_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
213{
214    tAVCT_CCB   *p_ccb = &avct_cb.ccb[0];
215    int         i;
216    BOOLEAN     bind = FALSE;
217
218    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
219    {
220        /* if ccb allocated and */
221        if (p_ccb->allocated)
222        {
223            /* if bound to this lcb send connect confirm event */
224            if (p_ccb->p_lcb == p_lcb)
225            {
226                bind = TRUE;
227                L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
228                p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT,
229                                       0, p_lcb->peer_addr);
230            }
231            /* if unbound acceptor and lcb doesn't already have a ccb for this PID */
232            else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
233                     (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL))
234            {
235                /* bind ccb to lcb and send connect ind event */
236                bind = TRUE;
237                p_ccb->p_lcb = p_lcb;
238                L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
239                p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT,
240                                    0, p_lcb->peer_addr);
241            }
242        }
243    }
244
245    /* if no ccbs bound to this lcb, disconnect */
246    if (bind == FALSE)
247    {
248        avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
249    }
250}
251
252/*******************************************************************************
253**
254** Function         avct_lcb_open_fail
255**
256** Description      L2CAP channel open attempt failed.  Deallocate any ccbs
257**                  on this lcb and send connect confirm event with failure.
258**
259**
260** Returns          Nothing.
261**
262*******************************************************************************/
263void avct_lcb_open_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
264{
265    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
266    int                 i;
267
268    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
269    {
270        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
271        {
272            avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT,
273                             p_data->result, p_lcb->peer_addr);
274        }
275    }
276}
277
278/*******************************************************************************
279**
280** Function         avct_lcb_close_ind
281**
282** Description      L2CAP channel closed by peer.  Deallocate any initiator
283**                  ccbs on this lcb and send disconnect ind event.
284**
285**
286** Returns          Nothing.
287**
288*******************************************************************************/
289void avct_lcb_close_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
290{
291    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
292    int                 i;
293
294    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
295    {
296        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
297        {
298            if (p_ccb->cc.role == AVCT_INT)
299            {
300                avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT,
301                                 0, p_lcb->peer_addr);
302            }
303            else
304            {
305                p_ccb->p_lcb = NULL;
306                (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), AVCT_DISCONNECT_IND_EVT,
307                                          0, p_lcb->peer_addr);
308            }
309        }
310    }
311}
312
313/*******************************************************************************
314**
315** Function         avct_lcb_close_cfm
316**
317** Description      L2CAP channel closed by us.  Deallocate any initiator
318**                  ccbs on this lcb and send disconnect ind or cfm event.
319**
320**
321** Returns          Nothing.
322**
323*******************************************************************************/
324void avct_lcb_close_cfm(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
325{
326    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
327    int                 i;
328    UINT8               event;
329
330    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
331    {
332        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
333        {
334            /* if this ccb initiated close send disconnect cfm otherwise ind */
335            if (p_ccb->ch_close)
336            {
337                p_ccb->ch_close = FALSE;
338                event = AVCT_DISCONNECT_CFM_EVT;
339            }
340            else
341            {
342                event = AVCT_DISCONNECT_IND_EVT;
343            }
344
345            if (p_ccb->cc.role == AVCT_INT)
346            {
347                avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr);
348            }
349            else
350            {
351                p_ccb->p_lcb = NULL;
352                (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event,
353                                       p_data->result, p_lcb->peer_addr);
354            }
355        }
356    }
357}
358
359/*******************************************************************************
360**
361** Function         avct_lcb_bind_conn
362**
363** Description      Bind ccb to lcb and send connect cfm event.
364**
365**
366** Returns          Nothing.
367**
368*******************************************************************************/
369void avct_lcb_bind_conn(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
370{
371    p_data->p_ccb->p_lcb = p_lcb;
372    (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
373                                      AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
374}
375
376/*******************************************************************************
377**
378** Function         avct_lcb_chk_disc
379**
380** Description      A ccb wants to close; if it is the last ccb on this lcb,
381**                  close channel.  Otherwise just deallocate and call
382**                  callback.
383**
384**
385** Returns          Nothing.
386**
387*******************************************************************************/
388void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
389{
390    AVCT_TRACE_WARNING0("avct_lcb_chk_disc");
391#if (AVCT_BROWSE_INCLUDED == TRUE)
392    avct_close_bcb(p_lcb, p_data);
393#endif
394    if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb))
395    {
396        AVCT_TRACE_WARNING0("closing");
397        p_data->p_ccb->ch_close = TRUE;
398        avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
399    }
400    else
401    {
402        AVCT_TRACE_WARNING0("dealloc ccb");
403        avct_lcb_unbind_disc(p_lcb, p_data);
404    }
405}
406
407/*******************************************************************************
408**
409** Function         avct_lcb_chnl_disc
410**
411** Description      Disconnect L2CAP channel.
412**
413**
414** Returns          Nothing.
415**
416*******************************************************************************/
417void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
418{
419    L2CA_DisconnectReq(p_lcb->ch_lcid);
420}
421
422/*******************************************************************************
423**
424** Function         avct_lcb_bind_fail
425**
426** Description      Deallocate ccb and call callback with connect event
427**                  with failure result.
428**
429**
430** Returns          Nothing.
431**
432*******************************************************************************/
433void avct_lcb_bind_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
434{
435    avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
436}
437
438/*******************************************************************************
439**
440** Function         avct_lcb_cong_ind
441**
442** Description      Handle congestion indication from L2CAP.
443**
444**
445** Returns          Nothing.
446**
447*******************************************************************************/
448void avct_lcb_cong_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
449{
450    tAVCT_CCB           *p_ccb = &avct_cb.ccb[0];
451    int                 i;
452    UINT8               event;
453    BT_HDR          *p_buf;
454
455    /* set event */
456    event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
457    p_lcb->cong = p_data->cong;
458    if (p_lcb->cong == FALSE && GKI_getfirst(&p_lcb->tx_q))
459    {
460        while ( !p_lcb->cong  && (p_buf = (BT_HDR *)GKI_dequeue(&p_lcb->tx_q)) != NULL)
461        {
462            if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
463            {
464                p_lcb->cong = TRUE;
465            }
466        }
467    }
468
469    /* send event to all ccbs on this lcb */
470    for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++)
471    {
472        if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb))
473        {
474            (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0, p_lcb->peer_addr);
475        }
476    }
477}
478
479/*******************************************************************************
480**
481** Function         avct_lcb_discard_msg
482**
483** Description      Discard a message sent in from the API.
484**
485**
486** Returns          Nothing.
487**
488*******************************************************************************/
489void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
490{
491    AVCT_TRACE_WARNING0("Dropping msg");
492
493    GKI_freebuf(p_data->ul_msg.p_buf);
494}
495
496/*******************************************************************************
497**
498** Function         avct_lcb_send_msg
499**
500** Description      Build and send an AVCTP message.
501**
502**
503** Returns          Nothing.
504**
505*******************************************************************************/
506void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
507{
508    UINT16          curr_msg_len;
509    UINT8           pkt_type;
510    UINT8           hdr_len;
511    BT_HDR          *p_buf;
512    UINT8           *p;
513    UINT8           nosp = 0;       /* number of subsequent packets */
514    UINT16          temp;
515    UINT16          buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
516
517
518    /* store msg len */
519    curr_msg_len = p_data->ul_msg.p_buf->len;
520
521    /* initialize packet type and other stuff */
522    if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE))
523    {
524        pkt_type = AVCT_PKT_TYPE_SINGLE;
525    }
526    else
527    {
528        pkt_type = AVCT_PKT_TYPE_START;
529        temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu);
530        nosp = temp / (p_lcb->peer_mtu - 1) + 1;
531        if ( (temp % (p_lcb->peer_mtu - 1)) != 0)
532            nosp++;
533    }
534
535    /* while we haven't sent all packets */
536    while (curr_msg_len != 0)
537    {
538        /* set header len */
539        hdr_len = avct_lcb_pkt_type_len[pkt_type];
540
541        /* if remaining msg must be fragmented */
542        if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len))
543        {
544            /* get a new buffer for fragment we are sending */
545            if ((p_buf = (BT_HDR *) GKI_getbuf(buf_size)) == NULL)
546            {
547                /* whoops; free original msg buf and bail */
548                AVCT_TRACE_ERROR0 ("avct_lcb_send_msg cannot alloc buffer!!");
549                GKI_freebuf(p_data->ul_msg.p_buf);
550                break;
551            }
552
553            /* copy portion of data from current message to new buffer */
554            p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
555            p_buf->len = p_lcb->peer_mtu - hdr_len;
556
557            memcpy((UINT8 *)(p_buf + 1) + p_buf->offset,
558                   (UINT8 *)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset, p_buf->len);
559
560            p_data->ul_msg.p_buf->offset += p_buf->len;
561            p_data->ul_msg.p_buf->len -= p_buf->len;
562        }
563        else
564        {
565            p_buf = p_data->ul_msg.p_buf;
566        }
567
568        curr_msg_len -= p_buf->len;
569
570        /* set up to build header */
571        p_buf->len += hdr_len;
572        p_buf->offset -= hdr_len;
573        p = (UINT8 *)(p_buf + 1) + p_buf->offset;
574
575        /* build header */
576        AVCT_BLD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
577        if (pkt_type == AVCT_PKT_TYPE_START)
578        {
579            UINT8_TO_STREAM(p, nosp);
580        }
581        if ((pkt_type == AVCT_PKT_TYPE_START) || (pkt_type == AVCT_PKT_TYPE_SINGLE))
582        {
583            UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
584        }
585
586        if (p_lcb->cong == TRUE)
587        {
588            GKI_enqueue (&p_lcb->tx_q, p_buf);
589        }
590
591        /* send message to L2CAP */
592        else
593        {
594            if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED)
595            {
596                p_lcb->cong = TRUE;
597            }
598        }
599
600        /* update pkt type for next packet */
601        if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END))
602        {
603            pkt_type = AVCT_PKT_TYPE_CONT;
604        }
605        else
606        {
607            pkt_type = AVCT_PKT_TYPE_END;
608        }
609    }
610    AVCT_TRACE_DEBUG1 ("avct_lcb_send_msg tx_q_count:%d", p_lcb->tx_q.count);
611    return;
612}
613
614/*******************************************************************************
615**
616** Function         avct_lcb_free_msg_ind
617**
618** Description      Discard an incoming AVCTP message.
619**
620**
621** Returns          Nothing.
622**
623*******************************************************************************/
624void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
625{
626    if (p_data)
627        GKI_freebuf(p_data->p_buf);
628    return;
629}
630
631/*******************************************************************************
632**
633** Function         avct_lcb_msg_ind
634**
635** Description      Handle an incoming AVCTP message.
636**
637**
638** Returns          Nothing.
639**
640*******************************************************************************/
641void avct_lcb_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
642{
643    UINT8       *p;
644    UINT8       label, type, cr_ipid;
645    UINT16      pid;
646    tAVCT_CCB   *p_ccb;
647    BT_HDR      *p_buf;
648
649    /* this p_buf is to be reported through p_msg_cback. The layer_specific
650     * needs to be set properly to indicate that it is received through
651     * control channel */
652    p_data->p_buf->layer_specific = AVCT_DATA_CTRL;
653
654    /* reassemble message; if no message available (we received a fragment) return */
655    if ((p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf)) == NULL)
656    {
657        return;
658    }
659
660    p = (UINT8 *)(p_data->p_buf + 1) + p_data->p_buf->offset;
661
662    /* parse header byte */
663    AVCT_PRS_HDR(p, label, type, cr_ipid);
664
665    /* check for invalid cr_ipid */
666    if (cr_ipid == AVCT_CR_IPID_INVALID)
667    {
668        AVCT_TRACE_WARNING1("Invalid cr_ipid", cr_ipid);
669        GKI_freebuf(p_data->p_buf);
670        return;
671    }
672
673    /* parse and lookup PID */
674    BE_STREAM_TO_UINT16(pid, p);
675    if ((p_ccb = avct_lcb_has_pid(p_lcb, pid)) != NULL)
676    {
677        /* PID found; send msg up, adjust bt hdr and call msg callback */
678        p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
679        p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
680        (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid, p_data->p_buf);
681    }
682    else
683    {
684        /* PID not found; drop message */
685        AVCT_TRACE_WARNING1("No ccb for PID=%x", pid);
686        GKI_freebuf(p_data->p_buf);
687
688        /* if command send reject */
689        if (cr_ipid == AVCT_CMD)
690        {
691            if ((p_buf = (BT_HDR *) GKI_getpoolbuf(AVCT_CMD_POOL_ID)) != NULL)
692            {
693                p_buf->len = AVCT_HDR_LEN_SINGLE;
694                p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
695                p = (UINT8 *)(p_buf + 1) + p_buf->offset;
696                AVCT_BLD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
697                UINT16_TO_BE_STREAM(p, pid);
698                L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
699            }
700        }
701    }
702}
703