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