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