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