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