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