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