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