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
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
43ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
448451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Function         l2cu_can_allocate_lcb
458451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
468451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Description      Look for an unused LCB
478451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
488451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Returns          true if there is space for one more lcb
498451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
508451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren ******************************************************************************/
518451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngrenbool l2cu_can_allocate_lcb(void) {
528451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren  for (int i = 0; i < MAX_L2CAP_LINKS; i++) {
538451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren    if (!l2cb.lcb_pool[i].in_use) return true;
548451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren  }
558451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren  return false;
568451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren}
578451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren
588451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren/*******************************************************************************
598451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
60ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_lcb
61ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
62ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look for an unused LCB
63ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
64ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          LCB address or NULL if none found
65ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
66ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
679e030fde05352ec4385d7baf6cc2af89e95e039cJakub PawlowskitL2C_LCB* l2cu_allocate_lcb(const RawAddress& p_bd_addr, bool is_bonding,
68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            tBT_TRANSPORT transport) {
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->in_use) {
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      alarm_free(p_lcb->l2c_lcb_timer);
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      alarm_free(p_lcb->info_resp_timer);
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memset(p_lcb, 0, sizeof(tL2C_LCB));
77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
78c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski      p_lcb->remote_bd_addr = p_bd_addr;
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->in_use = true;
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTED;
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->handle = HCI_INVALID_HANDLE;
83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_flush_tout = 0xFFFF;
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->l2c_lcb_timer = alarm_new("l2c_lcb.l2c_lcb_timer");
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->info_resp_timer = alarm_new("l2c_lcb.info_resp_timer");
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->idle_timeout = l2cb.idle_timeout;
87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->id = 1; /* spec does not allow '0' */
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->is_bonding = is_bonding;
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->transport = transport;
90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->tx_data_len =
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          controller_get_interface()->get_ble_default_data_packet_length();
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (transport == BT_TRANSPORT_LE) {
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.num_ble_links_active++;
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_ble_link_adjust_allocation();
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.num_links_active++;
99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_link_adjust_allocation();
100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1011a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#if (L2CAP_UCD_INCLUDED == TRUE)
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->ucd_out_sec_pending_q = fixed_queue_new(SIZE_MAX);
103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->ucd_in_sec_pending_q = fixed_queue_new(SIZE_MAX);
1041a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#endif
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_xmit_data_q = list_new(NULL);
106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
1075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free LCB found */
111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
116ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_update_lcb_4_bonding
117ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
118ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Mark the lcb for bonding. Used when bonding takes place on
119ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  an existing ACL connection.  (Pre-Lisbon devices)
120ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
121ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing
122ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
123ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1249e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskivoid l2cu_update_lcb_4_bonding(const RawAddress& p_bd_addr, bool is_bonding) {
125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) {
128c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    VLOG(1) << __func__ << " BDA: " << p_bd_addr
129c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski            << " is_bonding: " << is_bonding;
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->is_bonding = is_bonding;
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
136ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_lcb
137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Release an LCB. All timers will be stopped and freed,
139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  channels dropped, buffers returned etc.
140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_lcb(tL2C_LCB* p_lcb) {
145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->in_use = false;
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->is_bonding = false;
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Stop and free timers */
151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_lcb->l2c_lcb_timer);
152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->l2c_lcb_timer = NULL;
153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_lcb->info_resp_timer);
154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->info_resp_timer = NULL;
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release any unfinished L2CAP packet on this link */
157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free_and_reset((void**)&p_lcb->p_hcit_rcv_acl);
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
159d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_BR_EDR) /* Release all SCO links */
161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_remove_sco_links(p_lcb->remote_bd_addr);
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->sent_not_acked > 0) {
165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_LE) {
166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.controller_xmit_window += p_lcb->sent_not_acked;
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
17598657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach    }
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17798657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Reset BLE connecting flag only if the address matches
179c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  if (l2cb.ble_connecting_bda == p_lcb->remote_bd_addr)
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.is_ble_connecting = false;
1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_process_fixed_disc_cback(p_lcb);
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Ensure no CCBs left on this LCB */
187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       p_ccb = p_lcb->ccb_queue.p_first_ccb) {
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_ccb(p_ccb);
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Tell BTM Acl management the link was removed */
193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb->link_state == LST_CONNECTED) ||
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_DISCONNECTING))
195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport);
196ef92b534112a5df57de11ef45f5174f75d44b355Andre Eisenbach
197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release any held buffers */
198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_xmit_data_q) {
199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!list_is_empty(p_lcb->link_xmit_data_q)) {
200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BT_HDR* p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q));
201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      list_remove(p_lcb->link_xmit_data_q, p_buf);
202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
2036c303aeca25783453333172d0b29e5472f1b1c93Chris Manton    }
204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    list_free(p_lcb->link_xmit_data_q);
205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->link_xmit_data_q = NULL;
206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* clean up any security pending UCD */
210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_ucd_delete_sec_pending_q(p_lcb);
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Re-adjust flow control windows make sure it does not go negative */
214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.num_ble_links_active >= 1) l2cb.num_ble_links_active--;
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_ble_link_adjust_allocation();
218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.num_links_active >= 1) l2cb.num_links_active--;
22092ac2d8919f8e38a091903270eb5500073d67d4bMudumba Ananth
221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_link_adjust_allocation();
222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check for ping outstanding */
225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->p_echo_rsp_cb) {
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2CA_ECHO_RSP_CB* p_cb = p_lcb->p_echo_rsp_cb;
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Zero out the callback in case app immediately calls us again */
229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_echo_rsp_cb = NULL;
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_cb)(L2CAP_PING_RESULT_NO_LINK);
232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2335e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar
234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check and release all the LE COC connections waiting for security */
235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->le_sec_pending_q) {
236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      tL2CAP_SEC_DATA* p_buf =
238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (tL2CAP_SEC_DATA*)fixed_queue_try_dequeue(p_lcb->le_sec_pending_q);
239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf->p_callback)
240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport,
241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          p_buf->p_ref_data, BTM_DEV_RESET);
242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
2435e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar    }
244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->le_sec_pending_q = NULL;
246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_bd_addr
252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  remote BD address.
255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched LCB, or NULL if no match
257ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
258ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2599e030fde05352ec4385d7baf6cc2af89e95e039cJakub PawlowskitL2C_LCB* l2cu_find_lcb_by_bd_addr(const RawAddress& p_bd_addr,
260c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                                   tBT_TRANSPORT transport) {
261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && p_lcb->transport == transport &&
266c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski        (p_lcb->remote_bd_addr == p_bd_addr)) {
267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
2685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
276ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
277ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_conn_role
278ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
279ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Determine the desired role (master or slave) of a link.
280ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If already got a slave link, this one must be a master. If
2819ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  already got at least 1 link where we are the master, make
2829ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  this also a master.
283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          HCI_ROLE_MASTER or HCI_ROLE_SLAVE
285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_conn_role(tL2C_LCB* p_this_lcb) { return l2cb.desire_role; }
2885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
290ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
291ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2c_is_cmd_rejected
292ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Checks if cmd_code is command or response
294ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If a command it will be rejected per spec.
2959ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  This function is used when a illegal packet length is
2969ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  detected.
297ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
298ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          bool    - true if cmd_code is a command and it is rejected,
299ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                            false if response code. (command not rejected)
300ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
301ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t id, tL2C_LCB* p_lcb) {
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  switch (cmd_code) {
3048fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_CONN_REQ:
3058fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_CONFIG_REQ:
3068fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_DISC_REQ:
3078fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_ECHO_REQ:
3088fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_INFO_REQ:
3098fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_AMP_CONN_REQ:
3108fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_AMP_MOVE_REQ:
3118fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_BLE_UPDATE_REQ:
312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id,
313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                L2CAP_DEFAULT_MTU, 0);
314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("Dumping first Command (%d)", cmd_code);
315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return true;
3168fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    default: /* Otherwise a response */
318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3208fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta}
3218fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
3228fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/*******************************************************************************
323ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
324ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_build_header
325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Builds the L2CAP command packet header
327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
328ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to allocated packet or NULL if no resources
329ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
330ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
331911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd,
332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          uint8_t id) {
333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE);
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset = L2CAP_SEND_CMD_OFFSET;
337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len =
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
3405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in HCI header - handle + pkt boundary */
342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                          << L2CAP_PKT_TYPE_SHIFT)));
345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_lcb->handle | l2cb.non_flushable_pbf);
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
3515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len + L2CAP_CMD_OVERHEAD);
356cccf02fadb2dd4dceb22f2d58ed5840b0ef1860eChris Manton
357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_BLE_SIGNALLING_CID);
359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP command header */
364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, cmd);
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, id);
366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len);
3675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_buf);
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
372ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
373ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_adj_id
374ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Checks for valid ID based on specified mask
376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  and adjusts the id if invalid.
377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adj_id(tL2C_LCB* p_lcb, uint8_t adj_mask) {
382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->id++;
384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
388ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
389ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_cmd_reject
390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "command reject" message
392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_cmd_reject(tL2C_LCB* p_lcb, uint16_t reason, uint8_t rem_id,
398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               uint16_t p1, uint16_t p2) {
399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t param_len;
400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP packet header */
404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED)
405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 2;
406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (reason == L2CAP_CMD_REJ_INVALID_CID)
407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 4;
408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 0;
4105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_CMD_REJECT_LEN + param_len),
412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_REJECT, rem_id);
413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer cmd_rej");
415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, reason);
4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (param_len >= 2) UINT16_TO_STREAM(p, p1);
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (param_len >= 4) UINT16_TO_STREAM(p, p2);
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
431ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
432ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_connect_req
433ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
434ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection request" message
435ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
436ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
437ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
438ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
439ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_req(tL2C_CCB* p_ccb) {
441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
4475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_REQ_LEN,
451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONN_REQ, p_ccb->local_id);
452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
4625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
467ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
468ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_connect_rsp
469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection response" message
471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_rsp(tL2C_CCB* p_ccb, uint16_t result,
477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t status) {
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (result == L2CAP_CONN_PENDING) {
482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if we already sent pending response */
483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->flags & CCB_FLAG_SENT_PENDING)
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->flags |= CCB_FLAG_SENT_PENDING;
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN,
490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONN_RSP, p_ccb->remote_id);
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_rsp");
493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, status);
5035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
508ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
509ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_reject_connection
510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection response neg" message
512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer. This function is called when there is no peer
513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB (non-existant PSM or no resources).
514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
515ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
516ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
517ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid,
519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            uint8_t rem_id, uint16_t result) {
520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
5225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf =
524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id);
525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
5325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, remote_cid);
535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Status of 0      */
5375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
542ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
543ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_req
544ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
545ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration request" message
546ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
547ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
548ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
549ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
550ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t cfg_len = 0;
554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present)
563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present)
565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present)
567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present)
569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcs_present)
571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present)
573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb,
576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            (uint16_t)(L2CAP_CONFIG_REQ_LEN + cfg_len),
577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONFIG_REQ, p_ccb->local_id);
578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_cfg->flags); /* Flags (continuation) */
588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the options */
590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->mtu);
594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->flush_to);
599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.service_type);
605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.latency);
609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.mode);
615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.rtrans_tout);
618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mon_tout);
619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mps);
620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcs_present) {
623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCS);
624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCS_OPTION_LEN);
625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcs);
626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present) {
629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
6405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
643ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
644ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_rsp
645ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
646ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration response" message
647ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
648ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
649ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t cfg_len = 0;
655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present)
659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present)
661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present)
663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present)
665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present)
667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb,
670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            (uint16_t)(L2CAP_CONFIG_RSP_LEN + cfg_len),
671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id);
672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p,
682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                   p_cfg->flags); /* Flags (continuation) Must match request */
683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_cfg->result);
684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the options */
686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->mtu);
690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->flush_to);
695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.service_type);
701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.latency);
705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.mode);
711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.rtrans_tout);
714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.mon_tout);
715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mps);
716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present) {
719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
7305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
733ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
734ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_rej
735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration reject" message
737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data,
743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               uint16_t data_len, uint16_t rej_len) {
744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len, cfg_len, buf_space, len1;
745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t *p, *p_hci_len, *p_data_end;
746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t cfg_code;
7475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d",
749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    data_len, rej_len);
7508fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len1 = 0xFFFF - len;
754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (rej_len > len1) {
755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7598fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf = (BT_HDR*)osi_malloc(len + rej_len);
761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset = L2CAP_SEND_CMD_OFFSET;
762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
7635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Put in HCI header - handle + pkt boundary */
7655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures())) {
767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 << L2CAP_PKT_TYPE_SHIFT)));
769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
7705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Remember the HCI header length position, and save space for it */
777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_hci_len = p;
778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p += 2;
779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP packet header */
781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP command header */
785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, L2CAP_CMD_CONFIG_RSP);
786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, p_ccb->remote_id);
787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CONFIG_RSP_LEN + rej_len);
789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Flags = 0 (no continuation) */
792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CFG_UNKNOWN_OPTIONS);
793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  buf_space = rej_len;
795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the rejected options */
797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_data_end = p_data + data_len;
798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (p_data < p_data_end) {
799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_code = *p_data;
800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len = *(p_data + 1);
801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    switch (cfg_code & 0x7F) {
803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* skip known options */
804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_MTU:
805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_FLUSH_TOUT:
806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_QOS:
807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* unknown options; copy into rsp if not hints */
811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      default:
812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* sanity check option length */
813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if ((cfg_code & 0x80) == 0) {
815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
819911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            } else {
820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_data = p_data_end; /* force loop exit */
822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            }
824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* bad length; force loop exit */
828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_data = p_data_end;
8305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
8325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len = (uint16_t)(p - p_hci_len - 2);
836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p_hci_len, len);
8375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len = len + 4;
8395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d", len,
841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
8428fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
8445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
847ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
848ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_disc_req
849ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
850ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "disconnect request" message
851ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
852ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
853ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
854ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
855ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_req(tL2C_CCB* p_ccb) {
857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR *p_buf, *p_buf2;
858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
8595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb) || (p_ccb->p_lcb == NULL)) {
861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s L2CAP - ccb or lcb invalid", __func__);
862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
864bf955cb7e50e1047452e741effa504c8aefc8a4fvenkata Jagadeesh
865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
8685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
8705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN,
872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_DISC_REQ, p_ccb->local_id);
873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_req");
875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
8805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
8835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Move all queued data packets to the LCB. In FCR mode, assume the higher
885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     layer checks that all buffers are sent before disconnecting.
886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while ((p_buf2 = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) !=
889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           NULL) {
890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_set_acl_hci_header(p_buf2, p_ccb);
891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_check_send_pkts(p_ccb->p_lcb, p_ccb, p_buf2);
8925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
8965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
899ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
900ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_disc_rsp
901ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
902ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "disconnect response" message
903ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
904ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
905ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  This function is passed the parameters for the disconnect
906ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  response instead of the CCB address, as it may be called
907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to send a disconnect response when there is no CCB.
908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
910ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
911ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t local_cid, uint16_t remote_cid) {
914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
9165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP,
918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            remote_id);
919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_rsp");
921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
9265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, local_cid);
928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, remote_cid);
9295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
934ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
935ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_echo_req
936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "echo request" message
938ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer. Note that we do not currently allow
939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  data in the echo request.
940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
944911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_req(tL2C_LCB* p_lcb, uint8_t* p_data,
945911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t data_len) {
946911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
9485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
9515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_REQ_LEN + data_len),
953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_ECHO_REQ, p_lcb->id);
954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_req");
956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
9615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len) {
963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ARRAY_TO_STREAM(p, p_data, data_len);
964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
9675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
970ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
971ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_echo_rsp
972ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
973ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "echo response" message
974ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
975ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
976ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
977ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
978ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data,
980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t data_len) {
981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t maxlen;
984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Filter out duplicate IDs or if available buffers are low (intruder
985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * checking) */
986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!id || id == p_lcb->cur_echo_id) {
987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Dump this request since it is illegal */
988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP ignoring duplicate echo request (%d)", id);
989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->cur_echo_id = id;
992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t acl_data_size =
994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      controller_get_interface()->get_acl_data_size_classic();
995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t acl_packet_size =
996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      controller_get_interface()->get_acl_packet_size_classic();
997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Don't return data if it does not fit in ACL and L2CAP MTU */
998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size)
999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               ? acl_data_size
1000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               : (uint16_t)L2CAP_CMD_BUF_SIZE;
1001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  maxlen -=
1002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (uint16_t)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
1004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len > maxlen) data_len = 0;
1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len),
1008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_ECHO_RSP, id);
1009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_rsp");
1011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len) {
1018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ARRAY_TO_STREAM(p, p_data, data_len);
1019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
10225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1025ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1026ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_info_req
1027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1028ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "info request" message
1029ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
1030ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1031ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1032ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) {
1034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
1035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
10365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* check for wrap and/or BRCM ID */
1038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
1039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id);
1042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for info_req");
1044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_EVENT("l2cu_send_peer_info_req: type 0x%04x", info_type);
10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
10515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, info_type);
10535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->w4_info_rsp = true;
105547616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski  alarm_set_on_mloop(p_lcb->info_resp_timer, L2CAP_WAIT_INFO_RSP_TIMEOUT_MS,
105647616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski                     l2c_info_resp_timer_timeout, p_lcb);
10575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
10595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1062ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1063ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_info_rsp
1064ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1065ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "info response" message
1066ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
1067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1069ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1070ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
1072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t info_type) {
1073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
1074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
1075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len = L2CAP_INFO_RSP_LEN;
10765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.test_info_resp &
1080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)))
10845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (L2CAP_EXTFEA_SUPPORTED_MASK &
1087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
10905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
1092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id);
1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for info_rsp");
1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
11075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, info_type);
11095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.test_info_resp &
1113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)))
11155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (L2CAP_EXTFEA_SUPPORTED_MASK &
1118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
11205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
1122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_LE) {
1124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* optional data are not added for now */
1125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, L2CAP_BLE_EXTFEA_MASK);
1126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1127d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, l2cb.test_info_resp);
11295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
11305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
1131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p,
1132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
11335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, L2CAP_EXTFEA_SUPPORTED_MASK);
11355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    memset(p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
11415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
11435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION)
1145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
11465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
11485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      int xx;
1150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
1152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Skip fixed channels not used on BR/EDR-ACL link */
1153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((xx >= L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL) &&
1154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            (xx <= L2CAP_SMP_CID - L2CAP_FIRST_FIXED_CHNL))
1155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
1156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL)
1158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |=
1159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
11615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
1163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_UCD_MTU);
1166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
1168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
11725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1175ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1176ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_enqueue_ccb
1177ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1178ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      queue CCB by priority. The first CCB is highest priority and
1179ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is served at first. The CCB is queued to an LLCB or an LCB.
1180ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
1182ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1183ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_enqueue_ccb(tL2C_CCB* p_ccb) {
1185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb1;
1186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB_Q* p_q = NULL;
11875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find out which queue the channel is on
1189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
1190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
11915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb->in_use) || (p_q == NULL)) {
1193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_enqueue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x",
1195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_enqueue_ccb CID: 0x%04x  priority: %d",
1200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->local_cid, p_ccb->ccb_priority);
12015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the queue is empty, we go at the front */
1203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_q->p_first_ccb) {
1204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb1 = p_q->p_first_ccb;
1208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (p_ccb1 != NULL) {
1210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Insert new ccb at the end of the same priority. Lower number, higher
1211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * priority */
1212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Are we at the head of the queue ? */
1214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb1 == p_q->p_first_ccb)
1215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_q->p_first_ccb = p_ccb;
1216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else
1217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
12185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_next_ccb = p_ccb1;
1220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb1->p_prev_ccb = p_ccb;
1222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
1223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb1 = p_ccb1->p_next_ccb;
1226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
12275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If we are lower then anyone in the list, we go at the end */
1229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_ccb1) {
1230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* add new ccb at the end of the list */
1231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb->p_next_ccb = p_ccb;
12325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_next_ccb = NULL;
1234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_prev_ccb = p_q->p_last_ccb;
1235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb = p_ccb;
12365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Adding CCB into round robin service table of its LCB */
1241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) {
1242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if this is the first channel in this priority group */
1243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Set the first channel to this CCB */
1245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Set the next serving channel in this group to this CCB */
1247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Initialize quota of this priority group based on its priority */
1249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* increase number of channels in this group */
1253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
12565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1259ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1260ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_dequeue_ccb
1261ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1262ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      dequeue CCB from a queue
1263ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1264ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          -
1265ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1266ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_dequeue_ccb(tL2C_CCB* p_ccb) {
1268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB_Q* p_q = NULL;
12695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_dequeue_ccb  CID: 0x%04x", p_ccb->local_cid);
12715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find out which queue the channel is on
1273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
1274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
12755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL)) {
1277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_dequeue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x  p_q: "
1279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "0x%08x  p_q->p_first_ccb: 0x%08x",
1280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q,
1281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_q ? p_q->p_first_ccb : 0);
1282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Removing CCB from round robin service table of its LCB */
1287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) {
1288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* decrease number of channels in this priority group */
1289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if it was the last channel in the priority group */
1292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if it is the first channel of this group */
1297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb) {
1298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb =
1299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_next_ccb;
1300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if it is the next serving channel of this group */
1302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb) {
1303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* simply, start serving from the first channel */
1304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb =
1305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
13105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == p_q->p_first_ccb) {
1312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We are removing the first in a queue */
1313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_first_ccb = p_ccb->p_next_ccb;
13145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_q->p_first_ccb)
1316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_first_ccb->p_prev_ccb = NULL;
13175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
1318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb = NULL;
1319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (p_ccb == p_q->p_last_ccb) {
1320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We are removing the last in a queue */
1321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_last_ccb = p_ccb->p_prev_ccb;
1322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_last_ccb->p_next_ccb = NULL;
1323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* In the middle of a chain. */
1325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
13305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1333ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1334ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_change_pri_ccb
1335ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description
1337ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          -
1339ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_change_pri_ccb(tL2C_CCB* p_ccb, tL2CAP_CHNL_PRIORITY priority) {
1342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->ccb_priority != priority) {
1343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If CCB is not the only guy on the queue */
1344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL)) {
1345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("Update CCB list in logical link");
13465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Remove CCB from queue and re-queue it at new priority */
1348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_dequeue_ccb(p_ccb);
13495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ccb_priority = priority;
1351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_enqueue_ccb(p_ccb);
1352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
13535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If CCB is the only guy on the queue, no need to re-enqueue */
1356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* update only round robin service data */
1357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ccb_priority = priority;
1362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
13685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
1370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1374ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_ccb
1376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function allocates a Channel Control Block and
1378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  attaches it to a link control block. The local CID
1379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is also assigned.
1380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB, or NULL if none
1382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1383ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1384911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid) {
1385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_prev;
13875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x", cid);
13895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cb.p_free_ccb_first) return (NULL);
13915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If a CID was passed in, use that, else take the first free one */
1393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cid == 0) {
1394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.p_free_ccb_first;
1395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_prev = NULL;
13985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
14005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == l2cb.p_free_ccb_first)
1402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL;
1405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           p_prev = p_prev->p_next_ccb) {
1406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_prev->p_next_ccb == p_ccb) {
1407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_prev->p_next_ccb = p_ccb->p_next_ccb;
14085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb == l2cb.p_free_ccb_last) l2cb.p_free_ccb_last = p_prev;
14105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
1412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
1413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_prev == NULL) {
1415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR(
1416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free "
1417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "list",
1418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            cid);
1419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return NULL;
1420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->in_use = true;
1427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Get a CID for the connection */
1429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_cid = L2CAP_BASE_APPL_CID + (uint16_t)(p_ccb - l2cb.ccb_pool);
1430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb = p_lcb;
1432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_rcb = NULL;
1433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->should_free_rcb = false;
1434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) l2cu_enqueue_ccb(p_ccb);
1439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* clear what peer wants to configure */
1441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->peer_cfg_bits = 0;
1442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in default values for configuration */
1444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in default values for local/peer configurations */
1448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type =
1451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_SERV_TYPE;
1452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate =
1453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_TOKEN_RATE;
1454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size =
1455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_BUCKET_SIZE;
1456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth =
1457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_PEAK_BANDWIDTH;
1458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency =
1459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_LATENCY;
1460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation =
1461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_DELAY;
1462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->bypass_fcs = 0;
1464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->peer_cfg_already_rejected = false;
1466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->fcrb.ack_timer);
1469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.ack_timer = alarm_new("l2c_fcrb.ack_timer");
1470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /*  CSP408639 Fix: When L2CAP send amp move channel request or receive
1472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    * request -> Stop retrans/monitor timer -> Change channel state to
1474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * CST_AMP_MOVING. */
1475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->fcrb.mon_retrans_timer);
1476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.mon_retrans_timer = alarm_new("l2c_fcrb.mon_retrans_timer");
1477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.preferred_mode =
1479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.allowed_modes =
1481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */
1482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->cong_sent = false;
1495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->buff_quota = 2; /* This gets set after config */
1496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If CCB was reserved Config_Done can already have some value */
1498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cid == 0)
1499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->config_done = 0;
1500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
1501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid,
1502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_ccb->config_done);
1503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->chnl_state = CST_CLOSED;
1506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->flags = 0;
1507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
15095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = false;
15125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
15135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->l2c_ccb_timer);
1515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->l2c_ccb_timer = alarm_new("l2c.l2c_ccb_timer");
15165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_adjust_chnl_allocation();
15185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb);
15205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1523ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1524ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_start_post_bond_timer
1525ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function starts the ACL Link inactivity timer after
1527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  dedicated bonding
1528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  This timer can be longer than the normal link inactivity
1529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  timer for some platforms.
1530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
15319ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns          bool  - true if idle timer started or disconnect initiated
15329ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                          false if there's one or more pending CCB's exist
1533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_start_post_bond_timer(uint16_t handle) {
1536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
15375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) return (true);
15395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->is_bonding = false;
15415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Only start timer if no control blocks allocated */
1543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->ccb_queue.p_first_ccb != NULL) return (false);
15445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no channels on the connection, start idle timeout */
1546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb->link_state == LST_CONNECTED) ||
1547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_CONNECTING) ||
1548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_DISCONNECTING)) {
1549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    period_ms_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000;
155078bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov
1551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->idle_timeout == 0) {
1552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
1553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
1554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
15555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
155647616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski    alarm_set_on_mloop(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
155747616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski                       p_lcb);
1558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (true);
1559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (false);
15625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1565ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1566ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_ccb
1567ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1568ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function releases a Channel Control Block. The timer
15699ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  is stopped, any attached buffers freed, and the CCB is
15709ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  removed from the link control block.
1571ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1572ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1573ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1574ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_ccb(tL2C_CCB* p_ccb) {
1576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = p_ccb->p_lcb;
1577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = p_ccb->p_rcb;
15785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_release_ccb: cid 0x%04x  in_use: %u",
1580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->local_cid, p_ccb->in_use);
15815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If already released, could be race condition */
1583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb->in_use) return;
15845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_sec_clr_service_by_psm(p_rcb->psm);
1587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1588ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->should_free_rcb) {
1590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_rcb);
1591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_rcb = NULL;
1592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->should_free_rcb = false;
1593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1594a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
1595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btm_sec_clr_temp_auth_service(p_lcb->remote_bd_addr);
1596ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Free the timer */
1598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->l2c_ccb_timer);
1599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->l2c_ccb_timer = NULL;
16005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fixed_queue_free(p_ccb->xmit_hold_q, osi_free);
1602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->xmit_hold_q = NULL;
16035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_cleanup(p_ccb);
16055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Channel may not be assigned to any LCB if it was just pre-reserved */
1607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
16085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
1609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
16105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      )) {
1612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_dequeue_ccb(p_ccb);
1613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Delink the CCB from the LCB */
1615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb = NULL;
1616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put the CCB back on the free pool */
1619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cb.p_free_ccb_first) {
1620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_first = p_ccb;
1621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last = p_ccb;
1622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = NULL;
1623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb = NULL;
1624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = NULL;
1626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last = p_ccb;
1629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Flag as not in use */
1632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->in_use = false;
1633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no channels on the connection, start idle timeout */
1635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->ccb_queue.p_first_ccb) {
16377c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      // Closing a security channel on LE device should not start connection
16387c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      // timeout
16397c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      if (p_lcb->transport == BT_TRANSPORT_LE &&
16407c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski          p_ccb->local_cid == L2CAP_SMP_CID)
16417c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski        return;
16427c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski
1643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_no_dynamic_ccbs(p_lcb);
1644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1645911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Link is still active, adjust channel quotas. */
1646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_adjust_chnl_allocation();
16475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ccb_by_remote_cid
1654ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active CCBs on a link for a match based
1656ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on the remote CID.
1657ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1658ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched CCB, or NULL if no match
1659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1660ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1661911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_remote_cid(tL2C_LCB* p_lcb, uint16_t remote_cid) {
1662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
16635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If LCB is NULL, look through all active links */
1665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) {
1666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return NULL;
1667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) return (p_ccb);
1670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
16745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1677ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1678ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_rcb
1679ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1680ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the Registration Control Blocks for a free
1681ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  one.
1682ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1683ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the RCB or NULL if not found
1684ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1685ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1686911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_rcb(uint16_t psm) {
1687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
16895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_rcb->in_use) {
1692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->in_use = true;
1693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->psm = psm;
16945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
1695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
16965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_rcb);
16985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free RCB found */
1702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17056721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
1706ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1707ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_ble_rcb
1708ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1709ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the BLE Registration Control Blocks for a free
1710ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  one.
1711ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the BLE RCB or NULL if not found
1713ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1714ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1715911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm) {
1716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
17186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_rcb->in_use) {
1721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->in_use = true;
1722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->psm = psm;
17236721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#if (L2CAP_UCD_INCLUDED == TRUE)
1724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
17256721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#endif
1726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_rcb);
17276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
1728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17296721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free RCB found */
1731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17326721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
17335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_rcb
1737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Mark an RCB as no longet in use
1739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_rcb(tL2C_RCB* p_rcb) {
1744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->in_use = false;
1745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->psm = 0;
17465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1749ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1750ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_disconnect_chnl
1751ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1752ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Disconnect a channel. Typically, this is due to either
17539ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  receiving a bad configuration,  bad packet or max_retries
17549ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  expiring.
1755ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1756ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_disconnect_chnl(tL2C_CCB* p_ccb) {
1758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t local_cid = p_ccb->local_cid;
17595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (local_cid >= L2CAP_BASE_APPL_CID) {
1761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2CA_DISCONNECT_IND_CB* p_disc_cb =
1762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
17635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
17655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_send_peer_disc_req(p_ccb);
17675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_ccb(p_ccb);
17695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_disc_cb)(local_cid, false);
1771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* failure on the AMP channel, probably need to disconnect ACL */
1773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
17765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1778ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1779ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_rcb_by_psm
1780ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1781ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the Registration Control Blocks to see if
1782ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  anyone registered to handle the PSM in question
1783ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1784ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the RCB or NULL if not found
1785ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1786ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1787911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm) {
1788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
17905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17996721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
1800ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1801ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ble_rcb_by_psm
1802ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1803ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the BLE Registration Control Blocks to see if
1804ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  anyone registered to handle the PSM in question
1805ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1806ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the BLE RCB or NULL if not found
1807ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1808ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1809911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm) {
1810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
18126721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18166721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
18196721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
18205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1822ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1823ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_peer_cfg_req
1824ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
18259ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when the peer sends us a "config
18269ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  request" message. It extracts the configuration of interest
18279ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
1828ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
18299ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  Note:  Negotiation of the FCR channel type is handled
18309ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                         internally, all others are passed to the upper layer.
1831ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1832ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          uint8_t - L2CAP_PEER_CFG_OK if passed to upper layer,
18339ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                            L2CAP_PEER_CFG_UNACCEPTABLE if automatically
18349ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      responded to because parameters are
18359ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      unnacceptable from a specification point
18369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      of view.
18379ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                            L2CAP_PEER_CFG_DISCONNECT if no compatible channel
18389ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      modes between the two devices, and shall
18399ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      be closed.
1840ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1841ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool mtu_ok = true;
1844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool qos_type_ok = true;
1845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool flush_to_ok = true;
1846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool fcr_ok = true;
1847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t fcr_status;
1848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Ignore FCR parameters for basic mode */
1850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_cfg->fcr_present) p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the MTU that our peer can receive */
1853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
1854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Make sure MTU is at least the minimum */
1855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* In basic mode, limit the MTU to our buffer size */
1857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_cfg->fcr_present == false) && (p_cfg->mtu > L2CAP_MTU_SIZE))
1858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->mtu = L2CAP_MTU_SIZE;
1859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Save the accepted value in case of renegotiation */
1861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.mtu = p_cfg->mtu;
1862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.mtu_present = true;
1863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Illegal MTU value */
1865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {
1866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->mtu = L2CAP_MIN_MTU;
1867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      mtu_ok = false;
1868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload mtu from a previously accepted config request */
1871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.mtu_present) {
1872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu_present = true;
1873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu = p_ccb->peer_cfg.mtu;
1874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify that the flush timeout is a valid value (0 is illegal) */
1877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
1878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_cfg->flush_to) {
1879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      flush_to_ok = false;
1881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Save the accepted value in case of renegotiation */
1882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {
1883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.flush_to_present = true;
1884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload flush_to from a previously accepted config request */
1889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.flush_to_present) {
1890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->flush_to_present = true;
1891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the QOS settings the the peer is using */
1895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
1896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Make sure service type is not a reserved value; otherwise let upper
1897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       layer decide if acceptable
1898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    */
1899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->qos.service_type <= GUARANTEED) {
1900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.qos = p_cfg->qos;
1901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.qos_present = true;
1902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
1903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Illegal service type value */
19045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->qos.service_type = BEST_EFFORT;
1906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      qos_type_ok = false;
19075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload QOS from a previously accepted config request */
1910911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.qos_present) {
1911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos_present = true;
1912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos = p_ccb->peer_cfg.qos;
1913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fcr_status = l2c_fcr_process_peer_cfg_req(p_ccb, p_cfg);
1916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fcr_status == L2CAP_PEER_CFG_DISCONNECT) {
1917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Notify caller to disconnect the channel (incompatible modes) */
1918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
19205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_DISCONNECT);
1922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
19255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return any unacceptable parameters */
1927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
1928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_adjust_out_mps(p_ccb);
1929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_OK);
1930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
19325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (mtu_ok) p_cfg->mtu_present = false;
1934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (flush_to_ok) p_cfg->flush_to_present = false;
1935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (qos_type_ok) p_cfg->qos_present = false;
1936911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (fcr_ok) p_cfg->fcr_present = false;
19375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_UNACCEPTABLE);
1939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_peer_cfg_rsp
1945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
19469ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when the peer sends us a "config
19479ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  response" message. It extracts the configuration of interest
19489ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
1949ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1950ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1951ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we wanted QoS and the peer sends us a positive response with QoS, use
1955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * his values */
1956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->qos_present) && (p_ccb->our_cfg.qos_present))
1957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos = p_cfg->qos;
19585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
1960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Save the retransmission and monitor timeout values */
1961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
1962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
1963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
1964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
19655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Calculate the max number of packets for which we can delay sending an ack
1967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
1968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz)
1969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
1970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
1971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
19725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
1974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, "
1975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "max_held_acks: %d",
1976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz,
1977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->fcrb.max_held_acks);
1978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1982ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1983ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_our_cfg_req
1984ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1985ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when we send a "config request"
1986ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  message. It extracts the configuration of interest and saves
1987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  it in the CCB.
1988ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1989ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1991ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t hci_flush_to;
1995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the QOS settings we are using for transmit */
1997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
1998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos_present = true;
1999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos = p_cfg->qos;
2000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
2003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Override FCR options if attempting streaming or basic */
2004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE)
2005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
2007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* On BR/EDR, timer values are zero in config request */
2008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* On class 2 AMP, timer value in config request shall be non-0 processing
2009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * time */
2010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*                 timer value in config response shall be greater than
2011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * received processing time */
2012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE)
2015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
2017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Set the threshold to send acks (may be updated in the cfg response) */
2019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Include FCS option only if peer can handle it */
2022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* FCS check can be bypassed if peer also desires to bypass */
2024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS)
2025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else
2027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcs_present = false;
2028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check the flush timeout. If it is lower than the current one used */
2036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* then we need to adjust the flush timeout sent to the controller   */
2037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
2038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_cfg->flush_to == 0) ||
2039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* don't send invalid flush timeout */
2041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* SPEC: The sender of the Request shall specify its flush timeout value
2042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
2043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*       if it differs from the default value of 0xFFFF */
2044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->flush_to_present = false;
2045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
2046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb = p_ccb->p_lcb;
20485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_flush_tout = p_cfg->flush_to;
20515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* If the timeout is within range of HCI, set the flush timeout */
2053ecb6c72a1d06dbcbd0e5c07628b572c5f22a5f1dPavlin Radoslavov        if (p_cfg->flush_to <= ((HCI_MAX_AUTOMATIC_FLUSH_TIMEOUT * 5) / 8)) {
2054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* Convert flush timeout to 0.625 ms units, with round */
2055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          btsnd_hcic_write_auto_flush_tout(p_lcb->handle, hci_flush_to);
20575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
20595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2060911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
20615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2064ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2065ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_our_cfg_rsp
2066ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
20679ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when we send the peer a "config
20689ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  response" message. It extracts the configuration of interest
20699ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
2070ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2071ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2072ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2073ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
2075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If peer wants QoS, we are allowed to change the values in a positive
2076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * response */
2077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present))
2078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->peer_cfg.qos = p_cfg->qos;
2079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos_present = false;
20815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_adj_our_rsp_options(p_ccb, p_cfg);
20835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2086ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2087ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_device_reset
2088ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2089ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when reset of the device is
2090ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  completed.  For all active connection simulate HCI_DISC
2091ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2092ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_device_reset(void) {
2096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
20985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_hci_disc_comp(p_lcb->handle, (uint8_t)-1);
21025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cb.is_ble_connecting = false;
21055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_create_conn
2110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function initiates an acl connection via HCI
2112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if successful, false if get buffer fails.
2114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport) {
211796fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
211896fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  return l2cu_create_conn(p_lcb, transport, phy);
211996fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski}
212096fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski
212196fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowskibool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
212296fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski                      uint8_t initiating_phys) {
2123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
2125d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
2126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool is_sco_active;
21275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
21285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_DEVICE_TYPE dev_type;
2130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBLE_ADDR_TYPE addr_type;
21310fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
21330fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (transport == BT_TRANSPORT_LE) {
2135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!controller_get_interface()->supports_ble()) return false;
21360fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->ble_addr_type = addr_type;
2138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->transport = BT_TRANSPORT_LE;
213996fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski    p_lcb->initiating_phys = initiating_phys;
21405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (l2cble_create_conn(p_lcb));
2142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If there is a connection where we perform as a slave, try to switch roles
2145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     for this connection */
2146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       xx++, p_lcb_cur++) {
2148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb_cur == p_lcb) continue;
21495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2151d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
2152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* The LMP_switch_req shall be sent only if the ACL logical transport
2153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      is in active mode, when encryption is disabled, and all synchronous
2154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      logical transports on the same physical link are disabled." */
21555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Check if there is any SCO Active on this BD Address */
2157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
21585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_API(
2160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s",
2161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (is_sco_active == true) ? "true" : "false");
21625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (is_sco_active == true)
2164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        continue; /* No Master Slave switch not allowed when SCO Active */
21655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*4_1_TODO check  if btm_cb.devcb.local_features to be used instead */
2167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* mark this lcb waiting for switch to be completed and
2169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           start switch on the other one */
2170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_role = HCI_ROLE_MASTER;
2172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (BTM_SwitchRole(p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) ==
2174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            BTM_CMD_STARTED) {
217547616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski          alarm_set_on_mloop(p_lcb->l2c_lcb_timer,
217647616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski                             L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS,
217747616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski                             l2c_lcb_timer_timeout, p_lcb);
2178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          return (true);
21795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
21815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTING;
21855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (l2cu_create_conn_after_switch(p_lcb));
21875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2190ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2191ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_num_hi_priority
2192ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2193ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Gets the number of high priority channels.
2194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns
2196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2197ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_num_hi_priority(void) {
2199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t no_hi = 0;
2200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
22025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      no_hi++;
22065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return no_hi;
22095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
22105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2212ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2213ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_create_conn_after_switch
2214ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2215ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function initiates an acl connection via HCI
2216ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If switch required to create connection it is already done.
2217ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2218ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if successful, false if get buffer fails.
2219ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2220ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
22215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb) {
2223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_INQ_INFO* p_inq_info;
2225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t page_scan_rep_mode;
2226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t page_scan_mode;
2227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t clock_offset;
2228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p_features;
2229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t num_acl = BTM_GetNumAclLinks();
2230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_lcb->remote_bd_addr);
2231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t no_hi_prio_chs = l2cu_get_num_hi_priority();
22325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_features = BTM_ReadLocalFeatures();
22345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG(
2236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* FW team says that we can participant in 4 piconets
2239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * typically 3 piconet + 1 for scanning.
2240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * We can enhance the code to count the number of piconets later. */
2241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (((!l2cb.disallow_switch && (num_acl < 3)) ||
2242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (p_lcb->is_bonding && (no_hi_prio_chs == 0))) &&
2243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      HCI_SWITCH_SUPPORTED(p_features))
2244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
22475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTING;
22495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check with the BT manager if details about remote device are known */
2251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr);
2252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_inq_info != NULL) {
2253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_mode = p_inq_info->results.page_scan_mode;
2255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    clock_offset = (uint16_t)(p_inq_info->results.clock_offset);
2256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No info known. Use default settings */
2258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
22605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2264b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski  btsnd_hcic_create_conn(
2265b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski      p_lcb->remote_bd_addr, (HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1 |
2266b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski                              HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3 |
2267b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski                              HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5),
2268b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski      page_scan_rep_mode, page_scan_mode, clock_offset, allow_switch);
22695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btm_acl_update_busy_level(BTM_BLI_PAGE_EVT);
22715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
227247616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski  alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS,
227347616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski                     l2c_lcb_timer_timeout, p_lcb);
2274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
2276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
22775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2279ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2280ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_state
2281ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
2283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  LCB state.
2284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to first matched LCB, or NULL if no match
2286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2288911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state) {
2289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t i;
2290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
22915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
22955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
2299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
23005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2303ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2304ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_lcb_disconnecting
2305ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2306ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      On each active lcb, check if the lcb is in disconnecting
2307ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  state, or if there are no ccb's on the lcb (implying
23085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    idle timeout is running), or if last ccb on the link
23095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    is in disconnecting state.
2310ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2311ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if any of above conditions met, false otherwise
2312ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2313ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_lcb_disconnecting(void) {
2315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t i;
2318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool status = false;
23195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = &l2cb.lcb_pool[0];
23215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->in_use) {
2324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* no ccbs on lcb, or lcb is in disconnecting state */
2325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((!p_lcb->ccb_queue.p_first_ccb) ||
2326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_lcb->link_state == LST_DISCONNECTING)) {
2327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        status = true;
2328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
2329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* only one ccb left on lcb */
2331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb = p_lcb->ccb_queue.p_first_ccb;
2333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->in_use) &&
2335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          status = true;
2338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
23395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
23415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
23445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2347ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2348ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_acl_priority
2349ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets the transmission priority for a channel.
2351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  (For initial implementation only two values are valid.
2352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if a valid channel, else false
2355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
23575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23589e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskibool l2cu_set_acl_priority(const RawAddress& bd_addr, uint8_t priority,
2359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           bool reset_after_rs) {
2360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* pp;
2362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t vs_param;
23645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
23665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the link control block for the acl channel */
2368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
2369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
2370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_SetAclPriority");
2371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
2372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
23735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (BTM_IS_BRCM_CONTROLLER()) {
2375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Called from above L2CAP through API; send VSC if changed */
2376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Called because of a master/slave role switch; if high resend VSC */
2378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      pp = command;
23805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH
2382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                   : HCI_BRCM_ACL_PRIORITY_LOW;
23835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(pp, p_lcb->handle);
2385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT8_TO_STREAM(pp, vs_param);
23865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY,
2388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command,
2389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                NULL);
23905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2392624ba681a63fa5ecf778b0b019735359654c6dd0Ben YoungTae Kim
2393624ba681a63fa5ecf778b0b019735359654c6dd0Ben YoungTae Kim  /* Adjust lmp buffer allocation for this channel if priority changed */
2394624ba681a63fa5ecf778b0b019735359654c6dd0Ben YoungTae Kim  if (p_lcb->acl_priority != priority) {
2395624ba681a63fa5ecf778b0b019735359654c6dd0Ben YoungTae Kim    p_lcb->acl_priority = priority;
2396624ba681a63fa5ecf778b0b019735359654c6dd0Ben YoungTae Kim    l2c_link_adjust_allocation();
2397624ba681a63fa5ecf778b0b019735359654c6dd0Ben YoungTae Kim  }
2398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
23995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
24025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
2403ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_non_flushable_pbf
2405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_non_flushable_pbf(bool is_supported) {
2412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (is_supported)
2413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.non_flushable_pbf =
2414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
24175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
24195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2421ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2422ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_resubmit_pending_sec_req
2423ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2424ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when required security procedures
2425ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  are completed and any pending requests can be re-submitted.
2426ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2427ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2428ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2429ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
24309e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskivoid l2cu_resubmit_pending_sec_req(const RawAddress* p_bda) {
2431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_next_ccb;
2434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
24355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_resubmit_pending_sec_req  p_bda: 0x%08x", p_bda);
24375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we are called with a BDA, only resubmit for that BDA */
2439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_bda) {
2440c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    p_lcb = l2cu_find_lcb_by_bd_addr(*p_bda, BT_TRANSPORT_BR_EDR);
2441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If we don't have one, this is an error */
2443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb) {
2444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* For all channels, send the event through their FSMs */
2445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_next_ccb = p_ccb->p_next_ccb;
2447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
2450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
24515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No BDA pasesed in, so check all links */
2454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         xx++, p_lcb++) {
2456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->in_use) {
2457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* For all channels, send the event through their FSMs */
2458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_next_ccb = p_ccb->p_next_ccb;
2460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
24615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
24635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
24655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2467d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE)
24685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_info_rsp_mask
2471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function allows the script wrapper to change the
2473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  info resp mask for conformance testing.
2474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB, or NULL if none
2476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_info_rsp_mask(uint32_t mask) { l2cb.test_info_resp = mask; }
2479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif /* L2CAP_CONFORMANCE_TESTING */
24805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2482ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2483ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_adjust_out_mps
2484ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2485ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets our MPS based on current controller capabilities
2486ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2487ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2488ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2489ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adjust_out_mps(tL2C_CCB* p_ccb) {
2491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t packet_size;
2492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* on the tx side MTU is selected based on packet size of the controller */
2494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  packet_size = btm_get_max_packet_size(p_ccb->p_lcb->remote_bd_addr);
2495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* something is very wrong */
2499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
2500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_adjust_out_mps bad packet size: %u  will use MPS: %u",
2501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        packet_size, p_ccb->peer_cfg.fcr.mps);
2502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We try to negotiate MTU that each packet can be split into whole
2508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    number of max packets.  For example if link is 1.2 max packet size is 339
2509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    bytes.
2510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4
2511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    overhead.
2512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1695, that will be 5 Dh5 packets.  Now maximum L2CAP packet is
2513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1 3DH5
2516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    packet
2517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  */
2518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mps >= packet_size)
2519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
25205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
2521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
25225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
2524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_adjust_out_mps use %d   Based on peer_cfg.fcr.mps: %u  "
2525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "packet_size: %u",
2526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_initialize_fixed_ccb
2533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Initialize a fixed channel's CCB
2535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true or false
2537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid,
2540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               tL2CAP_FCR_OPTS* p_fcr) {
25415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
2542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2544911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we already have a CCB, then simply return */
2545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
2546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_ccb != NULL) && p_ccb->in_use) {
2547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /*
2548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * NOTE: The "in_use" check is needed to ignore leftover entries
2549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * that have been already released by l2cu_release_ccb().
2550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
2551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (true);
2552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_allocate_ccb(NULL, 0);
2555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) return (false);
25565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_cancel(p_lcb->l2c_lcb_timer);
2558ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
2559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set CID for the connection */
2560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_cid = fixed_cid;
2561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->remote_cid = fixed_cid;
25625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = false;
25645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_fcr) {
2566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Set the FCR parameters. For now, we will use default pools */
2567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
25685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
25735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Link ccb to lcb and lcb to ccb */
2578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb = p_lcb;
25805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* There is no configuration, so if the link is up, the channel is up */
2582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_CONNECTED) p_ccb->chnl_state = CST_OPEN;
25835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the default idle timeout value to use */
2585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fixed_chnl_idle_tout =
2586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
25875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
25895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2592ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2593ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_no_dynamic_ccbs
2594ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
25959ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Handles the case when there are no more dynamic CCBs. If
25969ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  there are any fixed CCBs, start the longest of the fixed CCB
25979ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  timeouts, otherwise start the default link idle timeout or
25989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  disconnect.
2599ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2600ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2601ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2602ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) {
2604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_STATUS rc;
2605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  period_ms_t timeout_ms = p_lcb->idle_timeout * 1000;
2606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool start_timeout = true;
26075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
2609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
26105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->p_fixed_ccbs[xx] != NULL) &&
2613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) {
2614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000;
26155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
26185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the link is pairing, do not mess with the timeouts */
2620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->is_bonding) return;
2621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (timeout_ms == 0) {
2623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
2624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (rc == BTM_CMD_STARTED) {
2628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (rc == BTM_SUCCESS) {
2632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* BTM SEC will make sure that link is release (probably after pairing is
2634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * done) */
2635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      start_timeout = false;
2637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (p_lcb->is_bonding) {
2638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
264278bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov    } else {
2643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* probably no buffer to send disconnect */
2644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = BT_1SEC_TIMEOUT_MS;
26455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (start_timeout) {
2649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %d ms", __func__, timeout_ms);
265047616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski    alarm_set_on_mloop(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
265147616530ceea2ea6432ffb35cd8a3fc0a56365b5Jakub Pawlowski                       p_lcb);
2652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_cancel(p_lcb->l2c_lcb_timer);
2654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
26565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
26585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2660ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_fixed_chnl_resp
2661ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2662ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      handle a fixed channel response (or lack thereof)
2663ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  if the link failed, or a fixed channel response was
2664ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  not received, the bitfield is all zeros.
2665ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2666ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb) {
2668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* ignore all not assigned BR/EDR channels */
2670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->peer_chnl_mask[0] &=
2671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_FIXED_CHNL_SIG_BIT | L2CAP_FIXED_CHNL_CNCTLESS_BIT |
2672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         L2CAP_FIXED_CHNL_SMP_BR_BIT);
2673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
2674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Tell all registered fixed channels about the connection */
2677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* skip sending LE fix channel callbacks on BR/EDR links */
2679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID)
2682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
2683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] &
2685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->p_fixed_ccbs[xx])
2687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 p_lcb->remote_bd_addr, true, 0,
2690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 p_lcb->transport);
2691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
2692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->disc_reason, p_lcb->transport);
2695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->p_fixed_ccbs[xx]) {
2697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
2698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[xx] = NULL;
26995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
27015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
27045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
27055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27068fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/*******************************************************************************
2707ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2708ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_fixed_disc_cback
2709ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
27109ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      send l2cap fixed channel disconnection callback to the
27119ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  application
2712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2713ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2714ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2715ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb) {
27178fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#if (L2CAP_NUM_FIXED_CHNLS > 0)
27188fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
2719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Select peer channels mask to use depending on transport */
2720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t peer_channel_mask = p_lcb->peer_chnl_mask[0];
2721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // For LE, reset the stored peer channel mask
2723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) p_lcb->peer_chnl_mask[0] = 0;
2724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->p_fixed_ccbs[xx]) {
2727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        tL2C_CCB* p_l2c_chnl_ctrl_block;
2729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->p_fixed_ccbs[xx] = NULL;
2731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->disc_reason, p_lcb->transport);
2735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2736911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if ((peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL))) &&
2737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL))
2738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->disc_reason, p_lcb->transport);
2741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27428fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#endif
27438fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta}
27448fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
27455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2746ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2747ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_par_req
2748ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2749ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE parameter update request message
2750ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
2751ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2752ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2753ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2754ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int,
2756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t max_int, uint16_t latency,
2757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t timeout) {
2758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
27605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
2763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
27645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id);
2767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_req - no buffer");
2769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
27745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, min_int);
2776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, max_int);
2777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, latency);
2778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, timeout);
27795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
27815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
27825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2784ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2785ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_par_rsp
2786ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2787ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE parameter update response message
2788ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
2789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2790ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2791ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2792ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason,
2794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint8_t rem_id) {
2795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
27975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_UPDATE_RSP, rem_id);
2800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_rsp - no buffer");
2802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, reason);
28095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
28115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
28125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
28136721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2814ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2815ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_req
2816ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28179ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send a BLE packet to establish LE connection
28189ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  oriented L2CAP channel.
2819ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2820ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2821ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2822ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb) {
2824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
2827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t mtu;
2828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t mps;
2829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t initial_credit;
28306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
28336721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
28376721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
28396721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id);
2842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28466721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28496721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  mtu = p_ccb->local_conn_cfg.mtu;
2851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  mps = p_ccb->local_conn_cfg.mps;
2852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  initial_credit = p_ccb->local_conn_cfg.credits;
28536721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG(
2855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                mtu:%d mps:%d initial_credit:%d",
2857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_rcb->real_psm, p_ccb->local_cid, mtu, mps, initial_credit);
28586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
2860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
2861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, mtu);
2862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, mps);
2863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, initial_credit);
28646721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
28666721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
28676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
28686721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2869ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2870ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_reject_ble_connection
2871ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send an L2CAP "Credit based connection res"
28739ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  message to the peer. This function is called for non-success
28749ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  cases.
2875ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2876ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2877ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2878ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_ble_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
2880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t result) {
2881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
28836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id);
2886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_reject_ble_connection - no buffer");
2888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28906721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28936721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
2895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* MTU */
2896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* MPS */
2897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* initial credit */
2898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
28996721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
29016721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29036721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2904ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2905ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_res
2906ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
29079ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send an L2CAP "Credit based connection res"
29089ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  message to the peer. This function is called in case of
29099ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  success.
2910ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2911ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2912ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2913ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb,
2915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                              uint16_t result) {
2916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
29186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_send_peer_ble_credit_based_conn_res");
2920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf =
2921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id);
2923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
2925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
29276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
29306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);              /* Local CID */
2932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu);     /* MTU */
2933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps);     /* MPS */
2934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */
2935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
29366721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
29386721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29396721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29406721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_flow_control_credit
2943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE packet to give credits to peer device
2945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  for LE connection oriented L2CAP channel.
2946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2948ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2949ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb,
2951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                            uint16_t credit_value) {
2952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
29556721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
29586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
29626721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
29646721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
2966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id);
2967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
29716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
29746721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
2976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, credit_value);
29776721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
29796721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29806721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29816721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2982ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2983ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_req
2984ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
29859ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send a BLE packet to disconnect LE connection
29869ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  oriented L2CAP channel.
2987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2988ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2989ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb) {
2992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
2995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("%s", __func__);
29966721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
29996721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
3001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
3002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
30036721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
3005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ,
3006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            p_lcb->id);
3007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
3008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING(
3009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
3011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30126721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
30156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
3017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
30186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
30206721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
30215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3023ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Functions used by both Full and Light Stack
3024ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
30255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3028ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_handle
3029ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3030ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
3031ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  HCI handle.
3032ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3033ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched LCB, or NULL if no match
3034ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3035ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3036911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) {
3037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
3038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
30395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
30435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
3047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
30485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
30495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3051ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3052ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ccb_by_cid
3053ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active CCBs on a link for a match based
3055ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on the local CID. If passed the link pointer is NULL, all
3056ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  active links are searched.
3057ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3058ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched CCB, or NULL if no match
3059ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3060ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3061911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) {
3062911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = NULL;
30635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3064911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t xx;
30655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
30665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (local_cid >= L2CAP_BASE_APPL_CID) {
3068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* find the associated CCB by "index" */
3069911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    local_cid -= L2CAP_BASE_APPL_CID;
30705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (local_cid >= MAX_L2CAP_CHANNELS) return NULL;
30725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.ccb_pool + local_cid;
30745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure the CCB is in use */
3076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_ccb->in_use) {
3077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = NULL;
30785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure it's for the same LCB */
3080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = NULL;
30825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#if (L2CAP_UCD_INCLUDED == TRUE)
3085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
3086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* searching fixed channel */
3087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.ccb_pool;
3088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
3089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->local_cid == local_cid) && (p_ccb->in_use) &&
3090911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_lcb == p_ccb->p_lcb))
3091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
3092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else
3093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb++;
3094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (xx >= MAX_L2CAP_CHANNELS) return NULL;
3096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
30985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb);
31005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
31015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
31025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
31035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
31045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3105ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3106ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_channel_in_rr
3107ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next channel to send on a link. It also adjusts the
3109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB queue to do a basic priority and round-robin scheduling.
3110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB or NULL
3112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) {
3115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_serve_ccb = NULL;
3116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
31175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i, j;
31195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* scan all of priority until finding a channel to serve */
3121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++) {
3122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* scan all channel within serving priority group until finding a channel to
3123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * serve */
3124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb);
3125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         j++) {
3126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* scaning from next serving channel */
3127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
31285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!p_ccb) {
3130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return NULL;
3132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        p_ccb->ccb_priority, p_ccb->local_cid,
3136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        fixed_queue_length(p_ccb->xmit_hold_q));
3137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* store the next serving channel */
3139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* this channel is the last channel of its priority group */
3140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->p_next_ccb == NULL) ||
3141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority)) {
3142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* next serving channel is set to the first channel in the group */
3143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb =
3144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
3146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* next serving channel is set to the next channel in the group */
3147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->chnl_state != CST_OPEN) continue;
3151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_DEBUG("%s : Connection oriented channel", __func__);
3154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
3157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* eL2CAP option in use */
3158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
31605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
31635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            /* If in eRTM mode, check for window closure */
3165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (l2c_fcr_is_flow_controlled(p_ccb)))
3167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              continue;
3168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        } else {
3170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
31715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
31735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* found a channel to serve */
3175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_serve_ccb = p_ccb;
3176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* decrease quota of its priority group */
3177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_serv[p_lcb->rr_pri].quota--;
31785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
31795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if there is no more quota of the priority group or no channel to have
3181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * data to send */
3182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* serve next priority group */
3184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* initialize its quota */
3186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_serv[p_lcb->rr_pri].quota =
3187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
31885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_serve_ccb) {
3192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_serve_ccb->ccb_priority,
3194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_serve_ccb->local_cid);
3196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
31975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return p_serve_ccb;
31995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
32005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#else  /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
32025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
32035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_channel
3206ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3207ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next channel to send on a link bassed on priority
3208ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  scheduling.
3209ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3210ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB or NULL
3211ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3212ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) {
3214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
32155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Get the first CCB with data to send.
3217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
3218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->chnl_state != CST_OPEN) continue;
32205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
32225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) return p_ccb;
32245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
32265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If in eRTM mode, check for window closure */
3228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (l2c_fcr_is_flow_controlled(p_ccb)))
3230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
32315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If here, we found someone */
3233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return p_ccb;
3234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
32355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return NULL;
32375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
32385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
32395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
324035e95c989923880e838741d52035c065c043921dYamei Duvoid l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
3241c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  if (p_cbi->cb != NULL) p_cbi->cb(p_cbi->local_cid, p_cbi->num_sdu);
324235e95c989923880e838741d52035c065c043921dYamei Du}
324335e95c989923880e838741d52035c065c043921dYamei Du
32445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3245ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3246ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_buffer_to_send
3247ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next buffer to send on a link. It also adjusts the
3249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB queue to do a basic priority and round-robin scheduling.
3250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to buffer or NULL
3252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3254c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskiBT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
3255c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                                     tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
3256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
3257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
32585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Highest priority are fixed channels */
32605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
3261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
32625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
326335e95c989923880e838741d52035c065c043921dYamei Du  p_cbi->cb = NULL;
326435e95c989923880e838741d52035c065c043921dYamei Du
3265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = p_lcb->p_fixed_ccbs[xx];
3267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == NULL) continue;
32685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* eL2CAP option in use */
3270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
32725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* No more checks needed if sending from the reatransmit queue */
3274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* If in eRTM mode, check for window closure */
3278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            (l2c_fcr_is_flow_controlled(p_ccb)))
3280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
3281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf != NULL) {
3285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_check_channel_congestion(p_ccb);
3286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_set_acl_hci_header(p_buf, p_ccb);
3287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (p_buf);
3288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (NULL == p_buf) {
329335e95c989923880e838741d52035c065c043921dYamei Du          L2CAP_TRACE_ERROR("%s: No data to be sent", __func__);
3294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          return (NULL);
3295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
329635e95c989923880e838741d52035c065c043921dYamei Du
329735e95c989923880e838741d52035c065c043921dYamei Du        /* Prepare callback info for TX completion */
329835e95c989923880e838741d52035c065c043921dYamei Du        p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb;
329935e95c989923880e838741d52035c065c043921dYamei Du        p_cbi->local_cid = p_ccb->local_cid;
330035e95c989923880e838741d52035c065c043921dYamei Du        p_cbi->num_sdu = 1;
3301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_check_channel_congestion(p_ccb);
3303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_set_acl_hci_header(p_buf, p_ccb);
3304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (p_buf);
3305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
33085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
33095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* get next serving channel in round-robin */
3312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_get_next_channel_in_rr(p_lcb);
33135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
3314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_get_next_channel(p_lcb);
33155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
33165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return if no buffer */
3318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) return (NULL);
33196721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Check credits */
3322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_conn_cfg.credits == 0) {
3323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
3324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return NULL;
33255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, 0);
3327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf == NULL) return (NULL);
33285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->peer_conn_cfg.credits--;
3330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf == NULL) return (NULL);
3334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (NULL == p_buf) {
3337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (NULL);
3339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
33425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb &&
3344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
3345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
33465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_check_channel_congestion(p_ccb);
33485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_set_acl_hci_header(p_buf, p_ccb);
33505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_buf);
33525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
33535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_acl_hci_header
3357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Set HCI handle for ACL packet
3359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
3361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb) {
3364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
33655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the pointer to the beginning of the data minus 4 bytes for the packet
3367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * header */
3368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
33695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
3372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                << L2CAP_PKT_TYPE_SHIFT));
3373eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh
3374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t acl_data_size =
3375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        controller_get_interface()->get_acl_data_size_ble();
3376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* The HCI transport will segment the buffers. */
3377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > acl_data_size) {
3378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, acl_data_size);
3379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_buf->len);
338184baa7f16e830394408278dbb8c508dd9fa02887Myles Watson    }
3382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3383eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_FLUSHABLE_CH_BASED) &&
3386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         (p_ccb->is_flushable)) ||
3387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         L2CAP_FLUSHABLE_PKT)) {
3389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(
3390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3394eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#else
3395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
3396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3397eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#endif
33985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t acl_data_size =
3400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        controller_get_interface()->get_acl_data_size_classic();
3401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* The HCI transport will segment the buffers. */
3402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > acl_data_size) {
3403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, acl_data_size);
3404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_buf->len);
34065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len += HCI_DATA_PREAMBLE_SIZE;
34105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
34115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
34125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3413ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3414ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_check_channel_congestion
3415ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      check if any change in congestion status
3417ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3418ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
3419ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3420ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
3422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
34235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
34245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
34285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the CCB queue limit is subject to a quota, check for congestion */
3430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* if this channel has outgoing traffic */
3431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->buff_quota != 0) {
3432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If this channel was congested */
3433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->cong_sent) {
3434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If the channel is not congested now, tell the app */
3435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (q_count <= (p_ccb->buff_quota / 2)) {
3436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cong_sent = false;
3437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_DEBUG(
3439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "L2CAP - Calling CongestionStatus_Cb (false), CID: 0x%04x  "
3440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "xmit_hold_q.count: %u  buff_quota: %u",
3441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_ccb->local_cid, q_count, p_ccb->buff_quota);
3442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* Prevent recursive calling */
3444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_cong_cback_context = true;
3445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
3446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                         false);
3447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_cong_cback_context = false;
3448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
3452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            L2CAP_TRACE_DEBUG(
3453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "L2CAP - Calling UCD CongestionStatus_Cb (false), "
3454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "SecPendingQ:%u,XmitQ:%u,Quota:%u",
3455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
3457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
3458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                p_ccb->p_lcb->remote_bd_addr, false);
3459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3462493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0)
3463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
3464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          uint8_t xx;
3465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
3469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->p_lcb->remote_bd_addr, false);
3470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
34715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
3474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
3475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If this channel was not congested but it is congested now, tell the app
3478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
3479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (q_count > p_ccb->buff_quota) {
3480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cong_sent = true;
3481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_DEBUG(
3483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "L2CAP - Calling CongestionStatus_Cb "
3484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "(true),CID:0x%04x,XmitQ:%u,Quota:%u",
3485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_ccb->local_cid, q_count, p_ccb->buff_quota);
3486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
3488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                         true);
34895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
34905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
3493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            L2CAP_TRACE_DEBUG(
3494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "L2CAP - Calling UCD CongestionStatus_Cb (true), "
3495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "SecPendingQ:%u,XmitQ:%u,Quota:%u",
3496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
3498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
3499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                p_ccb->p_lcb->remote_bd_addr, true);
3500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
35025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3503493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0)
3504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
3505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          uint8_t xx;
3506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
3510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->p_lcb->remote_bd_addr, true);
3511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
35125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
35145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
3516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
35175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
35195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
35205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3521494b510b9bdf5bf9bb8b74181a8f640e54e6cd40Gurpreet Ghai/*******************************************************************************
3522ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3523ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_is_ccb_active
3524ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3525ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Check if Channel Control Block is in use or released
3526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          bool    - true if Channel Control Block is in use
3528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                            false if p_ccb is null or is released.
3529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_is_ccb_active(tL2C_CCB* p_ccb) { return (p_ccb && p_ccb->in_use); }
3532