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