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