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 */
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 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 *******************************************************************************/
avct_lcb_chnl_open(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)171 void 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 *******************************************************************************/
avct_lcb_unbind_disc(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)196 void 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 *******************************************************************************/
avct_lcb_open_ind(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)216 void 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 *******************************************************************************/
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 {
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 *******************************************************************************/
avct_lcb_close_ind(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)293 void 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 *******************************************************************************/
avct_lcb_close_cfm(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)329 void 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 *******************************************************************************/
avct_lcb_bind_conn(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)374 void 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 *******************************************************************************/
avct_lcb_chk_disc(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)393 void 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 *******************************************************************************/
avct_lcb_chnl_disc(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)422 void 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 *******************************************************************************/
avct_lcb_bind_fail(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)440 void 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 *******************************************************************************/
avct_lcb_cong_ind(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)457 void 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 *******************************************************************************/
avct_lcb_discard_msg(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)498 void 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 *******************************************************************************/
avct_lcb_send_msg(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)517 void 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 *******************************************************************************/
avct_lcb_free_msg_ind(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)635 void 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 *******************************************************************************/
avct_lcb_msg_ind(tAVCT_LCB * p_lcb,tAVCT_LCB_EVT * p_data)654 void 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