blob: c927622480d6fc4ba15dc00e594b67776c9113c6 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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>
Chris Manton83e2c342014-09-29 21:37:44 -070026#include "bt_types.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080027#include "bt_target.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080028#include "bt_utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080029#include "avct_api.h"
30#include "avct_int.h"
Pavlin Radoslavov258c2532015-09-27 20:59:05 -070031#include "bt_common.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080032#include "btm_api.h"
33
34/* packet header length lookup table */
35const 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*******************************************************************************/
53static 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;
The Android Open Source Project5738f832012-12-12 16:00:35 -080058
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 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080066 osi_free(p_buf);
Sharvil Nanavati158084e2014-05-04 09:53:44 -070067 AVCT_TRACE_WARNING("Bad length during reassembly");
The Android Open Source Project5738f832012-12-12 16:00:35 -080068 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)
Sharvil Nanavati158084e2014-05-04 09:53:44 -070075 AVCT_TRACE_WARNING("Got single during reassembly");
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080076
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080077 osi_free_and_reset((void **)&p_lcb->p_rx_msg);
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080078
The Android Open Source Project5738f832012-12-12 16:00:35 -080079 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)
Sharvil Nanavati158084e2014-05-04 09:53:44 -070086 AVCT_TRACE_WARNING("Got start during reassembly");
Pavlin Radoslavov20524d32016-02-02 18:12:08 -080087
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080088 osi_free(p_lcb->p_rx_msg);
Pavlin Radoslavov20524d32016-02-02 18:12:08 -080089
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080090 /*
91 * Allocate bigger buffer for reassembly. As lower layers are
92 * not aware of possible packet size after reassembly, they
Mallikarjuna GB0d65d4c2013-11-10 13:30:25 +053093 * would have allocated smaller buffer.
94 */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -080095 p_lcb->p_rx_msg = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080096 memcpy(p_lcb->p_rx_msg, p_buf,
97 sizeof(BT_HDR) + p_buf->offset + p_buf->len);
The Android Open Source Project5738f832012-12-12 16:00:35 -080098
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -080099 /* Free original buffer */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800100 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800101
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800102 /* update p to point to new buffer */
103 p = (UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800104
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800105 /* copy first header byte over nosp */
106 *(p + 1) = *p;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800107
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800108 /* 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
The Android Open Source Project5738f832012-12-12 16:00:35 -0800114 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 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800122 osi_free(p_buf);
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700123 AVCT_TRACE_WARNING("Pkt type=%d out of order", pkt_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800124 p_ret = NULL;
125 }
126 else
127 {
128 /* get size of buffer holding assembled message */
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800129 /*
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);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800134
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 */
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800140 if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800141 /* won't fit; free everything */
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800142 AVCT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800143 osi_free_and_reset((void **)&p_lcb->p_rx_msg);
144 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800145 p_ret = NULL;
Pavlin Radoslavov0a20dd42016-02-04 18:20:06 -0800146 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800147 /* 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 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800164 osi_free(p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800165 }
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*******************************************************************************/
182void avct_lcb_chnl_open(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
183{
184 UINT16 result = AVCT_RESULT_FAIL;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800185 UNUSED(p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800186
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*******************************************************************************/
207void avct_lcb_unbind_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
208{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800209 UNUSED(p_lcb);
210
The Android Open Source Project5738f832012-12-12 16:00:35 -0800211 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*******************************************************************************/
227void 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*******************************************************************************/
278void 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*******************************************************************************/
304void 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;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800308 UNUSED(p_data);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800309
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*******************************************************************************/
340void 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*******************************************************************************/
385void 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*******************************************************************************/
404void avct_lcb_chk_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
405{
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700406 AVCT_TRACE_WARNING("avct_lcb_chk_disc");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800407#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 {
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700412 AVCT_TRACE_WARNING("closing");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800413 p_data->p_ccb->ch_close = TRUE;
414 avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
415 }
416 else
417 {
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700418 AVCT_TRACE_WARNING("dealloc ccb");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800419 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*******************************************************************************/
433void avct_lcb_chnl_disc(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
434{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800435 UNUSED(p_data);
436
The Android Open Source Project5738f832012-12-12 16:00:35 -0800437 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*******************************************************************************/
451void avct_lcb_bind_fail(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
452{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800453 UNUSED(p_lcb);
454
The Android Open Source Project5738f832012-12-12 16:00:35 -0800455 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*******************************************************************************/
468void 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;
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700478 if (p_lcb->cong == FALSE && !fixed_queue_is_empty(p_lcb->tx_q))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800479 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700480 while (!p_lcb->cong &&
481 (p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_lcb->tx_q)) != NULL)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800482 {
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*******************************************************************************/
510void avct_lcb_discard_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
511{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800512 UNUSED(p_lcb);
513
Pavlin Radoslavov20524d32016-02-02 18:12:08 -0800514 AVCT_TRACE_WARNING("Dropping message");
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800515 osi_free_and_reset((void **)&p_data->ul_msg.p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800516}
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*******************************************************************************/
528void 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;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800533 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 */
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800557 while (curr_msg_len != 0) {
558 BT_HDR *p_buf;
559
The Android Open Source Project5738f832012-12-12 16:00:35 -0800560 /* 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 */
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800567 p_buf = (BT_HDR *)osi_malloc(buf_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800568
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 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700604 fixed_queue_enqueue(p_lcb->tx_q, p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800605 }
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 }
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700626 AVCT_TRACE_DEBUG ("avct_lcb_send_msg tx_q_count:%d",
627 fixed_queue_length(p_lcb->tx_q));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800628 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*******************************************************************************/
641void avct_lcb_free_msg_ind(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data)
642{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800643 UNUSED(p_lcb);
644
Pavlin Radoslavov20524d32016-02-02 18:12:08 -0800645 if (p_data == NULL)
646 return;
647
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800648 osi_free_and_reset((void **)&p_data->p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800649}
650
651/*******************************************************************************
652**
653** Function avct_lcb_msg_ind
654**
655** Description Handle an incoming AVCTP message.
656**
657**
658** Returns Nothing.
659**
660*******************************************************************************/
661void 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;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800667
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);
Sharvil Nanavatif1c764f2015-02-23 17:31:48 -0800683 UNUSED(type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800684
685 /* check for invalid cr_ipid */
686 if (cr_ipid == AVCT_CR_IPID_INVALID)
687 {
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700688 AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800689 osi_free_and_reset((void **)&p_data->p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800690 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 */
Sharvil Nanavati158084e2014-05-04 09:53:44 -0700705 AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800706 osi_free_and_reset((void **)&p_data->p_buf);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800707
708 /* if command send reject */
709 if (cr_ipid == AVCT_CMD)
710 {
Pavlin Radoslavov717a4a92016-02-06 08:36:06 -0800711 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);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800718 }
719 }
720}