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