l2c_utils.cc revision 7c8bab231328956d3b7569280cb162be4e345422
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 1999-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 file contains L2CAP utility functions
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include <stdio.h>
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h>
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
29258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h"
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_types.h"
31911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_utils.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_api.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_int.h"
34911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btu.h"
35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "device/include/controller.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcidefs.h"
37911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "hcimsgs.h"
38911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2c_int.h"
39911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2cdefs.h"
40a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati#include "osi/include/allocator.h"
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
42911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonextern fixed_queue_t* btu_general_alarm_queue;
4378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
45ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
46ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_lcb
47ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
48ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look for an unused LCB
49ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
50ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          LCB address or NULL if none found
51ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
52ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
53911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_allocate_lcb(BD_ADDR p_bd_addr, bool is_bonding,
54911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            tBT_TRANSPORT transport) {
55911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
56911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
57911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
58911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
59911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->in_use) {
60911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      alarm_free(p_lcb->l2c_lcb_timer);
61911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      alarm_free(p_lcb->info_resp_timer);
62911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memset(p_lcb, 0, sizeof(tL2C_LCB));
63911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
64911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memcpy(p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN);
65911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
66911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->in_use = true;
67911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTED;
68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->handle = HCI_INVALID_HANDLE;
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_flush_tout = 0xFFFF;
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->l2c_lcb_timer = alarm_new("l2c_lcb.l2c_lcb_timer");
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->info_resp_timer = alarm_new("l2c_lcb.info_resp_timer");
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->idle_timeout = l2cb.idle_timeout;
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->id = 1; /* spec does not allow '0' */
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->is_bonding = is_bonding;
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->transport = transport;
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->tx_data_len =
77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          controller_get_interface()->get_ble_default_data_packet_length();
78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (transport == BT_TRANSPORT_LE) {
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.num_ble_links_active++;
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_ble_link_adjust_allocation();
83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.num_links_active++;
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_link_adjust_allocation();
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
871a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#if (L2CAP_UCD_INCLUDED == TRUE)
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->ucd_out_sec_pending_q = fixed_queue_new(SIZE_MAX);
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->ucd_in_sec_pending_q = fixed_queue_new(SIZE_MAX);
901a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#endif
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_xmit_data_q = list_new(NULL);
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free LCB found */
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
101ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
102ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_update_lcb_4_bonding
103ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
104ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Mark the lcb for bonding. Used when bonding takes place on
105ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  an existing ACL connection.  (Pre-Lisbon devices)
106ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
107ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing
108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_update_lcb_4_bonding(BD_ADDR p_bd_addr, bool is_bonding) {
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) {
114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("l2cu_update_lcb_4_bonding  BDA: %08x%04x is_bonding: %d",
115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      (p_bd_addr[0] << 24) + (p_bd_addr[1] << 16) +
116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          (p_bd_addr[2] << 8) + p_bd_addr[3],
117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      (p_bd_addr[4] << 8) + p_bd_addr[5], is_bonding);
118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->is_bonding = is_bonding;
119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
123ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
124ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_lcb
125ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
126ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Release an LCB. All timers will be stopped and freed,
127ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  channels dropped, buffers returned etc.
128ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
129ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_lcb(tL2C_LCB* p_lcb) {
133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->in_use = false;
136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->is_bonding = false;
1375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Stop and free timers */
139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_lcb->l2c_lcb_timer);
140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->l2c_lcb_timer = NULL;
141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_lcb->info_resp_timer);
142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->info_resp_timer = NULL;
1435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release any unfinished L2CAP packet on this link */
145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free_and_reset((void**)&p_lcb->p_hcit_rcv_acl);
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
147d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_BR_EDR) /* Release all SCO links */
149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_remove_sco_links(p_lcb->remote_bd_addr);
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->sent_not_acked > 0) {
153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_LE) {
154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.controller_xmit_window += p_lcb->sent_not_acked;
160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
16398657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach    }
164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16598657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach
166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Reset BLE connecting flag only if the address matches
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!memcmp(l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN))
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.is_ble_connecting = false;
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_process_fixed_disc_cback(p_lcb);
1725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Ensure no CCBs left on this LCB */
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       p_ccb = p_lcb->ccb_queue.p_first_ccb) {
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_ccb(p_ccb);
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Tell BTM Acl management the link was removed */
181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb->link_state == LST_CONNECTED) ||
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_DISCONNECTING))
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport);
184ef92b534112a5df57de11ef45f5174f75d44b355Andre Eisenbach
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release any held buffers */
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_xmit_data_q) {
187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!list_is_empty(p_lcb->link_xmit_data_q)) {
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BT_HDR* p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q));
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      list_remove(p_lcb->link_xmit_data_q, p_buf);
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
1916c303aeca25783453333172d0b29e5472f1b1c93Chris Manton    }
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    list_free(p_lcb->link_xmit_data_q);
193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->link_xmit_data_q = NULL;
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* clean up any security pending UCD */
198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_ucd_delete_sec_pending_q(p_lcb);
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Re-adjust flow control windows make sure it does not go negative */
202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.num_ble_links_active >= 1) l2cb.num_ble_links_active--;
2045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_ble_link_adjust_allocation();
206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.num_links_active >= 1) l2cb.num_links_active--;
20892ac2d8919f8e38a091903270eb5500073d67d4bMudumba Ananth
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_link_adjust_allocation();
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check for ping outstanding */
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->p_echo_rsp_cb) {
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2CA_ECHO_RSP_CB* p_cb = p_lcb->p_echo_rsp_cb;
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Zero out the callback in case app immediately calls us again */
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_echo_rsp_cb = NULL;
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_cb)(L2CAP_PING_RESULT_NO_LINK);
220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2215e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar
222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check and release all the LE COC connections waiting for security */
223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->le_sec_pending_q) {
224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      tL2CAP_SEC_DATA* p_buf =
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (tL2CAP_SEC_DATA*)fixed_queue_try_dequeue(p_lcb->le_sec_pending_q);
227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf->p_callback)
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport,
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          p_buf->p_ref_data, BTM_DEV_RESET);
230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
2315e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar    }
232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->le_sec_pending_q = NULL;
234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
238ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
239ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_bd_addr
240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
241ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
242ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  remote BD address.
243ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
244ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched LCB, or NULL if no match
245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
247911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_bd_addr(BD_ADDR p_bd_addr, tBT_TRANSPORT transport) {
248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && p_lcb->transport == transport &&
253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (!memcmp(p_lcb->remote_bd_addr, p_bd_addr, BD_ADDR_LEN))) {
254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
2555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
2605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
263ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
264ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_conn_role
265ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
266ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Determine the desired role (master or slave) of a link.
267ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If already got a slave link, this one must be a master. If
2689ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  already got at least 1 link where we are the master, make
2699ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  this also a master.
270ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
271ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          HCI_ROLE_MASTER or HCI_ROLE_SLAVE
272ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
273ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_conn_role(tL2C_LCB* p_this_lcb) { return l2cb.desire_role; }
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
277ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
278ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2c_is_cmd_rejected
279ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
280ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Checks if cmd_code is command or response
281ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If a command it will be rejected per spec.
2829ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  This function is used when a illegal packet length is
2839ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  detected.
284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          bool    - true if cmd_code is a command and it is rejected,
286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                            false if response code. (command not rejected)
287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t id, tL2C_LCB* p_lcb) {
290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  switch (cmd_code) {
2918fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_CONN_REQ:
2928fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_CONFIG_REQ:
2938fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_DISC_REQ:
2948fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_ECHO_REQ:
2958fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_INFO_REQ:
2968fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_AMP_CONN_REQ:
2978fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_AMP_MOVE_REQ:
2988fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_BLE_UPDATE_REQ:
299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id,
300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                L2CAP_DEFAULT_MTU, 0);
301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("Dumping first Command (%d)", cmd_code);
302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return true;
3038fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    default: /* Otherwise a response */
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3078fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta}
3088fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
3098fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/*******************************************************************************
310ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
311ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_build_header
312ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
313ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Builds the L2CAP command packet header
314ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
315ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to allocated packet or NULL if no resources
316ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
317ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
318911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd,
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          uint8_t id) {
320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE);
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
3225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset = L2CAP_SEND_CMD_OFFSET;
324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len =
325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
3275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in HCI header - handle + pkt boundary */
329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                          << L2CAP_PKT_TYPE_SHIFT)));
332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_lcb->handle | l2cb.non_flushable_pbf);
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
3385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len + L2CAP_CMD_OVERHEAD);
343cccf02fadb2dd4dceb22f2d58ed5840b0ef1860eChris Manton
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_BLE_SIGNALLING_CID);
346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP command header */
351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, cmd);
352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, id);
353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len);
3545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_buf);
3565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_adj_id
361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Checks for valid ID based on specified mask
363ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  and adjusts the id if invalid.
364ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
365ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
366ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
367ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adj_id(tL2C_LCB* p_lcb, uint8_t adj_mask) {
369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->id++;
371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_cmd_reject
377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "command reject" message
379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
383ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_cmd_reject(tL2C_LCB* p_lcb, uint16_t reason, uint8_t rem_id,
385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               uint16_t p1, uint16_t p2) {
386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t param_len;
387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP packet header */
391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED)
392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 2;
393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (reason == L2CAP_CMD_REJ_INVALID_CID)
394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 4;
395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 0;
3975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_CMD_REJECT_LEN + param_len),
399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_REJECT, rem_id);
400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer cmd_rej");
402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, reason);
4095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (param_len >= 2) UINT16_TO_STREAM(p, p1);
4115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (param_len >= 4) UINT16_TO_STREAM(p, p2);
4135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
4155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
418ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
419ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_connect_req
420ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
421ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection request" message
422ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
423ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
424ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
425ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
426ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_req(tL2C_CCB* p_ccb) {
428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
4345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
4365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_REQ_LEN,
438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONN_REQ, p_ccb->local_id);
439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
454ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
455ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_connect_rsp
456ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
457ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection response" message
458ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
459ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
460ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
461ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
462ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_rsp(tL2C_CCB* p_ccb, uint16_t result,
464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t status) {
465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (result == L2CAP_CONN_PENDING) {
469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if we already sent pending response */
470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->flags & CCB_FLAG_SENT_PENDING)
471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->flags |= CCB_FLAG_SENT_PENDING;
474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN,
477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONN_RSP, p_ccb->remote_id);
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_rsp");
480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, status);
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
495ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
496ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_reject_connection
497ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
498ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection response neg" message
499ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer. This function is called when there is no peer
500ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB (non-existant PSM or no resources).
501ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
502ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
503ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
504ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid,
506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            uint8_t rem_id, uint16_t result) {
507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf =
511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id);
512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
5195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, remote_cid);
522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Status of 0      */
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_req
531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration request" message
533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t cfg_len = 0;
541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present)
550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present)
552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present)
554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present)
556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcs_present)
558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present)
560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb,
563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            (uint16_t)(L2CAP_CONFIG_REQ_LEN + cfg_len),
564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONFIG_REQ, p_ccb->local_id);
565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_cfg->flags); /* Flags (continuation) */
575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the options */
577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->mtu);
581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->flush_to);
586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.service_type);
592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.latency);
596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.mode);
602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.rtrans_tout);
605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mon_tout);
606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mps);
607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcs_present) {
610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCS);
611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCS_OPTION_LEN);
612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcs);
613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present) {
616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
6275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
630ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
631ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_rsp
632ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
633ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration response" message
634ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
635ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
636ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
637ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
638ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t cfg_len = 0;
642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
645911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present)
646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present)
648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present)
650911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present)
652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present)
654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb,
657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            (uint16_t)(L2CAP_CONFIG_RSP_LEN + cfg_len),
658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id);
659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p,
669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                   p_cfg->flags); /* Flags (continuation) Must match request */
670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_cfg->result);
671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the options */
673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->mtu);
677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->flush_to);
682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.service_type);
688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.latency);
692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.mode);
698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.rtrans_tout);
701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.mon_tout);
702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mps);
703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present) {
706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
7175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
720ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
721ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_rej
722ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
723ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration reject" message
724ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
725ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
726ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
727ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
728ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data,
730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               uint16_t data_len, uint16_t rej_len) {
731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len, cfg_len, buf_space, len1;
732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t *p, *p_hci_len, *p_data_end;
733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t cfg_code;
7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d",
736911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    data_len, rej_len);
7378fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len1 = 0xFFFF - len;
741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (rej_len > len1) {
742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7468fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf = (BT_HDR*)osi_malloc(len + rej_len);
748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset = L2CAP_SEND_CMD_OFFSET;
749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
7505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Put in HCI header - handle + pkt boundary */
7525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures())) {
754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 << L2CAP_PKT_TYPE_SHIFT)));
756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
7575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Remember the HCI header length position, and save space for it */
764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_hci_len = p;
765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p += 2;
766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP packet header */
768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP command header */
772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, L2CAP_CMD_CONFIG_RSP);
773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, p_ccb->remote_id);
774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CONFIG_RSP_LEN + rej_len);
776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Flags = 0 (no continuation) */
779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CFG_UNKNOWN_OPTIONS);
780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  buf_space = rej_len;
782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the rejected options */
784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_data_end = p_data + data_len;
785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (p_data < p_data_end) {
786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_code = *p_data;
787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len = *(p_data + 1);
788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    switch (cfg_code & 0x7F) {
790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* skip known options */
791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_MTU:
792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_FLUSH_TOUT:
793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_QOS:
794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* unknown options; copy into rsp if not hints */
798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      default:
799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* sanity check option length */
800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if ((cfg_code & 0x80) == 0) {
802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            } else {
807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_data = p_data_end; /* force loop exit */
809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            }
811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* bad length; force loop exit */
815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_data = p_data_end;
8175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
8195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len = (uint16_t)(p - p_hci_len - 2);
823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p_hci_len, len);
8245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len = len + 4;
8265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d", len,
828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
8298fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
8315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
834ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
835ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_disc_req
836ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
837ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "disconnect request" message
838ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
839ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
840ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
841ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
842ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_req(tL2C_CCB* p_ccb) {
844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR *p_buf, *p_buf2;
845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb) || (p_ccb->p_lcb == NULL)) {
848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s L2CAP - ccb or lcb invalid", __func__);
849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
851bf955cb7e50e1047452e741effa504c8aefc8a4fvenkata Jagadeesh
852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
8555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
8575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN,
859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_DISC_REQ, p_ccb->local_id);
860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_req");
862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
8675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
8705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Move all queued data packets to the LCB. In FCR mode, assume the higher
872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     layer checks that all buffers are sent before disconnecting.
873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while ((p_buf2 = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) !=
876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           NULL) {
877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_set_acl_hci_header(p_buf2, p_ccb);
878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_check_send_pkts(p_ccb->p_lcb, p_ccb, p_buf2);
8795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
8835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
886ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
887ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_disc_rsp
888ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
889ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "disconnect response" message
890ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
891ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
892ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  This function is passed the parameters for the disconnect
893ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  response instead of the CCB address, as it may be called
894ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to send a disconnect response when there is no CCB.
895ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
896ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
897ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
898ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t local_cid, uint16_t remote_cid) {
901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
9035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
904911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP,
905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            remote_id);
906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
907911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_rsp");
908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
9135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, local_cid);
915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, remote_cid);
9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
921ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
922ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_echo_req
923ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
924ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "echo request" message
925ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer. Note that we do not currently allow
926ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  data in the echo request.
927ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
928ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
929ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
930ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_req(tL2C_LCB* p_lcb, uint8_t* p_data,
932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t data_len) {
933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
9355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
936911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
9385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_REQ_LEN + data_len),
940911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_ECHO_REQ, p_lcb->id);
941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_req");
943911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
944911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
946911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
9485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len) {
950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ARRAY_TO_STREAM(p, p_data, data_len);
951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
9545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
957ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
958ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_echo_rsp
959ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
960ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "echo response" message
961ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
962ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
963ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
964ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
965ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data,
967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t data_len) {
968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t maxlen;
971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Filter out duplicate IDs or if available buffers are low (intruder
972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * checking) */
973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!id || id == p_lcb->cur_echo_id) {
974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Dump this request since it is illegal */
975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP ignoring duplicate echo request (%d)", id);
976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->cur_echo_id = id;
979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t acl_data_size =
981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      controller_get_interface()->get_acl_data_size_classic();
982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t acl_packet_size =
983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      controller_get_interface()->get_acl_packet_size_classic();
984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Don't return data if it does not fit in ACL and L2CAP MTU */
985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size)
986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               ? acl_data_size
987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               : (uint16_t)L2CAP_CMD_BUF_SIZE;
988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  maxlen -=
989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (uint16_t)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len > maxlen) data_len = 0;
993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len),
995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_ECHO_RSP, id);
996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_rsp");
998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len) {
1005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ARRAY_TO_STREAM(p, p_data, data_len);
1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
10095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1012ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1013ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_info_req
1014ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1015ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "info request" message
1016ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
1017ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1018ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1019ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) {
1021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
1022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
10235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* check for wrap and/or BRCM ID */
1025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
1026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
10275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id);
1029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for info_req");
1031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_EVENT("l2cu_send_peer_info_req: type 0x%04x", info_type);
10355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
10385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, info_type);
10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->w4_info_rsp = true;
1042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_set_on_queue(p_lcb->info_resp_timer, L2CAP_WAIT_INFO_RSP_TIMEOUT_MS,
1043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     l2c_info_resp_timer_timeout, p_lcb,
1044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     btu_general_alarm_queue);
10455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
10475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1050ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1051ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_info_rsp
1052ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1053ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "info response" message
1054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
1055ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1056ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1057ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1058ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
1060911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t info_type) {
1061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
1062911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
1063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len = L2CAP_INFO_RSP_LEN;
10645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1066911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.test_info_resp &
1068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1069911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1070911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)))
10725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (L2CAP_EXTFEA_SUPPORTED_MASK &
1075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
10785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
1080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id);
1088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for info_rsp");
1090911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
10955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, info_type);
10975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.test_info_resp &
1101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)))
11035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (L2CAP_EXTFEA_SUPPORTED_MASK &
1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
11085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
1110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_LE) {
1112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* optional data are not added for now */
1113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, L2CAP_BLE_EXTFEA_MASK);
1114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1115d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, l2cb.test_info_resp);
11175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
11185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
1119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p,
1120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
11215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, L2CAP_EXTFEA_SUPPORTED_MASK);
11235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    memset(p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
11295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
11315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION)
1133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
11345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      int xx;
1138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
1140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Skip fixed channels not used on BR/EDR-ACL link */
1141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((xx >= L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL) &&
1142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            (xx <= L2CAP_SMP_CID - L2CAP_FIRST_FIXED_CHNL))
1143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
1144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL)
1146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |=
1147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
11495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
1151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_UCD_MTU);
1154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
1156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
11605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1163ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1164ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_enqueue_ccb
1165ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1166ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      queue CCB by priority. The first CCB is highest priority and
1167ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is served at first. The CCB is queued to an LLCB or an LCB.
1168ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1169ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
1170ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1171ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_enqueue_ccb(tL2C_CCB* p_ccb) {
1173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb1;
1174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB_Q* p_q = NULL;
11755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find out which queue the channel is on
1177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
1178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
11795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb->in_use) || (p_q == NULL)) {
1181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_enqueue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x",
1183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_enqueue_ccb CID: 0x%04x  priority: %d",
1188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->local_cid, p_ccb->ccb_priority);
11895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the queue is empty, we go at the front */
1191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_q->p_first_ccb) {
1192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb1 = p_q->p_first_ccb;
1196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (p_ccb1 != NULL) {
1198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Insert new ccb at the end of the same priority. Lower number, higher
1199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * priority */
1200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Are we at the head of the queue ? */
1202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb1 == p_q->p_first_ccb)
1203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_q->p_first_ccb = p_ccb;
1204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else
1205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
12065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_next_ccb = p_ccb1;
1208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb1->p_prev_ccb = p_ccb;
1210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
1211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb1 = p_ccb1->p_next_ccb;
1214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
12155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If we are lower then anyone in the list, we go at the end */
1217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_ccb1) {
1218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* add new ccb at the end of the list */
1219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb->p_next_ccb = p_ccb;
12205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_next_ccb = NULL;
1222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_prev_ccb = p_q->p_last_ccb;
1223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb = p_ccb;
12245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Adding CCB into round robin service table of its LCB */
1229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) {
1230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if this is the first channel in this priority group */
1231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Set the first channel to this CCB */
1233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Set the next serving channel in this group to this CCB */
1235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Initialize quota of this priority group based on its priority */
1237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* increase number of channels in this group */
1241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
12445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_dequeue_ccb
1249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      dequeue CCB from a queue
1251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          -
1253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_dequeue_ccb(tL2C_CCB* p_ccb) {
1256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB_Q* p_q = NULL;
12575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_dequeue_ccb  CID: 0x%04x", p_ccb->local_cid);
12595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find out which queue the channel is on
1261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
1262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
12635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL)) {
1265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_dequeue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x  p_q: "
1267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "0x%08x  p_q->p_first_ccb: 0x%08x",
1268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q,
1269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_q ? p_q->p_first_ccb : 0);
1270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Removing CCB from round robin service table of its LCB */
1275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) {
1276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* decrease number of channels in this priority group */
1277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if it was the last channel in the priority group */
1280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if it is the first channel of this group */
1285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb) {
1286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb =
1287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_next_ccb;
1288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if it is the next serving channel of this group */
1290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb) {
1291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* simply, start serving from the first channel */
1292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb =
1293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
12985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == p_q->p_first_ccb) {
1300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We are removing the first in a queue */
1301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_first_ccb = p_ccb->p_next_ccb;
13025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_q->p_first_ccb)
1304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_first_ccb->p_prev_ccb = NULL;
13055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
1306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb = NULL;
1307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (p_ccb == p_q->p_last_ccb) {
1308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We are removing the last in a queue */
1309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_last_ccb = p_ccb->p_prev_ccb;
1310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_last_ccb->p_next_ccb = NULL;
1311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* In the middle of a chain. */
1313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
13185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1321ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1322ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_change_pri_ccb
1323ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1324ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description
1325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          -
1327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1328ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_change_pri_ccb(tL2C_CCB* p_ccb, tL2CAP_CHNL_PRIORITY priority) {
1330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->ccb_priority != priority) {
1331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If CCB is not the only guy on the queue */
1332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL)) {
1333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("Update CCB list in logical link");
13345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Remove CCB from queue and re-queue it at new priority */
1336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_dequeue_ccb(p_ccb);
13375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ccb_priority = priority;
1339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_enqueue_ccb(p_ccb);
1340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
13415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If CCB is the only guy on the queue, no need to re-enqueue */
1344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* update only round robin service data */
1345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ccb_priority = priority;
1350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
13565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
1358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1363ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_ccb
1364ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1365ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function allocates a Channel Control Block and
1366ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  attaches it to a link control block. The local CID
1367ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is also assigned.
1368ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1369ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB, or NULL if none
1370ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1371ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1372911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid) {
1373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_prev;
13755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x", cid);
13775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cb.p_free_ccb_first) return (NULL);
13795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If a CID was passed in, use that, else take the first free one */
1381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cid == 0) {
1382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.p_free_ccb_first;
1383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_prev = NULL;
13865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
13885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == l2cb.p_free_ccb_first)
1390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL;
1393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           p_prev = p_prev->p_next_ccb) {
1394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_prev->p_next_ccb == p_ccb) {
1395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_prev->p_next_ccb = p_ccb->p_next_ccb;
13965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb == l2cb.p_free_ccb_last) l2cb.p_free_ccb_last = p_prev;
13985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
1400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
1401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_prev == NULL) {
1403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR(
1404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free "
1405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "list",
1406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            cid);
1407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return NULL;
1408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->in_use = true;
1415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Get a CID for the connection */
1417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_cid = L2CAP_BASE_APPL_CID + (uint16_t)(p_ccb - l2cb.ccb_pool);
1418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb = p_lcb;
1420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_rcb = NULL;
1421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->should_free_rcb = false;
1422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) l2cu_enqueue_ccb(p_ccb);
1427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* clear what peer wants to configure */
1429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->peer_cfg_bits = 0;
1430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in default values for configuration */
1432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in default values for local/peer configurations */
1436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type =
1439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_SERV_TYPE;
1440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate =
1441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_TOKEN_RATE;
1442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size =
1443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_BUCKET_SIZE;
1444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth =
1445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_PEAK_BANDWIDTH;
1446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency =
1447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_LATENCY;
1448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation =
1449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_DELAY;
1450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->bypass_fcs = 0;
1452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->peer_cfg_already_rejected = false;
1454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->fcrb.ack_timer);
1457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.ack_timer = alarm_new("l2c_fcrb.ack_timer");
1458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /*  CSP408639 Fix: When L2CAP send amp move channel request or receive
1460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    * request -> Stop retrans/monitor timer -> Change channel state to
1462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * CST_AMP_MOVING. */
1463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->fcrb.mon_retrans_timer);
1464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.mon_retrans_timer = alarm_new("l2c_fcrb.mon_retrans_timer");
1465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.preferred_mode =
1467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.allowed_modes =
1469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */
1470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->cong_sent = false;
1483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->buff_quota = 2; /* This gets set after config */
1484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If CCB was reserved Config_Done can already have some value */
1486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cid == 0)
1487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->config_done = 0;
1488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
1489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid,
1490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_ccb->config_done);
1491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->chnl_state = CST_CLOSED;
1494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->flags = 0;
1495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
14975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = false;
15005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
15015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->l2c_ccb_timer);
1503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->l2c_ccb_timer = alarm_new("l2c.l2c_ccb_timer");
15045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_adjust_chnl_allocation();
15065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb);
15085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_start_post_bond_timer
1513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function starts the ACL Link inactivity timer after
1515ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  dedicated bonding
1516ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  This timer can be longer than the normal link inactivity
1517ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  timer for some platforms.
1518ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
15199ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns          bool  - true if idle timer started or disconnect initiated
15209ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                          false if there's one or more pending CCB's exist
1521ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1522ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_start_post_bond_timer(uint16_t handle) {
1524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
15255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) return (true);
15275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->is_bonding = false;
15295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Only start timer if no control blocks allocated */
1531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->ccb_queue.p_first_ccb != NULL) return (false);
15325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no channels on the connection, start idle timeout */
1534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb->link_state == LST_CONNECTED) ||
1535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_CONNECTING) ||
1536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_DISCONNECTING)) {
1537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    period_ms_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000;
153878bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov
1539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->idle_timeout == 0) {
1540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
1541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
1542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
15435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
1545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       p_lcb, btu_general_alarm_queue);
1546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (true);
1547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (false);
15505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1553ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1554ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_ccb
1555ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1556ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function releases a Channel Control Block. The timer
15579ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  is stopped, any attached buffers freed, and the CCB is
15589ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  removed from the link control block.
1559ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1560ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1561ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1562ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_ccb(tL2C_CCB* p_ccb) {
1564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = p_ccb->p_lcb;
1565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = p_ccb->p_rcb;
15665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_release_ccb: cid 0x%04x  in_use: %u",
1568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->local_cid, p_ccb->in_use);
15695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If already released, could be race condition */
1571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb->in_use) return;
15725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_sec_clr_service_by_psm(p_rcb->psm);
1575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1576ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->should_free_rcb) {
1578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_rcb);
1579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_rcb = NULL;
1580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->should_free_rcb = false;
1581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1582a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
1583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btm_sec_clr_temp_auth_service(p_lcb->remote_bd_addr);
1584ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Free the timer */
1586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->l2c_ccb_timer);
1587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->l2c_ccb_timer = NULL;
15885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fixed_queue_free(p_ccb->xmit_hold_q, osi_free);
1590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->xmit_hold_q = NULL;
15915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_cleanup(p_ccb);
15935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Channel may not be assigned to any LCB if it was just pre-reserved */
1595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
15965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
1597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
15985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      )) {
1600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_dequeue_ccb(p_ccb);
1601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Delink the CCB from the LCB */
1603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb = NULL;
1604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put the CCB back on the free pool */
1607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cb.p_free_ccb_first) {
1608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_first = p_ccb;
1609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last = p_ccb;
1610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = NULL;
1611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb = NULL;
1612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = NULL;
1614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last = p_ccb;
1617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Flag as not in use */
1620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->in_use = false;
1621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no channels on the connection, start idle timeout */
1623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->ccb_queue.p_first_ccb) {
16257c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      // Closing a security channel on LE device should not start connection
16267c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      // timeout
16277c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      if (p_lcb->transport == BT_TRANSPORT_LE &&
16287c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski          p_ccb->local_cid == L2CAP_SMP_CID)
16297c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski        return;
16307c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski
1631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_no_dynamic_ccbs(p_lcb);
1632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Link is still active, adjust channel quotas. */
1634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_adjust_chnl_allocation();
16355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1640ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1641ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ccb_by_remote_cid
1642ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1643ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active CCBs on a link for a match based
1644ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on the remote CID.
1645ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1646ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched CCB, or NULL if no match
1647ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1648ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1649911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_remote_cid(tL2C_LCB* p_lcb, uint16_t remote_cid) {
1650911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
16515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If LCB is NULL, look through all active links */
1653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) {
1654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return NULL;
1655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) return (p_ccb);
1658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
16625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1665ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1666ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_rcb
1667ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1668ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the Registration Control Blocks for a free
1669ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  one.
1670ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1671ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the RCB or NULL if not found
1672ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1673ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1674911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_rcb(uint16_t psm) {
1675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
16775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_rcb->in_use) {
1680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->in_use = true;
1681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->psm = psm;
16825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
1683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
16845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_rcb);
16865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free RCB found */
1690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
16915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16936721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
1694ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1695ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_ble_rcb
1696ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1697ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the BLE Registration Control Blocks for a free
1698ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  one.
1699ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1700ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the BLE RCB or NULL if not found
1701ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1702ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1703911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm) {
1704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
17066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_rcb->in_use) {
1709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->in_use = true;
1710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->psm = psm;
17116721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#if (L2CAP_UCD_INCLUDED == TRUE)
1712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
17136721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#endif
1714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_rcb);
17156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
1716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17176721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free RCB found */
1719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17206721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
17215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1723ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1724ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_rcb
1725ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1726ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Mark an RCB as no longet in use
1727ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1728ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1729ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1730ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_rcb(tL2C_RCB* p_rcb) {
1732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->in_use = false;
1733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->psm = 0;
17345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_disconnect_chnl
1739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Disconnect a channel. Typically, this is due to either
17419ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  receiving a bad configuration,  bad packet or max_retries
17429ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  expiring.
1743ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1744ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_disconnect_chnl(tL2C_CCB* p_ccb) {
1746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t local_cid = p_ccb->local_cid;
17475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (local_cid >= L2CAP_BASE_APPL_CID) {
1749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2CA_DISCONNECT_IND_CB* p_disc_cb =
1750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
17515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
17535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_send_peer_disc_req(p_ccb);
17555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_ccb(p_ccb);
17575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_disc_cb)(local_cid, false);
1759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* failure on the AMP channel, probably need to disconnect ACL */
1761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
17645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1766ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1767ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_rcb_by_psm
1768ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1769ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the Registration Control Blocks to see if
1770ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  anyone registered to handle the PSM in question
1771ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1772ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the RCB or NULL if not found
1773ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1774ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1775911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm) {
1776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
17785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17876721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
1788ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ble_rcb_by_psm
1790ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1791ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the BLE Registration Control Blocks to see if
1792ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  anyone registered to handle the PSM in question
1793ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1794ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the BLE RCB or NULL if not found
1795ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1796ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1797911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm) {
1798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
18006721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18046721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
18076721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
18085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1810ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1811ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_peer_cfg_req
1812ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
18139ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when the peer sends us a "config
18149ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  request" message. It extracts the configuration of interest
18159ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
1816ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
18179ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  Note:  Negotiation of the FCR channel type is handled
18189ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                         internally, all others are passed to the upper layer.
1819ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1820ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          uint8_t - L2CAP_PEER_CFG_OK if passed to upper layer,
18219ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                            L2CAP_PEER_CFG_UNACCEPTABLE if automatically
18229ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      responded to because parameters are
18239ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      unnacceptable from a specification point
18249ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      of view.
18259ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                            L2CAP_PEER_CFG_DISCONNECT if no compatible channel
18269ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      modes between the two devices, and shall
18279ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      be closed.
1828ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1829ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool mtu_ok = true;
1832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool qos_type_ok = true;
1833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool flush_to_ok = true;
1834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool fcr_ok = true;
1835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t fcr_status;
1836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Ignore FCR parameters for basic mode */
1838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_cfg->fcr_present) p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the MTU that our peer can receive */
1841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
1842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Make sure MTU is at least the minimum */
1843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* In basic mode, limit the MTU to our buffer size */
1845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_cfg->fcr_present == false) && (p_cfg->mtu > L2CAP_MTU_SIZE))
1846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->mtu = L2CAP_MTU_SIZE;
1847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Save the accepted value in case of renegotiation */
1849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.mtu = p_cfg->mtu;
1850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.mtu_present = true;
1851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Illegal MTU value */
1853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {
1854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->mtu = L2CAP_MIN_MTU;
1855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      mtu_ok = false;
1856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload mtu from a previously accepted config request */
1859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.mtu_present) {
1860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu_present = true;
1861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu = p_ccb->peer_cfg.mtu;
1862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify that the flush timeout is a valid value (0 is illegal) */
1865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
1866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_cfg->flush_to) {
1867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      flush_to_ok = false;
1869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Save the accepted value in case of renegotiation */
1870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {
1871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.flush_to_present = true;
1872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload flush_to from a previously accepted config request */
1877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.flush_to_present) {
1878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->flush_to_present = true;
1879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the QOS settings the the peer is using */
1883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
1884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Make sure service type is not a reserved value; otherwise let upper
1885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       layer decide if acceptable
1886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    */
1887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->qos.service_type <= GUARANTEED) {
1888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.qos = p_cfg->qos;
1889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.qos_present = true;
1890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
1891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Illegal service type value */
18925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->qos.service_type = BEST_EFFORT;
1894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      qos_type_ok = false;
18955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload QOS from a previously accepted config request */
1898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.qos_present) {
1899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos_present = true;
1900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos = p_ccb->peer_cfg.qos;
1901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fcr_status = l2c_fcr_process_peer_cfg_req(p_ccb, p_cfg);
1904911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fcr_status == L2CAP_PEER_CFG_DISCONNECT) {
1905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Notify caller to disconnect the channel (incompatible modes) */
1906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1907911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
19085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_DISCONNECT);
1910911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
19135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return any unacceptable parameters */
1915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
1916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_adjust_out_mps(p_ccb);
1917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_OK);
1918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
19205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (mtu_ok) p_cfg->mtu_present = false;
1922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (flush_to_ok) p_cfg->flush_to_present = false;
1923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (qos_type_ok) p_cfg->qos_present = false;
1924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (fcr_ok) p_cfg->fcr_present = false;
19255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_UNACCEPTABLE);
1927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1931ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1932ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_peer_cfg_rsp
1933ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
19349ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when the peer sends us a "config
19359ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  response" message. It extracts the configuration of interest
19369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
1937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1938ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we wanted QoS and the peer sends us a positive response with QoS, use
1943911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * his values */
1944911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->qos_present) && (p_ccb->our_cfg.qos_present))
1945911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos = p_cfg->qos;
19465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
1948911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Save the retransmission and monitor timeout values */
1949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
1950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
1951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
1952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
19535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Calculate the max number of packets for which we can delay sending an ack
1955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
1956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz)
1957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
1958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
1959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
19605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
1962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, "
1963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "max_held_acks: %d",
1964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz,
1965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->fcrb.max_held_acks);
1966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1970ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1971ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_our_cfg_req
1972ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1973ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when we send a "config request"
1974ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  message. It extracts the configuration of interest and saves
1975ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  it in the CCB.
1976ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1977ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1978ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1979ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t hci_flush_to;
1983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the QOS settings we are using for transmit */
1985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
1986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos_present = true;
1987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos = p_cfg->qos;
1988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
1991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Override FCR options if attempting streaming or basic */
1992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE)
1993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
1994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* On BR/EDR, timer values are zero in config request */
1996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* On class 2 AMP, timer value in config request shall be non-0 processing
1997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * time */
1998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*                 timer value in config response shall be greater than
1999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * received processing time */
2000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE)
2003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
2005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Set the threshold to send acks (may be updated in the cfg response) */
2007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Include FCS option only if peer can handle it */
2010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* FCS check can be bypassed if peer also desires to bypass */
2012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS)
2013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else
2015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcs_present = false;
2016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check the flush timeout. If it is lower than the current one used */
2024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* then we need to adjust the flush timeout sent to the controller   */
2025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
2026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_cfg->flush_to == 0) ||
2027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* don't send invalid flush timeout */
2029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* SPEC: The sender of the Request shall specify its flush timeout value
2030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
2031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*       if it differs from the default value of 0xFFFF */
2032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->flush_to_present = false;
2033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
2034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb = p_ccb->p_lcb;
20365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_flush_tout = p_cfg->flush_to;
20395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* If the timeout is within range of HCI, set the flush timeout */
2041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* Convert flush timeout to 0.625 ms units, with round */
2043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          btsnd_hcic_write_auto_flush_tout(p_lcb->handle, hci_flush_to);
20455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
20475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2048911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
20495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2052ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2053ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_our_cfg_rsp
2054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
20559ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when we send the peer a "config
20569ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  response" message. It extracts the configuration of interest
20579ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
2058ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2059ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2060ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2061ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2062911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
2063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If peer wants QoS, we are allowed to change the values in a positive
2064911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * response */
2065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present))
2066911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->peer_cfg.qos = p_cfg->qos;
2067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos_present = false;
20695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2070911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_adj_our_rsp_options(p_ccb, p_cfg);
20715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2074ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2075ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_device_reset
2076ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2077ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when reset of the device is
2078ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  completed.  For all active connection simulate HCI_DISC
2079ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2080ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2081ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2082ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_device_reset(void) {
2084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
20865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_hci_disc_comp(p_lcb->handle, (uint8_t)-1);
20905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cb.is_ble_connecting = false;
20935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2096ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_create_conn
2098ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2099ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function initiates an acl connection via HCI
2100ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2101ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if successful, false if get buffer fails.
2102ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2103ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport) {
210596fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
210696fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  return l2cu_create_conn(p_lcb, transport, phy);
210796fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski}
210896fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski
210996fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowskibool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
211096fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski                      uint8_t initiating_phys) {
2111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
2113d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
2114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool is_sco_active;
21155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
21165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_DEVICE_TYPE dev_type;
2118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBLE_ADDR_TYPE addr_type;
21190fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
21210fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (transport == BT_TRANSPORT_LE) {
2123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!controller_get_interface()->supports_ble()) return false;
21240fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->ble_addr_type = addr_type;
2126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->transport = BT_TRANSPORT_LE;
212796fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski    p_lcb->initiating_phys = initiating_phys;
21285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (l2cble_create_conn(p_lcb));
2130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If there is a connection where we perform as a slave, try to switch roles
2133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     for this connection */
2134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       xx++, p_lcb_cur++) {
2136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb_cur == p_lcb) continue;
21375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2139d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
2140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* The LMP_switch_req shall be sent only if the ACL logical transport
2141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      is in active mode, when encryption is disabled, and all synchronous
2142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      logical transports on the same physical link are disabled." */
21435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Check if there is any SCO Active on this BD Address */
2145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
21465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_API(
2148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s",
2149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (is_sco_active == true) ? "true" : "false");
21505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (is_sco_active == true)
2152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        continue; /* No Master Slave switch not allowed when SCO Active */
21535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*4_1_TODO check  if btm_cb.devcb.local_features to be used instead */
2155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* mark this lcb waiting for switch to be completed and
2157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           start switch on the other one */
2158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_role = HCI_ROLE_MASTER;
2160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (BTM_SwitchRole(p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) ==
2162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            BTM_CMD_STARTED) {
2163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          alarm_set_on_queue(
2164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_lcb->l2c_lcb_timer, L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS,
2165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue);
2166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          return (true);
21675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
21695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTING;
21735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (l2cu_create_conn_after_switch(p_lcb));
21755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2178ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2179ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_num_hi_priority
2180ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Gets the number of high priority channels.
2182ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2183ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns
2184ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2185ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_num_hi_priority(void) {
2187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t no_hi = 0;
2188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
21905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      no_hi++;
21945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return no_hi;
21975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2200ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2201ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_create_conn_after_switch
2202ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2203ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function initiates an acl connection via HCI
2204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If switch required to create connection it is already done.
2205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2206ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if successful, false if get buffer fails.
2207ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2208ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
22095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb) {
2211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_INQ_INFO* p_inq_info;
2213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t page_scan_rep_mode;
2214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t page_scan_mode;
2215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t clock_offset;
2216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p_features;
2217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t num_acl = BTM_GetNumAclLinks();
2218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_lcb->remote_bd_addr);
2219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t no_hi_prio_chs = l2cu_get_num_hi_priority();
22205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_features = BTM_ReadLocalFeatures();
22225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG(
2224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* FW team says that we can participant in 4 piconets
2227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * typically 3 piconet + 1 for scanning.
2228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * We can enhance the code to count the number of piconets later. */
2229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (((!l2cb.disallow_switch && (num_acl < 3)) ||
2230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (p_lcb->is_bonding && (no_hi_prio_chs == 0))) &&
2231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      HCI_SWITCH_SUPPORTED(p_features))
2232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
22355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTING;
22375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check with the BT manager if details about remote device are known */
2239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr);
2240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_inq_info != NULL) {
2241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_mode = p_inq_info->results.page_scan_mode;
2243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    clock_offset = (uint16_t)(p_inq_info->results.clock_offset);
2244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No info known. Use default settings */
2246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
22485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btsnd_hcic_create_conn(
2253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->remote_bd_addr, (HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1 |
2254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                              HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3 |
2255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                              HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5),
2256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      page_scan_rep_mode, page_scan_mode, clock_offset, allow_switch);
22575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btm_acl_update_busy_level(BTM_BLI_PAGE_EVT);
22595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS,
2261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue);
2262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
2264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
22655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2267ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2268ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_state
2269ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2270ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
2271ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  LCB state.
2272ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2273ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to first matched LCB, or NULL if no match
2274ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2275ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2276911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state) {
2277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t i;
2278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
22795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
22835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
2287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
22885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
22895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2291ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2292ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_lcb_disconnecting
2293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2294ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      On each active lcb, check if the lcb is in disconnecting
2295ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  state, or if there are no ccb's on the lcb (implying
22965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    idle timeout is running), or if last ccb on the link
22975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    is in disconnecting state.
2298ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2299ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if any of above conditions met, false otherwise
2300ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2301ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_lcb_disconnecting(void) {
2303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t i;
2306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool status = false;
23075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = &l2cb.lcb_pool[0];
23095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->in_use) {
2312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* no ccbs on lcb, or lcb is in disconnecting state */
2313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((!p_lcb->ccb_queue.p_first_ccb) ||
2314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_lcb->link_state == LST_DISCONNECTING)) {
2315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        status = true;
2316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
2317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* only one ccb left on lcb */
2319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb = p_lcb->ccb_queue.p_first_ccb;
2321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->in_use) &&
2323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          status = true;
2326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
23275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
23295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
23325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2335ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_acl_priority
2337ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets the transmission priority for a channel.
2339ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  (For initial implementation only two values are valid.
2340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2341ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2342ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if a valid channel, else false
2343ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2344ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
23455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_set_acl_priority(BD_ADDR bd_addr, uint8_t priority,
2347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           bool reset_after_rs) {
2348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* pp;
2350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t vs_param;
23525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
23545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the link control block for the acl channel */
2356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
2357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
2358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_SetAclPriority");
2359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
2360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
23615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (BTM_IS_BRCM_CONTROLLER()) {
2363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Called from above L2CAP through API; send VSC if changed */
2364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Called because of a master/slave role switch; if high resend VSC */
2366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      pp = command;
23685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH
2370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                   : HCI_BRCM_ACL_PRIORITY_LOW;
23715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(pp, p_lcb->handle);
2373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT8_TO_STREAM(pp, vs_param);
23745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY,
2376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command,
2377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                NULL);
23785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Adjust lmp buffer allocation for this channel if priority changed */
2380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->acl_priority != priority) {
2381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->acl_priority = priority;
2382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_link_adjust_allocation();
2383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
23845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
23875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
23905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
2391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_non_flushable_pbf
2393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2397ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2398ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_non_flushable_pbf(bool is_supported) {
2400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (is_supported)
2401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.non_flushable_pbf =
2402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
24055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
24075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_resubmit_pending_sec_req
2411ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2412ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when required security procedures
2413ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  are completed and any pending requests can be re-submitted.
2414ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2415ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2417ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_resubmit_pending_sec_req(BD_ADDR p_bda) {
2419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_next_ccb;
2422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
24235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_resubmit_pending_sec_req  p_bda: 0x%08x", p_bda);
24255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we are called with a BDA, only resubmit for that BDA */
2427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_bda) {
2428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_BR_EDR);
2429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If we don't have one, this is an error */
2431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb) {
2432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* For all channels, send the event through their FSMs */
2433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_next_ccb = p_ccb->p_next_ccb;
2435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
2438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
24395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No BDA pasesed in, so check all links */
2442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         xx++, p_lcb++) {
2444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->in_use) {
2445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* For all channels, send the event through their FSMs */
2446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_next_ccb = p_ccb->p_next_ccb;
2448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
24495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
24515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
24535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2455d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE)
24565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2457ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2458ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_info_rsp_mask
2459ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2460ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function allows the script wrapper to change the
2461ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  info resp mask for conformance testing.
2462ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2463ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB, or NULL if none
2464ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2465ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_info_rsp_mask(uint32_t mask) { l2cb.test_info_resp = mask; }
2467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif /* L2CAP_CONFORMANCE_TESTING */
24685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_adjust_out_mps
2472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets our MPS based on current controller capabilities
2474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adjust_out_mps(tL2C_CCB* p_ccb) {
2479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t packet_size;
2480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* on the tx side MTU is selected based on packet size of the controller */
2482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  packet_size = btm_get_max_packet_size(p_ccb->p_lcb->remote_bd_addr);
2483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* something is very wrong */
2487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
2488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_adjust_out_mps bad packet size: %u  will use MPS: %u",
2489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        packet_size, p_ccb->peer_cfg.fcr.mps);
2490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We try to negotiate MTU that each packet can be split into whole
2496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    number of max packets.  For example if link is 1.2 max packet size is 339
2497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    bytes.
2498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4
2499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    overhead.
2500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1695, that will be 5 Dh5 packets.  Now maximum L2CAP packet is
2501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1 3DH5
2504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    packet
2505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  */
2506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mps >= packet_size)
2507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
25085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
2509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
25105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
2512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_adjust_out_mps use %d   Based on peer_cfg.fcr.mps: %u  "
2513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "packet_size: %u",
2514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2519ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2520ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_initialize_fixed_ccb
2521ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2522ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Initialize a fixed channel's CCB
2523ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2524ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true or false
2525ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid,
2528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               tL2CAP_FCR_OPTS* p_fcr) {
25295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
2530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we already have a CCB, then simply return */
2533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
2534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_ccb != NULL) && p_ccb->in_use) {
2535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /*
2536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * NOTE: The "in_use" check is needed to ignore leftover entries
2537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * that have been already released by l2cu_release_ccb().
2538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
2539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (true);
2540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_allocate_ccb(NULL, 0);
2543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) return (false);
25445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_cancel(p_lcb->l2c_lcb_timer);
2546ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
2547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set CID for the connection */
2548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_cid = fixed_cid;
2549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->remote_cid = fixed_cid;
25505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = false;
25525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_fcr) {
2554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Set the FCR parameters. For now, we will use default pools */
2555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
25565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
25615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Link ccb to lcb and lcb to ccb */
2566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb = p_lcb;
25685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* There is no configuration, so if the link is up, the channel is up */
2570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_CONNECTED) p_ccb->chnl_state = CST_OPEN;
25715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the default idle timeout value to use */
2573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fixed_chnl_idle_tout =
2574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
25755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
25775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2580ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2581ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_no_dynamic_ccbs
2582ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
25839ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Handles the case when there are no more dynamic CCBs. If
25849ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  there are any fixed CCBs, start the longest of the fixed CCB
25859ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  timeouts, otherwise start the default link idle timeout or
25869ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  disconnect.
2587ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2588ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2589ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2590ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) {
2592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_STATUS rc;
2593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  period_ms_t timeout_ms = p_lcb->idle_timeout * 1000;
2594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool start_timeout = true;
25955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
2597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
25985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->p_fixed_ccbs[xx] != NULL) &&
2601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) {
2602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000;
26035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
26065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the link is pairing, do not mess with the timeouts */
2608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->is_bonding) return;
2609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (timeout_ms == 0) {
2611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
2612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (rc == BTM_CMD_STARTED) {
2616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (rc == BTM_SUCCESS) {
2620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* BTM SEC will make sure that link is release (probably after pairing is
2622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * done) */
2623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      start_timeout = false;
2625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (p_lcb->is_bonding) {
2626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
263078bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov    } else {
2631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* probably no buffer to send disconnect */
2632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = BT_1SEC_TIMEOUT_MS;
26335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (start_timeout) {
2637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %d ms", __func__, timeout_ms);
2638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
2639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       p_lcb, btu_general_alarm_queue);
2640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_cancel(p_lcb->l2c_lcb_timer);
2642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
26445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
26465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2647ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2648ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_fixed_chnl_resp
2649ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      handle a fixed channel response (or lack thereof)
2651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  if the link failed, or a fixed channel response was
2652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  not received, the bitfield is all zeros.
2653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2654ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb) {
2656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* ignore all not assigned BR/EDR channels */
2658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->peer_chnl_mask[0] &=
2659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_FIXED_CHNL_SIG_BIT | L2CAP_FIXED_CHNL_CNCTLESS_BIT |
2660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         L2CAP_FIXED_CHNL_SMP_BR_BIT);
2661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
2662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Tell all registered fixed channels about the connection */
2665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* skip sending LE fix channel callbacks on BR/EDR links */
2667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID)
2670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
2671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] &
2673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->p_fixed_ccbs[xx])
2675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 p_lcb->remote_bd_addr, true, 0,
2678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 p_lcb->transport);
2679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
2680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->disc_reason, p_lcb->transport);
2683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->p_fixed_ccbs[xx]) {
2685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
2686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[xx] = NULL;
26875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
26895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
26925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
26935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26948fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/*******************************************************************************
2695ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2696ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_fixed_disc_cback
2697ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
26989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      send l2cap fixed channel disconnection callback to the
26999ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  application
2700ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2701ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2702ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2703ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb) {
27058fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#if (L2CAP_NUM_FIXED_CHNLS > 0)
27068fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
2707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Select peer channels mask to use depending on transport */
2708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t peer_channel_mask = p_lcb->peer_chnl_mask[0];
2709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // For LE, reset the stored peer channel mask
2711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) p_lcb->peer_chnl_mask[0] = 0;
2712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->p_fixed_ccbs[xx]) {
2715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        tL2C_CCB* p_l2c_chnl_ctrl_block;
2717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->p_fixed_ccbs[xx] = NULL;
2719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->disc_reason, p_lcb->transport);
2723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if ((peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL))) &&
2725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL))
2726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->disc_reason, p_lcb->transport);
2729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27308fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#endif
27318fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta}
27328fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
27335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2734ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_par_req
2736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE parameter update request message
2738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
2739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int,
2744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t max_int, uint16_t latency,
2745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t timeout) {
2746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
27485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
2751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
27525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id);
2755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_req - no buffer");
2757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
27625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, min_int);
2764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, max_int);
2765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, latency);
2766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, timeout);
27675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
27695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
27705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2772ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2773ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_par_rsp
2774ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2775ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE parameter update response message
2776ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
2777ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2778ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2779ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2780ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason,
2782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint8_t rem_id) {
2783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
27855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_UPDATE_RSP, rem_id);
2788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_rsp - no buffer");
2790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
27955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, reason);
27975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
27995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
28005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
28016721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2802ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2803ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_req
2804ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28059ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send a BLE packet to establish LE connection
28069ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  oriented L2CAP channel.
2807ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2808ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2809ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2810ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb) {
2812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
2815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t mtu;
2816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t mps;
2817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t initial_credit;
28186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2819911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
28216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
28256721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
28276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id);
2830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28346721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28376721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  mtu = p_ccb->local_conn_cfg.mtu;
2839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  mps = p_ccb->local_conn_cfg.mps;
2840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  initial_credit = p_ccb->local_conn_cfg.credits;
28416721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG(
2843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                mtu:%d mps:%d initial_credit:%d",
2845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_rcb->real_psm, p_ccb->local_cid, mtu, mps, initial_credit);
28466721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
2848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
2849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, mtu);
2850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, mps);
2851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, initial_credit);
28526721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
28546721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
28556721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
28566721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2857ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2858ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_reject_ble_connection
2859ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28609ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send an L2CAP "Credit based connection res"
28619ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  message to the peer. This function is called for non-success
28629ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  cases.
2863ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2864ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2865ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2866ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_ble_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
2868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t result) {
2869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
28716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id);
2874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_reject_ble_connection - no buffer");
2876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28786721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28816721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
2883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* MTU */
2884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* MPS */
2885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* initial credit */
2886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
28876721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
28896721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
28906721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
28916721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2892ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2893ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_res
2894ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28959ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send an L2CAP "Credit based connection res"
28969ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  message to the peer. This function is called in case of
28979ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  success.
2898ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2899ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2900ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2901ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb,
2903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                              uint16_t result) {
2904911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
29066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2907911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_send_peer_ble_credit_based_conn_res");
2908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf =
2909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2910911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id);
2911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
2913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
29156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
29186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);              /* Local CID */
2920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu);     /* MTU */
2921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps);     /* MPS */
2922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */
2923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
29246721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
29266721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29286721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2929ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2930ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_flow_control_credit
2931ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2932ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE packet to give credits to peer device
2933ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  for LE connection oriented L2CAP channel.
2934ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2935ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb,
2939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                            uint16_t credit_value) {
2940911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
29436721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2944911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2945911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
29466721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2948911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
29506721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
29526721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
2954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id);
2955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
29596721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
29626721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
2964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, credit_value);
29656721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
29676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29686721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29696721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2970ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2971ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_req
2972ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
29739ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send a BLE packet to disconnect LE connection
29749ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  oriented L2CAP channel.
2975ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2976ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2977ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2978ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb) {
2980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
2983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("%s", __func__);
29846721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
29876721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
29916721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
2993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ,
2994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            p_lcb->id);
2995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING(
2997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
2998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30006721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
30036721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
3005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
30066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
30086721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
30095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3011ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Functions used by both Full and Light Stack
3012ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
30135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3015ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3016ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_handle
3017ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3018ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
3019ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  HCI handle.
3020ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3021ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched LCB, or NULL if no match
3022ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3023ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3024911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) {
3025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
3026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
30275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
30315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
3035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
30365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
30375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3039ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3040ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ccb_by_cid
3041ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3042ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active CCBs on a link for a match based
3043ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on the local CID. If passed the link pointer is NULL, all
3044ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  active links are searched.
3045ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3046ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched CCB, or NULL if no match
3047ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3048ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3049911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) {
3050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = NULL;
30515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t xx;
30535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
30545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (local_cid >= L2CAP_BASE_APPL_CID) {
3056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* find the associated CCB by "index" */
3057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    local_cid -= L2CAP_BASE_APPL_CID;
30585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (local_cid >= MAX_L2CAP_CHANNELS) return NULL;
30605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.ccb_pool + local_cid;
30625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure the CCB is in use */
3064911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_ccb->in_use) {
3065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = NULL;
30665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure it's for the same LCB */
3068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3069911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = NULL;
30705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#if (L2CAP_UCD_INCLUDED == TRUE)
3073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
3074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* searching fixed channel */
3075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.ccb_pool;
3076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
3077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->local_cid == local_cid) && (p_ccb->in_use) &&
3078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_lcb == p_ccb->p_lcb))
3079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
3080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else
3081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb++;
3082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (xx >= MAX_L2CAP_CHANNELS) return NULL;
3084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
30865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb);
30885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
30895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
30915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_channel_in_rr
3095ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3096ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next channel to send on a link. It also adjusts the
3097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB queue to do a basic priority and round-robin scheduling.
3098ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3099ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB or NULL
3100ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3101ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) {
3103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_serve_ccb = NULL;
3104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
31055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i, j;
31075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* scan all of priority until finding a channel to serve */
3109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++) {
3110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* scan all channel within serving priority group until finding a channel to
3111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * serve */
3112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb);
3113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         j++) {
3114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* scaning from next serving channel */
3115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
31165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!p_ccb) {
3118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return NULL;
3120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        p_ccb->ccb_priority, p_ccb->local_cid,
3124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        fixed_queue_length(p_ccb->xmit_hold_q));
3125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* store the next serving channel */
3127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* this channel is the last channel of its priority group */
3128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->p_next_ccb == NULL) ||
3129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority)) {
3130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* next serving channel is set to the first channel in the group */
3131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb =
3132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
3134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* next serving channel is set to the next channel in the group */
3135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->chnl_state != CST_OPEN) continue;
3139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_DEBUG("%s : Connection oriented channel", __func__);
3142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
3145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* eL2CAP option in use */
3146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
31485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
31515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            /* If in eRTM mode, check for window closure */
3153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (l2c_fcr_is_flow_controlled(p_ccb)))
3155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              continue;
3156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        } else {
3158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
31595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
31615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* found a channel to serve */
3163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_serve_ccb = p_ccb;
3164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* decrease quota of its priority group */
3165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_serv[p_lcb->rr_pri].quota--;
31665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
31675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if there is no more quota of the priority group or no channel to have
3169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * data to send */
3170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* serve next priority group */
3172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* initialize its quota */
3174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_serv[p_lcb->rr_pri].quota =
3175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
31765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_serve_ccb) {
3180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_serve_ccb->ccb_priority,
3182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_serve_ccb->local_cid);
3184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
31855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return p_serve_ccb;
31875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
31885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#else  /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
31905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
31915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3192ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3193ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_channel
3194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next channel to send on a link bassed on priority
3196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  scheduling.
3197ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3198ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB or NULL
3199ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3200ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) {
3202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
32035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Get the first CCB with data to send.
3205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
3206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->chnl_state != CST_OPEN) continue;
32085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
32105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) return p_ccb;
32125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
32145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If in eRTM mode, check for window closure */
3216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (l2c_fcr_is_flow_controlled(p_ccb)))
3218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
32195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If here, we found someone */
3221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return p_ccb;
3222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
32235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return NULL;
32255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
32265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
32275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
32285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3229ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3230ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_buffer_to_send
3231ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3232ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next buffer to send on a link. It also adjusts the
3233ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB queue to do a basic priority and round-robin scheduling.
3234ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3235ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to buffer or NULL
3236ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3237ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3238911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb) {
3239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
3240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
32415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Highest priority are fixed channels */
32435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
3244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
32455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = p_lcb->p_fixed_ccbs[xx];
3248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == NULL) continue;
32495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* eL2CAP option in use */
3251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
32535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* No more checks needed if sending from the reatransmit queue */
3255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* If in eRTM mode, check for window closure */
3259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            (l2c_fcr_is_flow_controlled(p_ccb)))
3261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
3262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf != NULL) {
3266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_check_channel_congestion(p_ccb);
3267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_set_acl_hci_header(p_buf, p_ccb);
3268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (p_buf);
3269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (NULL == p_buf) {
3274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
3275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          return (NULL);
3276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
3277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* send tx complete */
3278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
3279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
3280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_check_channel_congestion(p_ccb);
3282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_set_acl_hci_header(p_buf, p_ccb);
3283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (p_buf);
3284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
32875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
32885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
32895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* get next serving channel in round-robin */
3291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_get_next_channel_in_rr(p_lcb);
32925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
3293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_get_next_channel(p_lcb);
32945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
32955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return if no buffer */
3297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) return (NULL);
32986721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Check credits */
3301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_conn_cfg.credits == 0) {
3302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
3303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return NULL;
33045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, 0);
3306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf == NULL) return (NULL);
33075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->peer_conn_cfg.credits--;
3309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf == NULL) return (NULL);
3313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (NULL == p_buf) {
3316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (NULL);
3318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
33215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb &&
3323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
3324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
33255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_check_channel_congestion(p_ccb);
33275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_set_acl_hci_header(p_buf, p_ccb);
33295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_buf);
33315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
33325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3334ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3335ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_acl_hci_header
3336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3337ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Set HCI handle for ACL packet
3338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3339ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
3340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3341ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb) {
3343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
33445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the pointer to the beginning of the data minus 4 bytes for the packet
3346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * header */
3347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
33485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
3351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                << L2CAP_PKT_TYPE_SHIFT));
3352eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh
3353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t acl_data_size =
3354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        controller_get_interface()->get_acl_data_size_ble();
3355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* The HCI transport will segment the buffers. */
3356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > acl_data_size) {
3357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, acl_data_size);
3358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_buf->len);
336084baa7f16e830394408278dbb8c508dd9fa02887Myles Watson    }
3361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3362eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_FLUSHABLE_CH_BASED) &&
3365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         (p_ccb->is_flushable)) ||
3366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         L2CAP_FLUSHABLE_PKT)) {
3368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(
3369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3373eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#else
3374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
3375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3376eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#endif
33775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t acl_data_size =
3379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        controller_get_interface()->get_acl_data_size_classic();
3380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* The HCI transport will segment the buffers. */
3381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > acl_data_size) {
3382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, acl_data_size);
3383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_buf->len);
33855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len += HCI_DATA_PREAMBLE_SIZE;
33895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
33905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_check_channel_congestion
3394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      check if any change in congestion status
3396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3397ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
3398ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3399ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
3401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
34025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
34035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
34075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the CCB queue limit is subject to a quota, check for congestion */
3409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* if this channel has outgoing traffic */
3410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->buff_quota != 0) {
3411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If this channel was congested */
3412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->cong_sent) {
3413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If the channel is not congested now, tell the app */
3414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (q_count <= (p_ccb->buff_quota / 2)) {
3415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cong_sent = false;
3416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_DEBUG(
3418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "L2CAP - Calling CongestionStatus_Cb (false), CID: 0x%04x  "
3419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "xmit_hold_q.count: %u  buff_quota: %u",
3420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_ccb->local_cid, q_count, p_ccb->buff_quota);
3421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* Prevent recursive calling */
3423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_cong_cback_context = true;
3424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
3425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                         false);
3426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_cong_cback_context = false;
3427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
3431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            L2CAP_TRACE_DEBUG(
3432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "L2CAP - Calling UCD CongestionStatus_Cb (false), "
3433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "SecPendingQ:%u,XmitQ:%u,Quota:%u",
3434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
3436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
3437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                p_ccb->p_lcb->remote_bd_addr, false);
3438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3441493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0)
3442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
3443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          uint8_t xx;
3444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
3448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->p_lcb->remote_bd_addr, false);
3449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
34505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
3453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
3454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If this channel was not congested but it is congested now, tell the app
3457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
3458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (q_count > p_ccb->buff_quota) {
3459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cong_sent = true;
3460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_DEBUG(
3462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "L2CAP - Calling CongestionStatus_Cb "
3463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "(true),CID:0x%04x,XmitQ:%u,Quota:%u",
3464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_ccb->local_cid, q_count, p_ccb->buff_quota);
3465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
3467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                         true);
34685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
34695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
3472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            L2CAP_TRACE_DEBUG(
3473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "L2CAP - Calling UCD CongestionStatus_Cb (true), "
3474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "SecPendingQ:%u,XmitQ:%u,Quota:%u",
3475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
3477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
3478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                p_ccb->p_lcb->remote_bd_addr, true);
3479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3482493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0)
3483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
3484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          uint8_t xx;
3485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
3489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->p_lcb->remote_bd_addr, true);
3490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
34915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
34935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
3495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
34965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
34985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
34995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3500494b510b9bdf5bf9bb8b74181a8f640e54e6cd40Gurpreet Ghai/*******************************************************************************
3501ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3502ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_is_ccb_active
3503ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3504ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Check if Channel Control Block is in use or released
3505ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3506ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          bool    - true if Channel Control Block is in use
3507ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                            false if p_ccb is null or is released.
3508ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3509ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_is_ccb_active(tL2C_CCB* p_ccb) { return (p_ccb && p_ccb->in_use); }
3511