15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2003-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  This module contains action functions of the link control state machine.
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "avct_api.h"
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "avct_int.h"
28258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h"
29911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_target.h"
30911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_types.h"
31911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_utils.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_api.h"
33d7ffd64accbd50a27289a388856e56244ccbb5daMyles Watson#include "osi/include/osi.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* packet header length lookup table */
36911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonconst uint8_t avct_lcb_pkt_type_len[] = {AVCT_HDR_LEN_SINGLE,
37911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         AVCT_HDR_LEN_START, AVCT_HDR_LEN_CONT,
38911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                         AVCT_HDR_LEN_END};
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
41ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
42ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_msg_asmbl
43ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
44ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Reassemble incoming message.
45ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
46ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
47ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to reassembled message;  NULL if no message
48ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  available.
49ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
50ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
51911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic BT_HDR* avct_lcb_msg_asmbl(tAVCT_LCB* p_lcb, BT_HDR* p_buf) {
52911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
53911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t pkt_type;
54911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_ret;
55911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
56911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* parse the message header */
57911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + p_buf->offset;
58911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pkt_type = AVCT_PKT_TYPE(p);
59911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
60911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* quick sanity check on length */
61911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf->len < avct_lcb_pkt_type_len[pkt_type]) {
62911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
63911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    AVCT_TRACE_WARNING("Bad length during reassembly");
64911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ret = NULL;
65911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
66911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* single packet */
67911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (pkt_type == AVCT_PKT_TYPE_SINGLE) {
68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if reassembly in progress drop message and process new single */
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->p_rx_msg != NULL)
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      AVCT_TRACE_WARNING("Got single during reassembly");
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free_and_reset((void**)&p_lcb->p_rx_msg);
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ret = p_buf;
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* start packet */
77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (pkt_type == AVCT_PKT_TYPE_START) {
78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if reassembly in progress drop message and process new start */
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->p_rx_msg != NULL)
80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      AVCT_TRACE_WARNING("Got start during reassembly");
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_lcb->p_rx_msg);
83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /*
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * Allocate bigger buffer for reassembly. As lower layers are
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * not aware of possible packet size after reassembly, they
87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * would have allocated smaller buffer.
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_rx_msg = (BT_HDR*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    memcpy(p_lcb->p_rx_msg, p_buf, sizeof(BT_HDR) + p_buf->offset + p_buf->len);
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Free original buffer */
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* update p to point to new buffer */
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p = (uint8_t*)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset;
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* copy first header byte over nosp */
99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *(p + 1) = *p;
100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* set offset to point to where to copy next */
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len;
103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* adjust length for packet header */
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_rx_msg->len -= 1;
106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ret = NULL;
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* continue or end */
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if no reassembly in progress drop message */
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->p_rx_msg == NULL) {
113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      AVCT_TRACE_WARNING("Pkt type=%d out of order", pkt_type);
115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ret = NULL;
116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* get size of buffer holding assembled message */
118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * NOTE: The buffer is allocated above at the beginning of the
120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * reassembly, and is always of size BT_DEFAULT_BUFFER_SIZE.
121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      uint16_t buf_len = BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR);
123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* adjust offset and len of fragment for header byte */
125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf->offset += AVCT_HDR_LEN_CONT;
126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf->len -= AVCT_HDR_LEN_CONT;
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* verify length */
129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_lcb->p_rx_msg->offset + p_buf->len) > buf_len) {
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* won't fit; free everything */
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        AVCT_TRACE_WARNING("%s: Fragmented message too big!", __func__);
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        osi_free_and_reset((void**)&p_lcb->p_rx_msg);
133cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov        osi_free(p_buf);
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        p_ret = NULL;
135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* copy contents of p_buf to p_rx_msg */
137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        memcpy((uint8_t*)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset,
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (pkt_type == AVCT_PKT_TYPE_END) {
141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_rx_msg->offset -= p_lcb->p_rx_msg->len;
142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_rx_msg->len += p_buf->len;
143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_ret = p_lcb->p_rx_msg;
144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_rx_msg = NULL;
145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        } else {
146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_rx_msg->offset += p_buf->len;
147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_rx_msg->len += p_buf->len;
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_ret = NULL;
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        osi_free(p_buf);
151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return p_ret;
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
158ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
159ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_chnl_open
160ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
161ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Open L2CAP channel to peer
162ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
163ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
164ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
165ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
166ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_chnl_open(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t result = AVCT_RESULT_FAIL;
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BTM_SetOutService(p_lcb->peer_addr, BTM_SEC_SERVICE_AVCTP, 0);
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* call l2cap connect req */
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->ch_state = AVCT_CH_CONN;
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->ch_lcid = L2CA_ConnectReq(AVCT_PSM, p_lcb->peer_addr);
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->ch_lcid == 0) {
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if connect req failed, send ourselves close event */
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    avct_lcb_event(p_lcb, AVCT_LCB_LL_CLOSE_EVT, (tAVCT_LCB_EVT*)&result);
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
182ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_unbind_disc
183ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
184ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Deallocate ccb and call callback with disconnect event.
185ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
186ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
187ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
188ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
189ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_unbind_disc(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  avct_ccb_dealloc(p_data->p_ccb, AVCT_DISCONNECT_CFM_EVT, 0, NULL);
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_open_ind
197ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
198ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Handle an LL_OPEN event.  For each allocated ccb already
199ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  bound to this lcb, send a connect event.  For each
200ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  unbound ccb with a new PID, bind that ccb to this lcb and
201ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  send a connect event.
202ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
203ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
206ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_open_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i;
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool bind = false;
211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if ccb allocated and */
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->allocated) {
215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if bound to this lcb send connect confirm event */
216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb == p_lcb) {
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        bind = true;
218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_CFM_EVT, 0,
220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               p_lcb->peer_addr);
221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if unbound acceptor and lcb doesn't already have a ccb for this PID */
223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else if ((p_ccb->p_lcb == NULL) && (p_ccb->cc.role == AVCT_ACP) &&
224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               (avct_lcb_has_pid(p_lcb, p_ccb->cc.pid) == NULL)) {
225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* bind ccb to lcb and send connect ind event */
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        bind = true;
227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb = p_lcb;
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CA_SetTxPriority(p_lcb->ch_lcid, L2CAP_CHNL_PRIORITY_HIGH);
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cc.p_ctrl_cback(avct_ccb_to_idx(p_ccb), AVCT_CONNECT_IND_EVT, 0,
230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               p_lcb->peer_addr);
231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* if no ccbs bound to this lcb, disconnect */
236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (bind == false) {
237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_open_fail
244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      L2CAP channel open attempt failed.  Deallocate any ccbs
246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on this lcb and send connect confirm event with failure.
247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_open_fail(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i;
255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      avct_ccb_dealloc(p_ccb, AVCT_CONNECT_CFM_EVT, p_data->result,
259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       p_lcb->peer_addr);
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
265ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
266ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_close_ind
267ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
268ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      L2CAP channel closed by peer.  Deallocate any initiator
269ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  ccbs on this lcb and send disconnect ind event.
270ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
271ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
272ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
273ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
274ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_close_ind(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i;
278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->cc.role == AVCT_INT) {
282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        avct_ccb_dealloc(p_ccb, AVCT_DISCONNECT_IND_EVT, 0, p_lcb->peer_addr);
283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb = NULL;
285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb),
286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  AVCT_DISCONNECT_IND_EVT, 0, p_lcb->peer_addr);
287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
294ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_close_cfm
295ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
296ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      L2CAP channel closed by us.  Deallocate any initiator
297ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  ccbs on this lcb and send disconnect ind or cfm event.
298ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
299ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
300ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
301ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
302ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_close_cfm(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i;
306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t event;
307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if this ccb initiated close send disconnect cfm otherwise ind */
311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->ch_close) {
312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->ch_close = false;
313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        event = AVCT_DISCONNECT_CFM_EVT;
314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        event = AVCT_DISCONNECT_IND_EVT;
316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->cc.role == AVCT_INT) {
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        avct_ccb_dealloc(p_ccb, event, p_data->result, p_lcb->peer_addr);
320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb = NULL;
322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, p_data->result,
323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                  p_lcb->peer_addr);
324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
330ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
331ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_bind_conn
332ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
333ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Bind ccb to lcb and send connect cfm event.
334ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
335ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
337ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_bind_conn(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_data->p_ccb->p_lcb = p_lcb;
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  (*p_data->p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_data->p_ccb),
342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                    AVCT_CONNECT_CFM_EVT, 0, p_lcb->peer_addr);
3435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
346ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
347ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_chk_disc
348ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
349ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      A ccb wants to close; if it is the last ccb on this lcb,
350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  close channel.  Otherwise just deallocate and call
351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  callback.
352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_chk_disc(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  AVCT_TRACE_WARNING("%s", __func__);
359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  avct_close_bcb(p_lcb, p_data);
361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (avct_lcb_last_ccb(p_lcb, p_data->p_ccb)) {
362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    AVCT_TRACE_WARNING("%s: closing", __func__);
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_data->p_ccb->ch_close = true;
364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    avct_lcb_event(p_lcb, AVCT_LCB_INT_CLOSE_EVT, p_data);
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    AVCT_TRACE_WARNING("%s: dealloc ccb", __func__);
367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    avct_lcb_unbind_disc(p_lcb, p_data);
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
372ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
373ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_chnl_disc
374ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Disconnect L2CAP channel.
376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_chnl_disc(tAVCT_LCB* p_lcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {
382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CA_DisconnectReq(p_lcb->ch_lcid);
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
386ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
387ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_bind_fail
388ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
389ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Deallocate ccb and call callback with connect event
390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  with failure result.
391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_bind_fail(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  avct_ccb_dealloc(p_data->p_ccb, AVCT_CONNECT_CFM_EVT, AVCT_RESULT_FAIL, NULL);
3985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
401ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
402ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_cong_ind
403ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Handle congestion indication from L2CAP.
405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_cong_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tAVCT_CCB* p_ccb = &avct_cb.ccb[0];
412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i;
413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t event;
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* set event */
417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  event = (p_data->cong) ? AVCT_CONG_IND_EVT : AVCT_UNCONG_IND_EVT;
418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->cong = p_data->cong;
419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->cong == false && !fixed_queue_is_empty(p_lcb->tx_q)) {
420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!p_lcb->cong &&
421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           (p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_lcb->tx_q)) != NULL) {
422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) {
423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->cong = true;
424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
4255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* send event to all ccbs on this lcb */
429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < AVCT_NUM_CONN; i++, p_ccb++) {
430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->allocated && (p_ccb->p_lcb == p_lcb)) {
431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (*p_ccb->cc.p_ctrl_cback)(avct_ccb_to_idx(p_ccb), event, 0,
432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                p_lcb->peer_addr);
4335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
438ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
439ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_discard_msg
440ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
441ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Discard a message sent in from the API.
442ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
443ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
444ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
445ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
446ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_discard_msg(UNUSED_ATTR tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  AVCT_TRACE_WARNING("%s Dropping message", __func__);
449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free_and_reset((void**)&p_data->ul_msg.p_buf);
4505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
453ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
454ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_send_msg
455ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
456ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an AVCTP message.
457ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
458ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
459ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
460ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
461ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_send_msg(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t curr_msg_len;
464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t pkt_type;
465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t hdr_len;
466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t nosp = 0; /* number of subsequent packets */
468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t temp;
469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t buf_size = p_lcb->peer_mtu + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* store msg len */
472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  curr_msg_len = p_data->ul_msg.p_buf->len;
473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* initialize packet type and other stuff */
475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (curr_msg_len <= (p_lcb->peer_mtu - AVCT_HDR_LEN_SINGLE)) {
476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    pkt_type = AVCT_PKT_TYPE_SINGLE;
477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    pkt_type = AVCT_PKT_TYPE_START;
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    temp = (curr_msg_len + AVCT_HDR_LEN_START - p_lcb->peer_mtu);
480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    nosp = temp / (p_lcb->peer_mtu - 1) + 1;
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((temp % (p_lcb->peer_mtu - 1)) != 0) nosp++;
482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* while we haven't sent all packets */
485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (curr_msg_len != 0) {
486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    BT_HDR* p_buf;
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* set header len */
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    hdr_len = avct_lcb_pkt_type_len[pkt_type];
490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if remaining msg must be fragmented */
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_data->ul_msg.p_buf->len > (p_lcb->peer_mtu - hdr_len)) {
493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* get a new buffer for fragment we are sending */
494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = (BT_HDR*)osi_malloc(buf_size);
495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* copy portion of data from current message to new buffer */
497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf->offset = L2CAP_MIN_OFFSET + hdr_len;
498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf->len = p_lcb->peer_mtu - hdr_len;
499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memcpy(
501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (uint8_t*)(p_buf + 1) + p_buf->offset,
502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (uint8_t*)(p_data->ul_msg.p_buf + 1) + p_data->ul_msg.p_buf->offset,
503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_buf->len);
504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_data->ul_msg.p_buf->offset += p_buf->len;
506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_data->ul_msg.p_buf->len -= p_buf->len;
507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = p_data->ul_msg.p_buf;
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    curr_msg_len -= p_buf->len;
5125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* set up to build header */
514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf->len += hdr_len;
515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf->offset -= hdr_len;
516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p = (uint8_t*)(p_buf + 1) + p_buf->offset;
5175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* build header */
519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    AVCT_BUILD_HDR(p, p_data->ul_msg.label, pkt_type, p_data->ul_msg.cr);
520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (pkt_type == AVCT_PKT_TYPE_START) {
521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT8_TO_STREAM(p, nosp);
522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((pkt_type == AVCT_PKT_TYPE_START) ||
524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (pkt_type == AVCT_PKT_TYPE_SINGLE)) {
525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_BE_STREAM(p, p_data->ul_msg.p_ccb->cc.pid);
526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->cong == true) {
529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      fixed_queue_enqueue(p_lcb->tx_q, p_buf);
530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* send message to L2CAP */
533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (L2CA_DataWrite(p_lcb->ch_lcid, p_buf) == L2CAP_DW_CONGESTED) {
535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->cong = true;
536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
5385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* update pkt type for next packet */
540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (curr_msg_len > (p_lcb->peer_mtu - AVCT_HDR_LEN_END)) {
541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      pkt_type = AVCT_PKT_TYPE_CONT;
542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      pkt_type = AVCT_PKT_TYPE_END;
5445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  AVCT_TRACE_DEBUG("%s tx_q_count:%d", __func__,
547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                   fixed_queue_length(p_lcb->tx_q));
548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return;
5495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
552ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
553ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_free_msg_ind
554ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
555ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Discard an incoming AVCTP message.
556ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
557ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
558ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
559ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
560ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_free_msg_ind(UNUSED_ATTR tAVCT_LCB* p_lcb,
562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           tAVCT_LCB_EVT* p_data) {
563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_data == NULL) return;
56420524d393e8b3bea4c573f7980cd843500b0e6a4Pavlin Radoslavov
565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free_and_reset((void**)&p_data->p_buf);
5665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
569ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
570ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         avct_lcb_msg_ind
571ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
572ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Handle an incoming AVCTP message.
573ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
574ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
575ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing.
576ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
577ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid avct_lcb_msg_ind(tAVCT_LCB* p_lcb, tAVCT_LCB_EVT* p_data) {
579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t label, type, cr_ipid;
581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t pid;
582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tAVCT_CCB* p_ccb;
583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* this p_buf is to be reported through p_msg_cback. The layer_specific
585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * needs to be set properly to indicate that it is received through
586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * control channel */
587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_data->p_buf->layer_specific = AVCT_DATA_CTRL;
588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* reassemble message; if no message available (we received a fragment) return
590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   */
591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_data->p_buf = avct_lcb_msg_asmbl(p_lcb, p_data->p_buf);
592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_data->p_buf == NULL) {
593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_data->p_buf + 1) + p_data->p_buf->offset;
5975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* parse header byte */
599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  AVCT_PARSE_HDR(p, label, type, cr_ipid);
6005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* check for invalid cr_ipid */
602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cr_ipid == AVCT_CR_IPID_INVALID) {
603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    AVCT_TRACE_WARNING("Invalid cr_ipid", cr_ipid);
604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free_and_reset((void**)&p_data->p_buf);
605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* parse and lookup PID */
609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BE_STREAM_TO_UINT16(pid, p);
610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = avct_lcb_has_pid(p_lcb, pid);
611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb) {
612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* PID found; send msg up, adjust bt hdr and call msg callback */
613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_data->p_buf->offset += AVCT_HDR_LEN_SINGLE;
614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_data->p_buf->len -= AVCT_HDR_LEN_SINGLE;
615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_ccb->cc.p_msg_cback)(avct_ccb_to_idx(p_ccb), label, cr_ipid,
616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             p_data->p_buf);
617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* PID not found; drop message */
621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  AVCT_TRACE_WARNING("No ccb for PID=%x", pid);
622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free_and_reset((void**)&p_data->p_buf);
623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* if command send reject */
625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cr_ipid == AVCT_CMD) {
626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    BT_HDR* p_buf = (BT_HDR*)osi_malloc(AVCT_CMD_BUF_SIZE);
627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf->len = AVCT_HDR_LEN_SINGLE;
628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf->offset = AVCT_MSG_OFFSET - AVCT_HDR_LEN_SINGLE;
629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p = (uint8_t*)(p_buf + 1) + p_buf->offset;
630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    AVCT_BUILD_HDR(p, label, AVCT_PKT_TYPE_SINGLE, AVCT_REJ);
631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_BE_STREAM(p, pid);
632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CA_DataWrite(p_lcb->ch_lcid, p_buf);
633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
635